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
+48-27Lines changed: 48 additions & 27 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -172,13 +172,10 @@ The server function adapter wraps around `NextServer` and exports a handler func
172
172
```diff
173
173
.next/ -> NextServer
174
174
+ .open-next/
175
-
+ public-files.json -> `/public` file listing
176
175
node_modules/ -> dependencies
177
176
+ index.mjs -> server function adapter
178
177
```
179
178
180
-
The file `public-files.json` contains the top-level file and directory names in your app's `public/` folder. At runtime, the server function will forward any requests made to these files and directories to S3. And S3 will serve them directly. [See why.](#workaround-public-static-files-served-out-by-server-function-aws-specific)
181
-
182
179
**Monorepo**
183
180
184
181
In the case of a monorepo, the build output looks slightly different. For example, if the app is located in `packages/web`, the build output looks like this:
@@ -198,7 +195,6 @@ In this case, the server function adapter needs to be created inside `packages/w
198
195
web/
199
196
.next/ -> NextServer
200
197
+ .open-next/
201
-
+ public-files.json -> `/public` file listing
202
198
node_modules/ -> dependencies from root node_modules (optional)
203
199
+ index.mjs -> server function adapter
204
200
node_modules/ -> dependencies from package node_modules
@@ -211,27 +207,29 @@ This ensures that the Lambda handler remains at `index.mjs`.
211
207
212
208
Create a CloudFront distribution, and dispatch requests to their corresponding handlers (behaviors). The following behaviors are configured:
213
209
214
-
| Behavior | Requests | CloudFront Function | Origin |
|`/_next/image`| Image optimization | - | image optimization function |
218
-
|`/_next/data/*`| data requests | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function |
219
-
|`/api/*`| API | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function |
220
-
|`/*`| catch all | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function fallback to<br />S3 bucket on 503<br />[see why](#workaround-public-static-files-served-out-by-server-function-aws-specific)|
210
+
| Behavior | Requests | CloudFront Function | Origin |
|`/_next/image`| Image optimization | - | image optimization function |
215
+
|`/_next/data/*`| data requests | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function |
216
+
|`/api/*`| API | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function |
217
+
|`/*`| catch all | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function |
221
218
222
219
#### Running at edge
223
220
224
221
The server function can also run at edge locations by configuring it as Lambda@Edge on Origin Request. The server function can accept both regional request events (API payload version 2.0) and edge request events (CloudFront Origin Request payload). Depending on the shape of the Lambda event object, the function will process the request accordingly.
|`/_next/data/*`| data requests | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function | - |
233
-
|`/api/*`| API | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function | - |
234
-
|`/*`| catch all | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function | S3 bucket<br />[see why](#workaround-public-static-files-served-out-by-server-function-aws-specific)|
|`/_next/data/*`| data requests | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function | - |
231
+
|`/api/*`| API | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function | - |
232
+
|`/*`| catch all | set `x-forwarded-host`<br />[see why](#workaround-set-x-forwarded-host-header-aws-specific)| server function | - |
235
233
236
234
#### Revalidation function
237
235
@@ -389,26 +387,49 @@ This cost estimate is based on the `us-east-1` region pricing and does not consi
389
387
390
388
## Limitations and workarounds
391
389
392
-
#### WORKAROUND: `public/` static files served by the server function (AWS specific)
390
+
#### WORKAROUND: Create one cache behavior per top-level file and folder in `public/` (AWS specific)
393
391
394
-
As mentioned in the [S3 bucket](#s3-bucket) section, files in your app's `public/` folder are static and are uploaded to the S3 bucket. Ideally, requests for these files should be handled by the S3 bucket, like so:
392
+
As mentioned in the [Asset files](#asset-files) section, files in your app's `public/` folder are static and are uploaded to the S3 bucket. And requests for these files are handled by the S3 bucket, like so:
395
393
396
394
```
397
-
398
395
https://my-nextjs-app.com/favicon.ico
396
+
https://my-nextjs-app.com/my-images/avatar.png
397
+
```
398
+
399
+
Ideally, we would create a single cache behavior that routes all requests for `public/` files to the S3 bucket. Unfortunately, CloudFront does not support regex or advanced string patternss for cache behaviors (ie. `/favicon.ico|my-images\/*/` ).
400
+
401
+
To work around this limitation, we create a separate cache behavior for each top-level file and folder in `public/`. For example, if your folder structure is:
399
402
400
403
```
404
+
public/
405
+
favicon.ico
406
+
my-images/
407
+
avatar.png
408
+
avatar-dark.png
409
+
foo/
410
+
bar.png
411
+
```
412
+
413
+
You would create three cache behaviors: `/favicon.ico`, `/my-images/*`, and `/foo/*`. Each of these behaviors points to the S3 bucket.
401
414
402
-
This requires the CloudFront distribution to have the behavior `/favicon.ico` and set the S3 bucket as the origin. However, CloudFront has a [default limit of 25 behaviors per distribution](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html#limits-web-distributions), so it is not a scalable solution to create one behavior per file.
415
+
One thing to be aware of is that CloudFront has a [default limit of 25 behaviors per distribution](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html#limits-web-distributions). If you have a lot of top-level files and folders, you may reach this limit. To avoid this, consider moving some or all files and folders into a subdirectory:
403
416
404
-
To work around the issue, requests for `public/` files are handled by the catch all behavior `/*`. This behavior sends the request to the server function first, and if the server fails to handle the request, it will fall back to the S3 bucket.
417
+
```
418
+
public/
419
+
files/
420
+
favicon.ico
421
+
my-images/
422
+
avatar.png
423
+
avatar-dark.png
424
+
foo/
425
+
bar.png
426
+
```
405
427
406
-
During the build process, the top-level file and directory names in the `public/` folder are saved to the `.open-next/public-files.json` file within the server function bundle. At runtime, the server function checks the request URL path against the file. If the request is made to a file in the `public/` folder:
428
+
In this case, you only need to create one cache behavior: `/files/*`.
407
429
408
-
- When deployed to a single region (Lambda), the server function returns a 503 response right away, and S3, which is configured as the failover origin on 503 status code, will serve the file. [Refer to the CloudFront setup.](#cloudfront-distribution)
409
-
- When deployed to the edge (Lambda@Edge), the server function returns the request object. And the request will be handled by S3, which is configured as the origin. [Refer to the CloudFront setup.](#running-at-edge)
430
+
Make sure to update your code accordingly to reflect the new file paths.
410
431
411
-
This means that on cache miss, the request may take slightly longer to process.
432
+
Alternatively, you can [request an increase to the limit through AWS Support](https://console.aws.amazon.com/support/home#/case/create?issueType=service-limit-increase&limitType=service-code-cloudfront-distributions).
412
433
413
434
#### WORKAROUND: Set `x-forwarded-host` header (AWS specific)
Copy file name to clipboardExpand all lines: packages/open-next/src/adapters/server-adapter.ts
+3Lines changed: 3 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -89,6 +89,9 @@ export async function handler(
89
89
}
90
90
91
91
// WORKAROUND: public/ static files served by the server function (AWS specific) — https://github.com/serverless-stack/open-next#workaround-public-static-files-served-by-the-server-function-aws-specific
92
+
// TODO: This is no longer required if each top-level file and folder in "/public"
93
+
// is handled by a separate cache behavior. Leaving here for backward compatibility.
0 commit comments