OpenNext takes the Next.js build output and converts it into a package that can be deployed to any functions as a service platform.
OpenNext aims to support all Next.js 13 features. Some features are work in progress. Please open a new issue to let us know!
- API routes
- Dynamic routes
- Static site generation (SSG)
- Server-side rendering (SSR)
- Incremental static regeneration (ISR)
- Middleware
- Image optimization (work in progress)
-
Naviate to your Next.js app
cd my-next-app
-
Build the app
npx open-next@latest build
This will generate an
.open-next
directory with the following bundles:my-next-app/ .open-next/ assets/ -> Static assets to upload to an S3 Bucket server-function/ -> Handler code for server Lambda Function middleware-function/ -> Handler code for middleware Lambda@Edge Function
OpenNext does not create the underlying infrastructure. You can create the infrastructure for your app with your preferred tool — SST, CDK, Serverless Framework, Terraform, etc.
This is the recommended setup.
A few AWS resources need to be created:
- An S3 bucket to host static assets from
.open-next/assets
. - A Lambda function handling server and API requests.
- A Lambda function handling image optimization requests.
- A CloudFront distribution that routes incoming requests based on URL path.
- And finally a Lambda@Edge function that runs the middleware before requests hit the CloudFront.
When you call npx open-next build
, behind the scenes OpenNext builds your Next.js app using the @vercel/next
package. This package does 2 things:
-
It calls
next build
with theminimalMode
flag. This flag disables running middleware in the server code. -
Instead, it bundles the middleware separately. This allows us to deploy middleware to edge locations.
Then open-next
transforms @vercel/next
's build output into a format that can be deployed to AWS. The following steps are performed:
-
Creates a
.open-next
directory in the user's Next.js app. -
Bundles the middleware handler with the middleware adapter. And outputs the handler file into
.open-next/middleware-function
. -
Bundles the server handler with the server adapter. And outputs the handler file into
.open-next/server-function
. Also copies over other server assets from.next/standalone
. -
Bundles the static assets into
.open-next/assets
with the following content:
public
.next/BUILD_ID
.next/static
In the example
folder, you can find a Next.js feature test app. Here's a link deployed using SST's NextjsSite
construct. It contains a handful of pages. Each page aims to test a single Next.js feature.
You can find the server log in the AWS CloudWatch console of the region you deployed to.
You can find the middleware log in the AWS CloudWatch console of the region you are physically close to. For example, if you deployed your app to us-east-1
and you are in London, it's likely you will find the logs in eu-west-2
.
Create a PR and add a new page to the benchmark app in example
with the issue.
The next build
command generates a server function that runs the middleware. With this setup, if you use middleware for static pages, these pages cannot be cached. If cached, CDN (CloudFront) will send back the cached response without calling the origin (server Lambda function). To ensure the middleware is invoked on every request, caching is always disabled.
Vercel deploys the middleware code to edge functions, which gets invoked before the request reaches the CDN. This way, static pages can be cached. On request, the middleware gets called, and then the CDN can send back the cached response.
OpenNext is designed to adopt the same setup as Vercel. And building using @vercel/next
allows us to separate the middleware code from the server code.
Maintained by SST. Join our community: Discord | YouTube | Twitter