|
| 1 | +<p align="center"> |
| 2 | + <a href="https://sst.dev/discord"><img alt="Discord" src="https://img.shields.io/discord/983865673656705025?style=flat-square" /></a> |
| 3 | + <a href="https://www.npmjs.com/package/open-next"><img alt="npm" src="https://img.shields.io/npm/v/open-next.svg?style=flat-square" /></a> |
| 4 | +</p> |
| 5 | + |
1 | 6 | # OpenNext
|
2 | 7 |
|
3 | 8 | OpenNext takes the Next.js build output and converts it into a package that can be deployed to any functions as a service platform.
|
4 | 9 |
|
5 |
| -It supports all Next.js 13 features including, SSG, ISR, SSR, Image Optimization, and Middleware. |
| 10 | +## Features |
| 11 | + |
| 12 | +OpenNext aims to support all Next.js 13 features. Some features are work in progress. Please open a [new issue](/issues/new) to let us know! |
| 13 | + |
| 14 | +[x] API routes |
| 15 | +[x] Dynamic routes |
| 16 | +[x] Static site generation (SSG) |
| 17 | +[x] Server-side rendering (SSR) |
| 18 | +[x] Incremental static regeneration (ISR) |
| 19 | +[] Image optimization (work in progress) |
| 20 | +[] Middleware (work in progress) |
| 21 | + |
| 22 | +## Quick start |
| 23 | + |
| 24 | +Naviate to your Next.js app |
| 25 | + |
| 26 | +```bash |
| 27 | +cd my-next-app |
| 28 | +``` |
| 29 | + |
| 30 | +Build app |
| 31 | + |
| 32 | +```bash |
| 33 | +npx open-next build |
| 34 | +``` |
| 35 | + |
| 36 | +This will generate an `.open-next` directory with the following bundles: |
| 37 | + |
| 38 | +```bash |
| 39 | +my-next-app/ |
| 40 | + .open-next/ |
| 41 | + assets/ -> Static assets to upload to an S3 Bucket |
| 42 | + server-function/ -> Handler code for server Lambda Function |
| 43 | + middleware-function/ -> Handler code for middleware Lambda@Edge Function |
| 44 | +``` |
| 45 | + |
| 46 | +## Recommeded infrastructure |
| 47 | + |
| 48 | +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. |
| 49 | + |
| 50 | +This is the recommended setup. |
| 51 | + |
| 52 | +<p align="center"> |
| 53 | + <img alt="Architecture" src="/readme/architecture.png" width="600" /> |
| 54 | +</p> |
| 55 | + |
| 56 | +A few AWS resources are created: |
| 57 | + |
| 58 | +- An S3 bucket to host static assets from `.open-next/assets`. |
| 59 | +- A Lambda function handling server and API requests. |
| 60 | +- A Lambda function handling image optimization requests. |
| 61 | +- A CloudFront distribution that routes incoming requests based on URL path. |
| 62 | +- And finally a Lambda@Edge function that runs the middleware before requests hit the CloudFront. |
| 63 | + |
| 64 | +## How does OpenNext work? |
| 65 | + |
| 66 | +When you call `npx open-next build`, behind the scene OpenNext builds your Next.js app using the `@vercel/next` package. This package does 2 things: |
| 67 | + |
| 68 | +- It calls `next build` with the [`minimalMode`](https://github.com/vercel/next.js/discussions/29801) flag. This flag disables running middleware in the server code. |
| 69 | + |
| 70 | +- Instead, it bundles the middleware separately. This allows us to deploy middleware to edge locations. |
| 71 | + |
| 72 | +Then `open-next` transforms `@vercel/next`'s build output into a format that can be deployed to AWS. The following steps are performed: |
| 73 | + |
| 74 | +1. Creates a `.open-next` directory in user's Next.js app. |
| 75 | + |
| 76 | +1. Bundles the middleware handler with the [middleware adapter](/cli/assets/middleware-adapter.js). And outputs the handler file into `.open-next/middleware-function`. |
| 77 | + |
| 78 | +1. Bundles the server handler with the [server adapter](/cli/assets/server-adapter.cjs). And outputs the handler file into `.open-next/server-function`. Also copies over other server assets from `.next/standalone`. |
| 79 | + |
| 80 | +1. Bundles the static assets into `.open-next/assets` with the following content: |
| 81 | + |
| 82 | +- `public` |
| 83 | +- `.next/BUILD_ID` |
| 84 | +- `.next/static` |
| 85 | + |
| 86 | +## Example |
| 87 | + |
| 88 | +In the `example` folder, you can find a benchmark Next.js app. Here is a link deployed using SST's [`NextjsSite`](https://docs.sst.dev/constructs/NextjsSite) construct. It contains a handful of pages. Each page aims to test a single Next.js feature. |
| 89 | + |
| 90 | +## Opening an issue |
| 91 | + |
| 92 | +Create a PR and add a new page to the benchmark app in `example` with the issue. |
| 93 | + |
| 94 | +### Debugging |
| 95 | + |
| 96 | +You can find the server log in the AWS CloudWatch console of the **region you deployed to**. |
| 97 | + |
| 98 | +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`. |
| 99 | + |
| 100 | +## FAQ |
| 101 | + |
| 102 | +#### Why use the `@vercel/next` package for building the Next.js app? |
| 103 | + |
| 104 | +`next build` generates a server function that runs middleware. With this setup, if you use middleware for static pages, these pages cannot be cached. If cached, CDN (CloudFront) will send back cached response without calling the origin (server Lambda function). To ensure the middleware is invoked on every request, caching is always disabled. |
| 105 | + |
| 106 | +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, middleware gets called, and then the CDK can send back cached response. |
| 107 | + |
| 108 | +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. |
0 commit comments