cdk-nextjs 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +2467 -2714
- package/.jsii.tabl.json +1 -1
- package/API.md +1725 -1909
- package/CLAUDE.md +2 -1
- package/README.md +429 -130
- package/assets/lambdas/post-deploy/post-deploy.lambda/index.js +152 -170
- package/assets/lambdas/redeploy-stage/redeploy-stage.lambda/index.js +875 -0
- package/docs/adapter-runtime.md +185 -0
- package/docs/breaking-changes.md +687 -4
- package/docs/caching-guide.md +156 -112
- package/docs/cdk-nextjs-cfn-exec-policy.json +2 -1
- package/docs/development-guide.md +1 -1
- package/docs/harness-coverage.md +598 -0
- package/docs/init-cache-deployment.md +32 -1
- package/docs/next-build-output-guide.md +30 -20
- package/examples/README.md +5 -1
- package/lib/adapter/__fixtures__/app-playground-base-path.json +4926 -0
- package/lib/adapter/__fixtures__/app-playground.json +4917 -0
- package/lib/adapter/__fixtures__/pages-i18n.json +1728 -0
- package/lib/adapter/adapter.mjs +1548 -185
- package/lib/adapter/adapter.test.js +106 -0
- package/lib/adapter/aws-cache-store.d.ts +489 -0
- package/lib/adapter/aws-cache-store.js +1004 -0
- package/lib/adapter/aws-cache-store.test.d.ts +1 -0
- package/lib/adapter/aws-cache-store.test.js +361 -0
- package/lib/adapter/build-outputs.d.ts +80 -0
- package/lib/adapter/build-outputs.js +852 -0
- package/lib/adapter/build-outputs.test.d.ts +1 -0
- package/lib/adapter/build-outputs.test.js +861 -0
- package/lib/adapter/cache-handler.d.ts +9 -2
- package/lib/adapter/cache-handler.js +72 -96
- package/lib/adapter/cache-handler.mjs +18956 -17774
- package/lib/adapter/cache-handler.test.js +263 -31
- package/lib/adapter/cache-kinds.d.ts +32 -0
- package/lib/adapter/cache-kinds.js +35 -0
- package/lib/adapter/cache-kinds.test.d.ts +1 -0
- package/lib/adapter/cache-kinds.test.js +69 -0
- package/lib/adapter/cache-utils.d.ts +90 -0
- package/lib/adapter/cache-utils.js +199 -4
- package/lib/adapter/cache-utils.test.d.ts +1 -0
- package/lib/adapter/cache-utils.test.js +179 -0
- package/lib/adapter/function-groups.d.ts +215 -0
- package/lib/adapter/function-groups.js +1099 -0
- package/lib/adapter/function-groups.test.d.ts +1 -0
- package/lib/adapter/function-groups.test.js +743 -0
- package/lib/adapter/init-cache.d.ts +6 -0
- package/lib/adapter/init-cache.js +245 -0
- package/lib/adapter/init-cache.test.d.ts +1 -0
- package/lib/adapter/init-cache.test.js +137 -0
- package/lib/adapter/local-file-cache-handler.d.ts +23 -0
- package/lib/adapter/local-file-cache-handler.js +52 -1
- package/lib/adapter/memory-cache-handler.d.ts +26 -17
- package/lib/adapter/memory-cache-handler.js +32 -50
- package/lib/adapter/memory-cache-handler.test.js +105 -85
- package/lib/adapter/s3-cache-handler.d.ts +179 -40
- package/lib/adapter/s3-cache-handler.js +807 -277
- package/lib/adapter/s3-cache-handler.test.js +1186 -31
- package/lib/adapter/use-cache-common.d.ts +90 -0
- package/lib/adapter/use-cache-common.js +250 -0
- package/lib/adapter/use-cache-common.test.d.ts +1 -0
- package/lib/adapter/use-cache-common.test.js +646 -0
- package/lib/adapter/use-cache-default-handler.d.ts +24 -0
- package/lib/adapter/use-cache-default-handler.js +90 -0
- package/lib/adapter/use-cache-default-handler.mjs +38645 -0
- package/lib/adapter/use-cache-handlers.test.d.ts +1 -0
- package/lib/adapter/use-cache-handlers.test.js +349 -0
- package/lib/adapter/use-cache-remote-handler.d.ts +26 -0
- package/lib/adapter/use-cache-remote-handler.js +186 -0
- package/lib/{image-optimization/handler.mjs → adapter/use-cache-remote-handler.mjs} +33572 -38798
- package/lib/generated-structs/OptionalNextjsApiProps.d.ts +59 -0
- package/lib/generated-structs/OptionalNextjsApiProps.js +3 -0
- package/lib/generated-structs/OptionalNextjsCacheProps.d.ts +15 -6
- package/lib/generated-structs/OptionalNextjsCacheProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsContainersProps.d.ts +25 -11
- package/lib/generated-structs/OptionalNextjsContainersProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsDistributionProps.d.ts +31 -9
- package/lib/generated-structs/OptionalNextjsDistributionProps.js +1 -1
- package/lib/generated-structs/OptionalNextjsPostDeployProps.d.ts +13 -0
- package/lib/generated-structs/OptionalNextjsPostDeployProps.js +1 -1
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.d.ts +11 -2
- package/lib/generated-structs/OptionalPostDeployCustomResourceProperties.js +1 -1
- package/lib/index.d.ts +6 -7
- package/lib/index.js +2 -4
- package/lib/lambdas/post-deploy/post-deploy.lambda.js +3 -2
- package/lib/lambdas/post-deploy/prune-cache-bucket.d.ts +7 -3
- package/lib/lambdas/post-deploy/prune-cache-bucket.js +57 -71
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-cache-bucket.test.js +114 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.js +23 -31
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-revalidation-table.test.js +71 -0
- package/lib/lambdas/post-deploy/prune-s3.d.ts +19 -3
- package/lib/lambdas/post-deploy/prune-s3.js +54 -15
- package/lib/lambdas/post-deploy/prune-s3.test.d.ts +1 -0
- package/lib/lambdas/post-deploy/prune-s3.test.js +255 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.d.ts +13 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage-function.js +55 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.d.ts +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.js +68 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.d.ts +20 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.lambda.js +24 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.d.ts +1 -0
- package/lib/lambdas/redeploy-stage/redeploy-stage.test.js +93 -0
- package/lib/nextjs-api.d.ts +107 -18
- package/lib/nextjs-api.js +349 -39
- package/lib/nextjs-api.test.js +582 -1
- package/lib/nextjs-build/global-containers.Dockerfile +15 -10
- package/lib/nextjs-build/nextjs-build.d.ts +339 -63
- package/lib/nextjs-build/nextjs-build.js +684 -327
- package/lib/nextjs-build/nextjs-build.test.d.ts +1 -0
- package/lib/nextjs-build/nextjs-build.test.js +412 -0
- package/lib/nextjs-build/patch-fetch.js +1 -1
- package/lib/nextjs-build/patch-fetch.test.js +166 -11
- package/lib/nextjs-build/regional-containers.Dockerfile +17 -10
- package/lib/nextjs-cache.d.ts +82 -4
- package/lib/nextjs-cache.js +186 -10
- package/lib/nextjs-cache.test.js +176 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.d.ts +21 -8
- package/lib/nextjs-compute/nextjs-compute-base-props.js +41 -1
- package/lib/nextjs-compute/nextjs-compute-base-props.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-compute-base-props.test.js +44 -0
- package/lib/nextjs-compute/nextjs-containers.d.ts +19 -0
- package/lib/nextjs-compute/nextjs-containers.js +57 -20
- package/lib/nextjs-compute/nextjs-functions.d.ts +122 -7
- package/lib/nextjs-compute/nextjs-functions.js +113 -67
- package/lib/nextjs-compute/nextjs-functions.test.d.ts +1 -0
- package/lib/nextjs-compute/nextjs-functions.test.js +99 -0
- package/lib/nextjs-distribution.d.ts +194 -23
- package/lib/nextjs-distribution.js +535 -62
- package/lib/nextjs-distribution.test.d.ts +1 -0
- package/lib/nextjs-distribution.test.js +697 -0
- package/lib/nextjs-post-deploy.d.ts +23 -3
- package/lib/nextjs-post-deploy.js +14 -10
- package/lib/nextjs-post-deploy.test.d.ts +1 -0
- package/lib/nextjs-post-deploy.test.js +34 -0
- package/lib/nextjs-static-assets.d.ts +23 -4
- package/lib/nextjs-static-assets.js +29 -6
- package/lib/nextjs-static-assets.test.js +20 -1
- package/lib/root-constructs/nextjs-base-construct.d.ts +105 -45
- package/lib/root-constructs/nextjs-base-construct.js +144 -34
- package/lib/root-constructs/nextjs-global-containers.d.ts +18 -20
- package/lib/root-constructs/nextjs-global-containers.js +20 -70
- package/lib/root-constructs/nextjs-global-functions.d.ts +26 -28
- package/lib/root-constructs/nextjs-global-functions.js +52 -69
- package/lib/root-constructs/nextjs-regional-containers.d.ts +25 -5
- package/lib/root-constructs/nextjs-regional-containers.js +17 -15
- package/lib/root-constructs/nextjs-regional-functions.d.ts +22 -18
- package/lib/root-constructs/nextjs-regional-functions.js +8 -25
- package/lib/runtime/api-gateway-path.d.ts +34 -0
- package/lib/runtime/api-gateway-path.js +71 -0
- package/lib/runtime/api-gateway-path.test.d.ts +1 -0
- package/lib/runtime/api-gateway-path.test.js +65 -0
- package/lib/runtime/case-redirect.d.ts +22 -0
- package/lib/runtime/case-redirect.js +63 -0
- package/lib/runtime/case-redirect.test.d.ts +1 -0
- package/lib/runtime/case-redirect.test.js +32 -0
- package/lib/runtime/core.d.ts +234 -0
- package/lib/runtime/core.js +1213 -0
- package/lib/runtime/core.test.d.ts +1 -0
- package/lib/runtime/core.test.js +1678 -0
- package/lib/runtime/deployment-root.d.ts +13 -0
- package/lib/runtime/deployment-root.js +29 -0
- package/lib/runtime/dispatch.d.ts +331 -0
- package/lib/runtime/dispatch.js +751 -0
- package/lib/runtime/dispatch.test.d.ts +1 -0
- package/lib/runtime/dispatch.test.js +853 -0
- package/lib/runtime/entrypoints.d.ts +57 -0
- package/lib/runtime/entrypoints.js +115 -0
- package/lib/runtime/http/abort-signal.d.ts +6 -0
- package/lib/runtime/http/abort-signal.js +19 -0
- package/lib/runtime/http/abort-signal.test.d.ts +1 -0
- package/lib/runtime/http/abort-signal.test.js +49 -0
- package/lib/runtime/http/node-server.d.ts +38 -0
- package/lib/runtime/http/node-server.js +99 -0
- package/lib/runtime/http/node-server.test.d.ts +1 -0
- package/lib/runtime/http/node-server.test.js +96 -0
- package/lib/runtime/http/node-sink.d.ts +16 -0
- package/lib/runtime/http/node-sink.js +48 -0
- package/lib/runtime/http/node-sink.test.d.ts +1 -0
- package/lib/runtime/http/node-sink.test.js +66 -0
- package/lib/runtime/http/request.d.ts +62 -0
- package/lib/runtime/http/request.js +134 -0
- package/lib/runtime/http/request.test.d.ts +1 -0
- package/lib/runtime/http/request.test.js +103 -0
- package/lib/runtime/http/response.d.ts +77 -0
- package/lib/runtime/http/response.js +229 -0
- package/lib/runtime/http/response.test.d.ts +1 -0
- package/lib/runtime/http/response.test.js +178 -0
- package/lib/runtime/http/sink.d.ts +73 -0
- package/lib/runtime/http/sink.js +188 -0
- package/lib/runtime/http/sink.test.d.ts +1 -0
- package/lib/runtime/http/sink.test.js +257 -0
- package/lib/runtime/image-utils.d.ts +78 -0
- package/lib/runtime/image-utils.js +129 -0
- package/lib/runtime/image-utils.test.d.ts +1 -0
- package/lib/runtime/image-utils.test.js +237 -0
- package/lib/runtime/image.d.ts +76 -0
- package/lib/runtime/image.js +296 -0
- package/lib/runtime/image.test.d.ts +1 -0
- package/lib/runtime/image.test.js +405 -0
- package/lib/runtime/lambda-event.d.ts +4 -0
- package/lib/runtime/lambda-event.js +113 -0
- package/lib/runtime/lambda-event.test.d.ts +1 -0
- package/lib/runtime/lambda-event.test.js +119 -0
- package/lib/runtime/lambda.mjs +41595 -0
- package/lib/runtime/load-module.d.ts +8 -0
- package/lib/runtime/load-module.js +35 -0
- package/lib/runtime/manifest.d.ts +215 -0
- package/lib/runtime/manifest.js +118 -0
- package/lib/runtime/middleware.d.ts +43 -0
- package/lib/runtime/middleware.js +113 -0
- package/lib/runtime/middleware.test.d.ts +1 -0
- package/lib/runtime/middleware.test.js +259 -0
- package/lib/runtime/next-modules.d.ts +55 -0
- package/lib/runtime/next-modules.js +124 -0
- package/lib/runtime/next-modules.test.d.ts +1 -0
- package/lib/runtime/next-modules.test.js +34 -0
- package/lib/runtime/public-files.d.ts +32 -0
- package/lib/runtime/public-files.js +117 -0
- package/lib/runtime/public-files.test.d.ts +1 -0
- package/lib/runtime/public-files.test.js +97 -0
- package/lib/runtime/server.mjs +41588 -0
- package/lib/runtime/static-files.d.ts +50 -0
- package/lib/runtime/static-files.js +266 -0
- package/lib/runtime/static-files.test.d.ts +1 -0
- package/lib/runtime/static-files.test.js +118 -0
- package/lib/runtime/util.d.ts +28 -0
- package/lib/runtime/util.js +79 -0
- package/lib/utils/base-path.d.ts +123 -11
- package/lib/utils/base-path.js +276 -39
- package/lib/utils/base-path.test.js +275 -50
- package/lib/utils/get-architecture.d.ts +7 -8
- package/lib/utils/get-architecture.js +12 -13
- package/lib/utils/zip-directory.d.ts +14 -0
- package/lib/utils/zip-directory.js +121 -0
- package/lib/utils/zip-directory.test.d.ts +1 -0
- package/lib/utils/zip-directory.test.js +99 -0
- package/package.json +22 -3
- package/scripts/capture-adapter-fixture.mjs +325 -0
- package/scripts/e2e-deploy.sh +398 -0
- package/scripts/e2e-harness/README.md +707 -0
- package/scripts/e2e-harness/app.js +370 -0
- package/scripts/e2e-harness/common.sh +249 -0
- package/scripts/e2e-harness/screen.mjs +302 -0
- package/scripts/e2e-harness/stage-proxy.mjs +145 -0
- package/scripts/e2e-harness/type-filters.mjs +47 -0
- package/scripts/e2e-logs.sh +75 -0
- package/scripts/e2e-offline.sh +91 -0
- package/scripts/e2e-sweep.sh +370 -0
- package/scripts/e2e-warm.sh +114 -0
- package/scripts/zero-config-build.mjs +418 -0
- package/docs/1k-concurrent-users-executions.png +0 -0
- package/docs/plans/adapter-runtime-release.md +0 -362
- package/docs/plans/phase-0-image-function-opt-in.md +0 -295
- package/lib/generated-structs/OptionalDockerImageFunctionProps.d.ts +0 -425
- package/lib/generated-structs/OptionalDockerImageFunctionProps.js +0 -3
- package/lib/image-optimization/handler-utils.d.ts +0 -34
- package/lib/image-optimization/handler-utils.js +0 -83
- package/lib/image-optimization/handler-utils.test.js +0 -178
- package/lib/nextjs-build/functions.Dockerfile +0 -31
- package/lib/nextjs-compute/nextjs-image-function.d.ts +0 -53
- package/lib/nextjs-compute/nextjs-image-function.js +0 -59
- package/lib/utils/experimental-flags.d.ts +0 -24
- package/lib/utils/experimental-flags.js +0 -30
- /package/lib/{image-optimization/handler-utils.test.d.ts → adapter/adapter.test.d.ts} +0 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# The adapter runtime
|
|
2
|
+
|
|
3
|
+
How cdk-nextjs serves a Next.js app on all four deployment types: what runs at
|
|
4
|
+
build time, what runs per request, where it knowingly differs from `next start`,
|
|
5
|
+
and what each deployment type cannot do. The reasoning behind individual
|
|
6
|
+
decisions lives in the code comments next to them; this is the map.
|
|
7
|
+
|
|
8
|
+
Written against Next.js 16.3.5. `@next/routing` is exact-pinned to the `next`
|
|
9
|
+
version and bumped with it.
|
|
10
|
+
|
|
11
|
+
## Build time: `onBuildComplete`
|
|
12
|
+
|
|
13
|
+
`src/adapter/adapter.mts` is the Next.js [deployment adapter][adapters]. Its
|
|
14
|
+
`onBuildComplete` hook calls `buildAdapterManifest` in
|
|
15
|
+
`src/adapter/build-outputs.ts`, which produces two things inside
|
|
16
|
+
`<distDir>/cdk-nextjs-adapter/`:
|
|
17
|
+
|
|
18
|
+
- **The staging tree** (`app/`, or `groups/<name>/` with `functionGroups`): the
|
|
19
|
+
union of every shipped output's traced `assets`, keyed by repo-root-relative
|
|
20
|
+
path. It replaces `output: "standalone"`, which cdk-nextjs no longer sets. This
|
|
21
|
+
directory is the _deployment root_: the Lambda zip and the container image's
|
|
22
|
+
`WORKDIR`. pnpm's symlinks are staged as symlinks, so `NextjsFunctions` zips
|
|
23
|
+
the root itself (`src/utils/zip-directory.ts`) rather than leaving it to
|
|
24
|
+
cdk-assets, which would dereference them.
|
|
25
|
+
- **`manifest.json`** (`src/runtime/manifest.ts`): the only contract between
|
|
26
|
+
build, synth and runtime. It holds `ctx.routing` verbatim, the entrypoint for
|
|
27
|
+
every route template, the build's static files, middleware, and the config
|
|
28
|
+
fields the runtime needs. Every path in it is a repo-root-relative POSIX key,
|
|
29
|
+
never an absolute path.
|
|
30
|
+
|
|
31
|
+
The same hook seeds the init cache for the S3 + DynamoDB cache handler, and it
|
|
32
|
+
refuses any output whose runtime is not `nodejs` (`assertNodeRuntimes`).
|
|
33
|
+
|
|
34
|
+
What is deliberately _not_ in the staging tree: `<distDir>/static` and
|
|
35
|
+
`public/`. On the Lambda types, CloudFront or API Gateway answers them from S3,
|
|
36
|
+
and `public/` alone can exceed the 250 MB unzipped Lambda limit.
|
|
37
|
+
`NextjsGlobalContainers` leaves them out for the same reason CloudFront makes
|
|
38
|
+
them unnecessary; only `NextjsRegionalContainers`, with no CDN in front of it,
|
|
39
|
+
copies both into its image (`src/nextjs-build/regional-containers.Dockerfile`).
|
|
40
|
+
|
|
41
|
+
## Request time
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
shell ──► NextjsRuntime.handle ──► Dispatcher.dispatch ──► one of:
|
|
45
|
+
lambda.mts (src/runtime/core.ts) (dispatch.ts) entrypoint
|
|
46
|
+
server.mts @next/routing static file
|
|
47
|
+
resolveRoutes /_next/image
|
|
48
|
+
+ middleware runner redirect / external rewrite
|
|
49
|
+
middleware's own response
|
|
50
|
+
404 / 500 ladder
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- **Shells.** `lambda.mts` (Lambda response streaming; Function URL events on
|
|
54
|
+
`NextjsGlobalFunctions`, API Gateway REST streaming events on
|
|
55
|
+
`NextjsRegionalFunctions`) and `server.mts` (`node:http`, both Containers
|
|
56
|
+
types). Each only translates its input into a `RuntimeRequest` and its output
|
|
57
|
+
into a `ResponseSink`. Both run the same core, so the container e2e suite
|
|
58
|
+
exercises the code Lambda runs.
|
|
59
|
+
- **Core** (`core.ts`). It synthesizes `IncomingMessage`/`ServerResponse` shims
|
|
60
|
+
(`http/`), dispatches, and acts on the result. It gzips streamed responses
|
|
61
|
+
itself, because neither API Gateway in STREAM mode nor CloudFront compresses a
|
|
62
|
+
response without `Content-Length`. It awaits `waitUntil` work before
|
|
63
|
+
returning, since Lambda freezes on return.
|
|
64
|
+
- **Dispatch** (`dispatch.ts`). Route matching is `@next/routing`'s
|
|
65
|
+
`resolveRoutes`, the library `next start`'s router was refactored to expose.
|
|
66
|
+
Dispatch adds what it gets wrong or leaves out, each with a comment:
|
|
67
|
+
`trailingSlash` variants, the i18n root, `nxtP` param repair, redirect-location
|
|
68
|
+
normalization. The routing table (pathnames plus every spelling of every
|
|
69
|
+
static file) is built once per cold start and cached.
|
|
70
|
+
- **Middleware** (`middleware.ts`) runs through `resolveRoutes`'s
|
|
71
|
+
`invokeMiddleware` callback. Request bodies are teed so middleware and the
|
|
72
|
+
entrypoint both read them.
|
|
73
|
+
- **Entrypoints** (`entrypoints.ts`) are required lazily, on first use, which is
|
|
74
|
+
most of the cold-start win over `server.js`.
|
|
75
|
+
- **Static files** (`static-files.ts`) go through Next.js's own `serveStatic`
|
|
76
|
+
(`send`), called as `next start` calls it. `public/` is listed off disk at
|
|
77
|
+
cold start (`public-files.ts`) rather than from the manifest, so files a
|
|
78
|
+
`postbuild` writes are included. On the Lambda types the directory is not in
|
|
79
|
+
the package: the list comes from `public-files.json`, written at synth, and
|
|
80
|
+
the files are streamed from the static-assets bucket.
|
|
81
|
+
- **Image optimization** (`image.ts`) runs inside the runtime, after middleware.
|
|
82
|
+
It reads local source images from the static-assets bucket, except on
|
|
83
|
+
`NextjsRegionalContainers`, which has them on disk. There
|
|
84
|
+
is no separate image Lambda any more, because middleware never ran for it.
|
|
85
|
+
- **Cache** (`src/adapter/cache-handler.ts`): memory in front of S3 + DynamoDB
|
|
86
|
+
at runtime, local files at build time. It also creates the CloudFront
|
|
87
|
+
invalidations for on-demand revalidation on the Global types.
|
|
88
|
+
- **`'use cache'` handlers** (`src/adapter/use-cache-{default,remote}-handler.ts`,
|
|
89
|
+
registered as `cacheHandlers`): `default` keeps entries in memory, `remote`
|
|
90
|
+
in S3 with memory in front, and both read tag revalidations from the same
|
|
91
|
+
DynamoDB marker rows as the cache handler (`src/adapter/aws-cache-store.ts`
|
|
92
|
+
is the plumbing all three share). Past a tag's first read, all three learn
|
|
93
|
+
about revalidations from the revalidation log (`RevalidationLog`, `pk =
|
|
94
|
+
<buildId>#log`) through `TrackedTagMarkers`: one `Query` per refresh interval
|
|
95
|
+
instead of re-reading every tracked marker. The cache handler and the
|
|
96
|
+
`'use cache'` handlers share one manifest, so an instance sends one.
|
|
97
|
+
|
|
98
|
+
### Invariants worth not breaking
|
|
99
|
+
|
|
100
|
+
- **`process.cwd()` is the staged project dir.** Next.js inlines
|
|
101
|
+
`relative(buildCwd, projectDir)` into every entrypoint and resolves it against
|
|
102
|
+
the runtime cwd. `loadRuntime` chdirs and asserts this. `build-outputs.ts`
|
|
103
|
+
asserts the build ran from the project dir, so the inlined value is `""`.
|
|
104
|
+
- **`minimalMode` is never set.** The non-minimal path keeps the incremental
|
|
105
|
+
cache inside the entrypoint, which the cache handler depends on.
|
|
106
|
+
- **PPR is origin-only**, as in `next start`. The CDN-shell variant needs
|
|
107
|
+
CloudFront to splice an edge response with an origin stream, which it cannot
|
|
108
|
+
do.
|
|
109
|
+
- **One Dispatcher serves every request**, concurrently on the container shell,
|
|
110
|
+
so per-request state (the middleware invoker, with its `waitUntil` and
|
|
111
|
+
`signal`) travels in the `DispatchRequest`, never on the Dispatcher.
|
|
112
|
+
|
|
113
|
+
### Why `functionGroups` exists
|
|
114
|
+
|
|
115
|
+
It's the largest feature here, and it's deliberate. One heavy dependency (a
|
|
116
|
+
PDF renderer, a headless browser) can push a zip Lambda past 250 MB, and it
|
|
117
|
+
makes every route pay its cold start. Splitting that route into its own
|
|
118
|
+
function fixes both and gives it its own memory and timeout, as Vercel and
|
|
119
|
+
OpenNext do. A container-image Lambda fixes only the size, and makes every
|
|
120
|
+
cold start slower, so it isn't a replacement.
|
|
121
|
+
|
|
122
|
+
Keep the cost in one place: the adapter decides the group edge (CloudFront
|
|
123
|
+
behaviors, API Gateway resources) once, checks it reaches every file, and
|
|
124
|
+
writes it to the manifest. The constructs read that list rather than
|
|
125
|
+
recomputing it.
|
|
126
|
+
|
|
127
|
+
## Where it differs from `next start`, knowingly
|
|
128
|
+
|
|
129
|
+
| Behavior | `next start` | cdk-nextjs | Why |
|
|
130
|
+
| ------------------------------------------------------------ | -------------------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
131
|
+
| Edge runtime, legacy edge `middleware.ts` | supported | build fails | Deprecated upstream. Node-runtime `proxy.ts` is supported. |
|
|
132
|
+
| `dynamicParams = false` | concrete prerenders served, others 404 | every param 404s | Next.js gates the route behind preview cookies and expects the platform to serve prerenders off the CDN. Supporting it is a design change. |
|
|
133
|
+
| Rewrite destination with a repeated query key (`?a=1&a=2`) | array | last value only | `@next/routing` bug ([vercel/next.js#99155](https://github.com/vercel/next.js/issues/99155)). |
|
|
134
|
+
| Static file requested with POST/PUT/DELETE | 405 rendered through `/_error` | 405, plain text | Same status and `Allow`; not worth an error-page render. |
|
|
135
|
+
| Response compression | gzip or brotli | gzip only, in the runtime | Brotli's streaming throughput is poor at default quality. |
|
|
136
|
+
| `public/` under a locale prefix | default locales only | default locales only | Same. Listed because it surprises people: `/fr/x.txt` 404s unless `fr` is a domain's default. |
|
|
137
|
+
| `X-Forwarded-Host` | ignored | ignored, except on `NextjsGlobalFunctions` | Same as `next start`. The Global Functions URL is reachable only through CloudFront, which overwrites the header with the viewer's host, and must see its own domain as `Host`. Trusted only on a request Lambda verified the SigV4 of. |
|
|
138
|
+
| `If-Range` on a `public/` file reached by a rewrite | range honored if the validator matches | whole file (200), except on `NextjsRegionalContainers` | Elsewhere the file is streamed from S3, which has no `If-Range`; sending the whole file is what HTTP allows. `Range` itself is honored. |
|
|
139
|
+
| Grouped route requested in the wrong case (`/API/reports/1`) | served | 308 to the route's spelling (`/api/reports/1`) | Edge path matching is case-sensitive, so the request reaches a function that doesn't carry the route. Only with `functionGroups`. |
|
|
140
|
+
| Missing `/_next/static/*` on the Global types | 404, body `Not Found` | 404, S3's XML body | S3 answers the Origin Access Control request itself; the body would need a Lambda@Edge rewrite. |
|
|
141
|
+
| `resume-data-cache` cases | pass | 2 cases fail | A multi-instance cache can't give the per-process guarantee the fixture asserts. |
|
|
142
|
+
| `config.maxDuration`, `preferredRegion` | honored on Vercel | dropped, with a warning | A Lambda timeout is per function, not per route; region is a stack-level choice. |
|
|
143
|
+
|
|
144
|
+
The compatibility harness keeps the full record, with a verdict per excluded
|
|
145
|
+
case: [`harness-coverage.md`](./harness-coverage.md).
|
|
146
|
+
|
|
147
|
+
## Per-type limitations
|
|
148
|
+
|
|
149
|
+
| | Global Functions | Global Containers | Regional Functions | Regional Containers |
|
|
150
|
+
| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | ----------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------- |
|
|
151
|
+
| Front door | CloudFront → Function URL (IAM, SigV4) | CloudFront → ALB (VPC origin) | API Gateway REST → Lambda | ALB |
|
|
152
|
+
| Static assets | S3 via CloudFront | S3 via CloudFront | S3 via API Gateway | from disk in the image |
|
|
153
|
+
| 75-behavior budget: top-level `public/` entries plus `functionGroups` patterns | yes | yes | no | no |
|
|
154
|
+
| Client `Authorization` header | used by SigV4; send credentials under another name | passes | passes | passes |
|
|
155
|
+
| POST/PUT body from a non-browser client | needs `x-amz-content-sha256` | fine | fine | fine |
|
|
156
|
+
| HEAD `content-length` | always `0` (Function URL) | declared | declared | declared |
|
|
157
|
+
| `public/` names | no CloudFront-spellable character → no behavior, warning; the server function streams it from S3 | same | outside `[a-zA-Z0-9:._-$]` at top level → no resource, warning; the server function streams it from S3 | any name |
|
|
158
|
+
| `functionGroups` | yes | no | yes | no |
|
|
159
|
+
| Stage prefix | — | — | put back for a `basePath` that starts with it | — |
|
|
160
|
+
|
|
161
|
+
Each of these is in the README's Limitations too, or in `breaking-changes.md`
|
|
162
|
+
for anything that changed from an earlier release.
|
|
163
|
+
|
|
164
|
+
## Debugging
|
|
165
|
+
|
|
166
|
+
- **Compare with `next start` on the same build.** `scripts/e2e-offline.sh
|
|
167
|
+
<next.js fixture>` builds one fixture through the adapter and serves it twice,
|
|
168
|
+
through our container shell and through `next start`. Most "why does the
|
|
169
|
+
deployment disagree" questions come down to diffing the two responses. For an
|
|
170
|
+
app in `examples/`, run `lib/runtime/server.mjs` from its
|
|
171
|
+
`.next/cdk-nextjs-adapter/app`, with `.next/static` and `public` copied in as
|
|
172
|
+
the regional containers Dockerfile does.
|
|
173
|
+
- **Tell the CDN from the origin.** Behind CloudFront, `x-cache` says whether the
|
|
174
|
+
edge answered, and every other header is the one the _cached copy_ was stored
|
|
175
|
+
with. An `x-nextjs-cache: REVALIDATED` on a `Hit from cloudfront` is an old
|
|
176
|
+
origin response, not a fresh render. The dynamic cache policy caches only what
|
|
177
|
+
sends `Cache-Control` (`s-maxage`); everything else goes to the origin.
|
|
178
|
+
- **Dispatch without AWS.** `src/runtime/dispatch.test.ts` runs the real
|
|
179
|
+
Dispatcher against manifests built from captured `onBuildComplete` contexts.
|
|
180
|
+
Add a case there before you deploy. Refresh the captures with
|
|
181
|
+
`scripts/capture-adapter-fixture.mjs` after a `next` upgrade.
|
|
182
|
+
- **Logs.** Unhandled errors are logged by the core before the error page is
|
|
183
|
+
rendered. The cache handler logs under `DEBUG=cdk-nextjs:*`.
|
|
184
|
+
|
|
185
|
+
[adapters]: https://nextjs.org/docs/app/api-reference/adapters
|