You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+102-9Lines changed: 102 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -63,6 +63,12 @@ OpenNext aims to support all Next.js 13 features. Some features are work in prog
63
63
64
64
If your Next.js app does not use [middleware](https://nextjs.org/docs/advanced-features/middleware), `middleware-function` will not be generated.
65
65
66
+
3. Add `.open-next` to your `.gitignore` file
67
+
```
68
+
# OpenNext
69
+
/.open-next/
70
+
```
71
+
66
72
## How does OpenNext work?
67
73
68
74
When calling `open-next build`, OpenNext **builds the Next.js app** using the `@vercel/next` package. And then it **transforms the build output** to a format that can be deployed to AWS.
Create a Lambda function with the code from `.open-next/image-optimization-function`.
120
+
Create a Lambda function with the code from `.open-next/image-optimization-function`, and the handler is `index.mjs`.
115
121
116
122
This function handles image optimization requests when the Next.js `<Image>` component is used. The [sharp](https://www.npmjs.com/package/sharp) library is bundled with the function. And it is used to convert the image.
117
123
118
124
Note that image optimization function responds with the `Cache-Control` header, and the image will be cached both at the CDN level and at the browser level.
119
125
120
126
#### Server Lambda function
121
127
122
-
Create a Lambda function with the code from `.open-next/server-function`.
128
+
Create a Lambda function with the code from `.open-next/server-function`, and the handler is `index.mjs`.
129
+
130
+
This function handles all the other types of requests from the Next.js app, including Server-side Rendering (SSR) requests and API requests. OpenNext builds the Next.js app in the **standalone** mode. The standalone mode generates a `.next` folder containing the **NextServer** class that does the request handling. It also generates a `node_modules` folder with **all the dependencies** required to run the `NextServer`.
131
+
132
+
```
133
+
.next/ -> NextServer
134
+
node_modules/ -> dependencies
135
+
```
136
+
137
+
The server function adapter wraps around `NextServer` and exports a handler function that supports the Lambda request and response. The `server-function` bundle looks like:
138
+
139
+
```diff
140
+
.next/ -> NextServer
141
+
node_modules/ -> dependencies
142
+
+ index.mjs -> server function adapter
143
+
```
144
+
145
+
**Monorepo**
146
+
The build output looks slightly different when the Next.js app is part of a monorepo. Imagine the app sits inside `packages/web`, the build output looks like:
147
+
148
+
```
149
+
packages/
150
+
web/
151
+
.next/ -> NextServer
152
+
node_modules/ -> dependencies from root node_modules (optional)
153
+
node_modules/ -> dependencies from package node_modules
154
+
```
123
155
124
-
This function handles all the other types of requests from the Next.js app, including Server-side Rendering (SSR) requests and API requests. OpenNext builds the Next.js app in the **standalone** mode. The standalone mode generates a **NextServer** class that does the request handling. And the server function wraps around the NextServer.
156
+
In this case, the server function adapter needs to be created inside `packages/web` next to `.next/`. This is to ensure the adapter can import dependencies from both `node_modules` folders. We could set the Lambda handler to point to `packages/web/index.mjs`, but it is a bad practice to have the Lambda configuration coupled with the project structure. Instead, we will add a wrapper `index.mjs` at the `server-function` bundle root that re-exports the adapter.
157
+
158
+
```diff
159
+
packages/
160
+
web/
161
+
.next/ -> NextServer
162
+
node_modules/ -> dependencies from root node_modules (optional)
163
+
+ index.mjs -> server function adapter
164
+
node_modules/ -> dependencies from package node_modules
165
+
+ index.mjs -> adapter wrapper
166
+
```
167
+
168
+
This ensure the Lambda handler remains at `index.mjs`.
125
169
126
170
#### CloudFront distribution
127
171
@@ -137,7 +181,7 @@ Create a CloudFront distribution, and dispatch requests to their cooresponding h
137
181
138
182
#### Middleware Lambda@Edge function (optional)
139
183
140
-
Create a Lambda function with the code from `.open-next/middleware-function`, and attach it to the `/_next/data/*` and `/*` behaviors as `viewer request` edge function. This allows the function to run your [Middleware](https://nextjs.org/docs/advanced-features/middleware) code before the request hits your server function, and also before cached content.
184
+
Create a Lambda function with the code from `.open-next/middleware-function`, and the handler is `index.mjs`. Attach it to the `/_next/data/*` and `/*` behaviors as `viewer request` edge function. This allows the function to run your [Middleware](https://nextjs.org/docs/advanced-features/middleware) code before the request hits your server function, and also before cached content.
141
185
142
186
The middleware function uses the Node.js 18 [global fetch API](https://nodejs.org/de/blog/announcements/v18-release-announce/#new-globally-available-browser-compatible-apis). It requires to run on Node.js 18 runtime. [See why Node.js 18 runtime is required.](#workaround-add-headersgetall-extension-to-the-middleware-function)
143
187
@@ -169,6 +213,55 @@ To workaround the issue, the server function checks if the request is to an HTML
#### WORKAROUND: Set `NextServer` working directory (AWS specific)
217
+
218
+
Next.js recommends using `process.cwd()` instead of `__dirname` to get the app directory. Imagine you have a `posts` folder in your app with markdown files:
219
+
220
+
```
221
+
pages/
222
+
posts/
223
+
my-post.md
224
+
public/
225
+
next.config.js
226
+
package.json
227
+
```
228
+
229
+
And you can build the file path like this:
230
+
231
+
```ts
232
+
path.join(process.cwd(), "posts", "my-post.md");
233
+
```
234
+
235
+
Recall in the [Server function](#server-lambda-function) section. In a non-monorepo setup, the `server-function` bundle looks like:
236
+
237
+
```
238
+
.next/
239
+
node_modules/
240
+
posts/
241
+
my-post.md <- path is "posts/my-post.md"
242
+
index.mjs
243
+
```
244
+
245
+
And `path.join(process.cwd(), "posts", "my-post.md")` resolves to the correct path.
246
+
247
+
However, when the user's app is inside a monorepo (ie. at `/packages/web`), the `server-function` bundle looks like:
248
+
249
+
```
250
+
packages/
251
+
web/
252
+
.next/
253
+
node_modules/
254
+
posts/
255
+
my-post.md <- path is "packages/web/posts/my-post.md"
256
+
index.mjs
257
+
node_modules/
258
+
index.mjs
259
+
```
260
+
261
+
And `path.join(process.cwd(), "posts", "my-post.md")` cannot be resolved.
262
+
263
+
To workaround the issue, we change the working directory for the server function to where `.next/` is located, ie. `packages/web`.
264
+
172
265
#### WORKAROUND: Pass headers from middleware function to server function (AWS specific)
173
266
174
267
[Middleware](https://nextjs.org/docs/advanced-features/middleware) allows you to modify the request and response headers. This requires the middleware function to be able to pass custom headers defined in your Next.js app's middleware code to the server function.
@@ -210,22 +303,22 @@ To run `OpenNext` locally:
210
303
1. Build `open-next`
211
304
```bash
212
305
cd open-next
213
-
yarn build
306
+
pnpm build
214
307
```
215
308
1. Run `open-next` in watch mode
216
309
```bash
217
-
yarn dev
310
+
pnpm dev
218
311
```
219
312
1. Make `open-next` linkable from your Next.js app
220
313
```bash
221
-
yarn link
314
+
pnpm link --global
222
315
```
223
316
1. Link `open-next` in your Next.js app
224
317
```bash
225
318
cd path/to/my/nextjs/app
226
-
yarn link open-next
319
+
pnpm link --global open-next
227
320
```
228
-
Now you can make changes in `open-next`, and run `yarn open-next build` in your Next.js app to test the changes.
321
+
Now you can make changes in `open-next`, and run `pnpm open-next build` in your Next.js app to test the changes.
// WORKAROUND: Set `NextServer` working directory (AWS specific) — https://github.com/serverless-stack/open-next#workaround-set-nextserver-working-directory-aws-specific
0 commit comments