From 1d2302c56c7bf5abb2fe2659c6edf826bd3f6b45 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Fri, 27 Sep 2024 16:37:17 +0100 Subject: [PATCH 001/150] update the create cloudflare command ofr creating a new Next.js application --- pages/cloudflare/examples.mdx | 3 +-- pages/cloudflare/get-started.mdx | 3 +-- pages/cloudflare/index.mdx | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/pages/cloudflare/examples.mdx b/pages/cloudflare/examples.mdx index 24e44f0..aba8420 100644 --- a/pages/cloudflare/examples.mdx +++ b/pages/cloudflare/examples.mdx @@ -6,8 +6,7 @@ import { Callout } from 'nextra/components'; To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: ``` -npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11040899018/npm-package-create-cloudflare-6830 --no-auto-update --experimental --framework next - +npm create cloudflare@latest -- my-next-app --framework=next --experimental ``` ### Basic starter projects diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 3a53cd3..8a306b2 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -8,8 +8,7 @@ import { Callout } from 'nextra/components'; To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: ``` -npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11040899018/npm-package-create-cloudflare-6830 --no-auto-update --experimental --framework next - +npm create cloudflare@latest -- my-next-app --framework=next --experimental ``` #### Existing Next.js apps diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 4781efb..4cf96fc 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -18,7 +18,7 @@ You can also use [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cl To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: ``` -npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11040899018/npm-package-create-cloudflare-6830 --no-auto-update --experimental --framework next +npm create cloudflare@latest -- my-next-app --framework=next --experimental ``` ##### Existing Next.js apps From d271ed84a899386c85b4fca40c13bfc3b7d1b172 Mon Sep 17 00:00:00 2001 From: Dani Haro <47931084+daniharo@users.noreply.github.com> Date: Fri, 27 Sep 2024 17:37:46 +0200 Subject: [PATCH 002/150] fix broken link to Node.js APIs in cloudflare --- pages/cloudflare/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 4781efb..cc6b6c3 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -27,7 +27,7 @@ Follow the guide [here](/cloudflare/get-started) to use [@opennextjs/cloudflare] ### Supported Next.js runtimes -Next.js has [two "runtimes"](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes) — "Edge" and "Node.js". When you use `@opennextjs/cloudflare`, your app can use the Node.js runtime, which is more fully featured, and allows you to use the [Node.js APIs](/workers/runtime-apis/nodejs/) that are provided by the Cloudflare Workers runtime. +Next.js has [two "runtimes"](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes) — "Edge" and "Node.js". When you use `@opennextjs/cloudflare`, your app can use the Node.js runtime, which is more fully featured, and allows you to use the [Node.js APIs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) that are provided by the Cloudflare Workers runtime. This is an important difference from `@cloudflare/next-on-pages`, which only supports the "Edge" runtime. The Edge Runtime code in Next.js [intentionally constrains which APIs from Node.js can be used](https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack/plugins/middleware-plugin.ts#L820), and the "Edge" runtime does not support all Next.js features. From 1e423bbee9ca7de277f52eaf24f6c3ab51d685b2 Mon Sep 17 00:00:00 2001 From: Jason Silberman Date: Mon, 30 Sep 2024 11:21:00 -0400 Subject: [PATCH 003/150] Update get-started.mdx --- pages/cloudflare/get-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 8a306b2..e58bc0d 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -62,7 +62,7 @@ Add the following to the scripts field of your `package.json` file: - `npm run build:worker`: Runs the [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter. This first builds your app by running `next build` behind the scenes, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. - `npm run dev:worker`: Takes the output generated by `build:worker` and runs it locally in [workerd](https://github.com/cloudflare/workerd), the open-source Workers Runtime, allowing you to run the app locally in the same environment that it will run in production. If you instead run `next dev`, your app will run in Node.js, which is a different JavaScript runtime from the Workers runtime, with differences in behavior and APIs. -- `npm run preview:worker`: Runs `build:worker` and then `preview:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. +- `npm run preview:worker`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. - `npm run deploy`: Builds your app, and then deploys it to Cloudflare ### 4. Add caching with Workers KV From 65147b7f2782dcddce1a2b8db5e17c20544ae900 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Tue, 1 Oct 2024 19:00:31 +0100 Subject: [PATCH 004/150] document that the Pages router is not supported by the cloudflare adapter --- pages/cloudflare/index.mdx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index a618279..7cc19e5 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -39,14 +39,17 @@ To help improve compatibility, we encourage you to [report bugs](https://github. ### Supported Next.js features -- [x] [App Router](https://nextjs.org/docs/app) & [Pages Router](https://nextjs.org/docs/pages) +- [x] [App Router](https://nextjs.org/docs/app) - [x] [API routes](https://nextjs.org/docs/pages/building-your-application/routing/api-routes) - [x] [Dynamic routes](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes) - [x] [Static Site Generation (SSG)](https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation) - [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering) - [x] [Incremental Static Regeneration1 (ISR)](https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration) -1 "Manual" revalidation is not supported (i.e. [`revalidateTag()`](https://nextjs.org/docs/app/api-reference/functions/revalidateTag) or [`revalidatePath()`](https://nextjs.org/docs/app/api-reference/functions/revalidatePath)) +1 The [Pages Router](https://nextjs.org/docs/pages) is not currently supported as the App Router has been prioritized given the fact that it is the officially recommended one. + Support for the Pages Router might be added in the future if there is demand for it. + +2 "Manual" revalidation is not supported (i.e. [`revalidateTag()`](https://nextjs.org/docs/app/api-reference/functions/revalidateTag) or [`revalidatePath()`](https://nextjs.org/docs/app/api-reference/functions/revalidatePath)) ### Not Yet Supported Next.js features From 54e79a3d6fb1cd257d6715579bf95241460aa13b Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Tue, 1 Oct 2024 19:08:06 +0100 Subject: [PATCH 005/150] fix incorrect Next.js docs links in Cloudflare docs --- pages/cloudflare/index.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 7cc19e5..9414bae 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -40,11 +40,11 @@ To help improve compatibility, we encourage you to [report bugs](https://github. ### Supported Next.js features - [x] [App Router](https://nextjs.org/docs/app) -- [x] [API routes](https://nextjs.org/docs/pages/building-your-application/routing/api-routes) -- [x] [Dynamic routes](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes) -- [x] [Static Site Generation (SSG)](https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation) -- [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering) -- [x] [Incremental Static Regeneration1 (ISR)](https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration) +- [x] [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) +- [x] [Dynamic routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) +- [x] [Static Site Generation (SSG)](https://nextjs.org/docs/app/building-your-application/rendering/server-components#static-rendering-default) +- [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/app/building-your-application/rendering/server-components) +- [x] [Incremental Static Regeneration1 (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) 1 The [Pages Router](https://nextjs.org/docs/pages) is not currently supported as the App Router has been prioritized given the fact that it is the officially recommended one. Support for the Pages Router might be added in the future if there is demand for it. @@ -55,7 +55,7 @@ To help improve compatibility, we encourage you to [report bugs](https://github. - [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) - [ ] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) -- [ ] [Image optimization](https://nextjs.org/docs/pages/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) +- [ ] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) - [ ] [Experimental streaming support](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) ### How @opennextjs/cloudflare Works From 999a520243b7372c8de3fabb0466b2928ba2a687 Mon Sep 17 00:00:00 2001 From: Brendan Irvine-Broque Date: Tue, 1 Oct 2024 21:47:01 +0200 Subject: [PATCH 006/150] Copy changes to Pages Router docs --- pages/cloudflare/index.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 9414bae..e7a70de 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -46,13 +46,13 @@ To help improve compatibility, we encourage you to [report bugs](https://github. - [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/app/building-your-application/rendering/server-components) - [x] [Incremental Static Regeneration1 (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) -1 The [Pages Router](https://nextjs.org/docs/pages) is not currently supported as the App Router has been prioritized given the fact that it is the officially recommended one. - Support for the Pages Router might be added in the future if there is demand for it. - -2 "Manual" revalidation is not supported (i.e. [`revalidateTag()`](https://nextjs.org/docs/app/api-reference/functions/revalidateTag) or [`revalidatePath()`](https://nextjs.org/docs/app/api-reference/functions/revalidatePath)) +1 "Manual" revalidation is not supported (i.e. [`revalidateTag()`](https://nextjs.org/docs/app/api-reference/functions/revalidateTag) or [`revalidatePath()`](https://nextjs.org/docs/app/api-reference/functions/revalidatePath)) ### Not Yet Supported Next.js features +The following Next.js features are not yet supported — but we welcome both contributions and feedback! Tell us what you'd like to see, or what you'd like to add support for: + +- [ ] [Pages Router](https://nextjs.org/docs/pages) (you should use the App Router instead, which was introduced in Next.js 13) - [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) - [ ] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) - [ ] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) @@ -64,4 +64,4 @@ The OpenNext Cloudflare adapter works by taking the Next.js build output and tra When you add [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) as a dependency to your Next.js app, and then run `npx cloudflare` the adapter first builds your app by running `next build`, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. -You can view the code for @opennextjs/cloudflare [here](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src) to understand what it does under the hood. \ No newline at end of file +You can view the code for @opennextjs/cloudflare [here](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src) to understand what it does under the hood. From 351115ff919241b155be98cfeba1a1a14e3ae5cb Mon Sep 17 00:00:00 2001 From: Brendan Irvine-Broque Date: Tue, 1 Oct 2024 21:50:47 +0200 Subject: [PATCH 007/150] Fix links and clarify warning for Next.js <> Workers and Pages --- pages/cloudflare/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index e7a70de..be9c2f5 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -8,7 +8,7 @@ The [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudfl [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) is pre 1.0, and still in active development. You should try it, [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues), [share feedback](https://github.com/opennextjs/opennextjs-cloudflare/discussions), and contribute code to help make running Next.js apps on Cloudflare easier. We don't quite yet recommend using it for mission-critical production apps. -You can also use [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cloudflare/next-on-pages) to deploy Next.js apps to Cloudflare Pages. You can review the differences in supported Next.js features between @opennextjs/cloudflare and @cloudflare/next-on-pages [here](https://developers.cloudflare.com/workers/static-assets/compatibility-matrix/). +You can also use [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cloudflare/next-on-pages) to deploy Next.js apps to Cloudflare Pages. You can review the differences in supported Next.js features below and by reviewing [the docs for `@cloudflare/next-on-pages`](https://developers.cloudflare.com/pages/framework-guides/nextjs/ssr/supported-features/), and understand the differences between Workers and Pages [here](https://developers.cloudflare.com/workers/static-assets/compatibility-matrix/). ### Get Started From d0930a304b296beba296391914eb0970269b0fca Mon Sep 17 00:00:00 2001 From: Tadhg Lewis Date: Fri, 4 Oct 2024 16:18:31 +1000 Subject: [PATCH 008/150] Update get-started.mdx --- pages/cloudflare/get-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index e58bc0d..9958066 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -40,7 +40,7 @@ main = ".worker-next/index.mjs" name = "my-app" compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat"] -experimental_assets = { directory = ".worker-next/assets", binding = "ASSETS" } +assets = { directory = ".worker-next/assets", binding = "ASSETS" } ``` From 948f2a623b47812e20ee7c8f44b59e0d58a58f2d Mon Sep 17 00:00:00 2001 From: James Date: Mon, 7 Oct 2024 23:49:34 +0100 Subject: [PATCH 009/150] remove cloudflare pages support in cloudflare docs --- pages/cloudflare/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index be9c2f5..2c93355 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -3,7 +3,7 @@ import { Callout } from 'nextra/components'; ## Cloudflare -The [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter lets you deploy Next.js apps to [Cloudflare Workers](https://developers.cloudflare.com/workers) and [Cloudflare Pages](https://developers.cloudflare.com/pages), using the [Node.js "runtime" from Next.js](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes). +The [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter lets you deploy Next.js apps to [Cloudflare Workers](https://developers.cloudflare.com/workers), using the [Node.js "runtime" from Next.js](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes). [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) is pre 1.0, and still in active development. You should try it, [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues), [share feedback](https://github.com/opennextjs/opennextjs-cloudflare/discussions), and contribute code to help make running Next.js apps on Cloudflare easier. We don't quite yet recommend using it for mission-critical production apps. From f4e4f7022cb2fe2f03c9d0a664227b1cddcc87da Mon Sep 17 00:00:00 2001 From: James Anderson Date: Tue, 8 Oct 2024 07:57:51 +0100 Subject: [PATCH 010/150] move ISR to unsupported in Cloudflare adaptor (#22) --- pages/cloudflare/index.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index be9c2f5..2354c4d 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -9,6 +9,7 @@ The [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudfl [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) is pre 1.0, and still in active development. You should try it, [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues), [share feedback](https://github.com/opennextjs/opennextjs-cloudflare/discussions), and contribute code to help make running Next.js apps on Cloudflare easier. We don't quite yet recommend using it for mission-critical production apps. You can also use [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cloudflare/next-on-pages) to deploy Next.js apps to Cloudflare Pages. You can review the differences in supported Next.js features below and by reviewing [the docs for `@cloudflare/next-on-pages`](https://developers.cloudflare.com/pages/framework-guides/nextjs/ssr/supported-features/), and understand the differences between Workers and Pages [here](https://developers.cloudflare.com/workers/static-assets/compatibility-matrix/). + ### Get Started @@ -44,15 +45,13 @@ To help improve compatibility, we encourage you to [report bugs](https://github. - [x] [Dynamic routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) - [x] [Static Site Generation (SSG)](https://nextjs.org/docs/app/building-your-application/rendering/server-components#static-rendering-default) - [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/app/building-your-application/rendering/server-components) -- [x] [Incremental Static Regeneration1 (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) - -1 "Manual" revalidation is not supported (i.e. [`revalidateTag()`](https://nextjs.org/docs/app/api-reference/functions/revalidateTag) or [`revalidatePath()`](https://nextjs.org/docs/app/api-reference/functions/revalidatePath)) ### Not Yet Supported Next.js features The following Next.js features are not yet supported — but we welcome both contributions and feedback! Tell us what you'd like to see, or what you'd like to add support for: - [ ] [Pages Router](https://nextjs.org/docs/pages) (you should use the App Router instead, which was introduced in Next.js 13) +- [ ] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) - [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) - [ ] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) - [ ] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) From 2ab8d94a6dac2dfcf50ebfc2098bfd629df22e87 Mon Sep 17 00:00:00 2001 From: James Anderson Date: Wed, 9 Oct 2024 09:51:39 +0100 Subject: [PATCH 011/150] Update pages/cloudflare/index.mdx Co-authored-by: Dario Piotrowicz --- pages/cloudflare/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 2c93355..b447c41 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -3,7 +3,7 @@ import { Callout } from 'nextra/components'; ## Cloudflare -The [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter lets you deploy Next.js apps to [Cloudflare Workers](https://developers.cloudflare.com/workers), using the [Node.js "runtime" from Next.js](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes). +The [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter lets you deploy Next.js apps to [Cloudflare Workers](https://developers.cloudflare.com/workers) using the [Node.js "runtime" from Next.js](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes). [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) is pre 1.0, and still in active development. You should try it, [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues), [share feedback](https://github.com/opennextjs/opennextjs-cloudflare/discussions), and contribute code to help make running Next.js apps on Cloudflare easier. We don't quite yet recommend using it for mission-critical production apps. From c87cb62c9e093e52a6f26bc90d532637f21c1541 Mon Sep 17 00:00:00 2001 From: James Anderson Date: Sat, 12 Oct 2024 22:31:34 +0100 Subject: [PATCH 012/150] add kv cache name env var to docs + fix a couple errors (#24) --- pages/cloudflare/caching.mdx | 10 ++++------ pages/cloudflare/get-started.mdx | 26 ++++---------------------- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/pages/cloudflare/caching.mdx b/pages/cloudflare/caching.mdx index 70072ad..b50eeab 100644 --- a/pages/cloudflare/caching.mdx +++ b/pages/cloudflare/caching.mdx @@ -15,24 +15,22 @@ Workers KV is eventually consistent, which means that it can take up to 60 secon ### How to enable caching -`opennextjs/cloudflare` uses [Workers KV](https://developers.cloudflare.com/kv/) as the cache for your Next.js app. Workers KV is [fast](https://blog.cloudflare.com/faster-workers-kv) and uses Cloudflare's [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) to increase cache hit rates. When you write cached data to Workers KV, you write to storage that can be read by any Cloudflare location. This means your app can fetch data, cache it in KV, and then subsequent requests anywhere around the world can read from this cache. +`@opennextjs/cloudflare` uses [Workers KV](https://developers.cloudflare.com/kv/) as the cache for your Next.js app. Workers KV is [fast](https://blog.cloudflare.com/faster-workers-kv) and uses Cloudflare's [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) to increase cache hit rates. When you write cached data to Workers KV, you write to storage that can be read by any Cloudflare location. This means your app can fetch data, cache it in KV, and then subsequent requests anywhere around the world can read from this cache. To enable caching, you must: #### 1. Create a KV namespace ``` -npx wrangler@latest kv namespace create NEXT_CACHE_WORKERS_KV +npx wrangler@latest kv namespace create ``` #### 2. Add the KV namespace to your Worker +The binding name used in your app's worker will be `NEXT_CACHE_WORKERS_KV` by default. This is configurable and can be changed by setting the `__OPENNEXT_KV_BINDING_NAME` build-time environment variable. + ``` [[kv_namespaces]] binding = "NEXT_CACHE_WORKERS_KV" id = "" ``` - -### 3. Set the name of the binding to `NEXT_CACHE_WORKERS_KV` - -As shown above, the name of the binding that you configure for the KV namespace must be set to `NEXT_CACHE_WORKERS_KV`. diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 9958066..84a841d 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -47,7 +47,7 @@ assets = { directory = ".worker-next/assets", binding = "ASSETS" } As shown above, you must enable the [`nodejs_compat` compatibility flag](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) *and* set your [compatibility date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/) to `2024-09-23` or later, in order for your Next.js app to work with @opennextjs/cloudflare. -`wrangler.toml` is where you configure your Worker and define what resources it can access via [bindings](/workers/runtime-apis/bindings/). +`wrangler.toml` is where you configure your Worker and define what resources it can access via [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings). ##### 3. Update `package.json` @@ -67,27 +67,7 @@ Add the following to the scripts field of your `package.json` file: ### 4. Add caching with Workers KV -`opennextjs/cloudflare` uses [Workers KV](https://developers.cloudflare.com/kv/) as the cache for your Next.js app. Workers KV is [fast](https://blog.cloudflare.com/faster-workers-kv) and uses Cloudflare's [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) to increase cache hit rates. When you write cached data to Workers KV, you write to storage that can be read by any Cloudflare location. This means your app can fetch data, cache it in KV, and then subsequent requests anywhere around the world can read from this cache. - -To enable caching, you must: - -##### Create a KV namespace - -``` -npx wrangler@latest kv namespace create NEXT_CACHE_WORKERS_KV -``` - -##### Add the KV namespace to your Worker - -``` -[[kv_namespaces]] -binding = "NEXT_CACHE_WORKERS_KV" -id = "" -``` - -#### Set the name of the binding to `NEXT_CACHE_WORKERS_KV` - -As shown above, the name of the binding that you configure for the KV namespace must be set to `NEXT_CACHE_WORKERS_KV`. +See the [Caching docs](/cloudflare/caching) for information on enabling Next.js caching in your OpenNext project. ### 5. Remove `@cloudflare/next-on-pages` (if necessary) @@ -116,6 +96,7 @@ In `package.json`: "devDependencies": { - "@cloudflare/next-on-pages": "*", ``` + (remember to also remove [eslint-plugin-next-on-pages](https://www.npmjs.com/package/eslint-plugin-next-on-pages) from your `.eslintrc.js` file) You no longer need to call `setupDevPlatform()` in your `next.config.mjs` file: @@ -129,6 +110,7 @@ const nextConfig = {}; - if (process.env.NODE_ENV === 'development') { - await setupDevPlatform(); - } +``` And you'll want to replace any uses of `getRequestContext` from `@cloudflare/next-on-pages` with `getCloudflareContext` from `@opennextjs/cloudflare`: From 8de3e5bbce7167c3e08e8ad6cff8a5e4ea0223d8 Mon Sep 17 00:00:00 2001 From: Sean C Davis Date: Wed, 23 Oct 2024 14:53:57 -0400 Subject: [PATCH 013/150] Netlify Next.js Adapter (#27) Co-authored-by: Philippe Serhal --- pages/_meta.json | 3 +- pages/index.mdx | 3 +- pages/netlify/_meta.json | 4 ++ pages/netlify/forms.mdx | 79 ++++++++++++++++++++++++++++++++ pages/netlify/index.mdx | 97 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 pages/netlify/_meta.json create mode 100644 pages/netlify/forms.mdx create mode 100644 pages/netlify/index.mdx diff --git a/pages/_meta.json b/pages/_meta.json index 6375005..43f637a 100644 --- a/pages/_meta.json +++ b/pages/_meta.json @@ -1,5 +1,6 @@ { "index": "Overview", "aws": "AWS", - "cloudflare": "Cloudflare" + "cloudflare": "Cloudflare", + "netlify": "Netlify" } diff --git a/pages/index.mdx b/pages/index.mdx index 6bf21c2..b52b10c 100644 --- a/pages/index.mdx +++ b/pages/index.mdx @@ -1,4 +1,4 @@ -import { SITE } from '../config'; +import { SITE } from "../config"; # OpenNext @@ -18,6 +18,7 @@ OpenNext is currently backed by: 1. [SST](https://sst.dev) community, maintains the [AWS](aws) adapter 2. [Cloudflare](https://developers.cloudflare.com/) team, maintains the [Cloudflare](cloudflare) adapter +3. [Netlify](https://www.netlify.com/) team, maintains the [Netlify](netlify) adapter If you'd like to join the effort, connect with us on [Discord](https://discord.gg/opennextjs). diff --git a/pages/netlify/_meta.json b/pages/netlify/_meta.json new file mode 100644 index 0000000..abb54ab --- /dev/null +++ b/pages/netlify/_meta.json @@ -0,0 +1,4 @@ +{ + "index": "Overview", + "forms": "Netlify Forms" +} diff --git a/pages/netlify/forms.mdx b/pages/netlify/forms.mdx new file mode 100644 index 0000000..fb2b9b6 --- /dev/null +++ b/pages/netlify/forms.mdx @@ -0,0 +1,79 @@ +# Using Netlify Forms with Next.js + +Netlify Forms use [automatic detection of form tag attributes](https://docs.netlify.com/get-started/#set-up-netlify-forms) (example: `data-netlify`) at deploy time by scanning any static HTML files present or generated during the build. + +As a security and anti-spam measure, only form and field names that Netlify detects at deployment are recognized by Netlify. When submitting a form, the form target URL must also be a static file. + +However, modern Next.js versions do not generate fully-static HTML pages because any page can be revalidated at runtime. Instead, relevant pages are pre-rendered at build time, and then stored in Next.js’s cache for serving. This means that your Next.js pages, including any form tags and attributes, are not written to static HTML files at deployment, and therefore cannot be the form’s target page. Attributes related to Netlify Forms set in these pages have no effect. + +## Workaround for Netlify Forms + +Here's one way to work around this limitation: + +1. Create a new HTML file in the `public` directory of your site. This file would be used for deploy-time form detection only. It can have any name, for example `public/__forms.html`. +2. In that file, add form tags for all your Netlify forms and fields. In the below example, note that only the bare minimum is needed, as users would not see this HTML page at all. + + ```html + + + + + + + ``` + +3. In your dynamic page or form component, handle the submission by serving a `POST` request to the static HTML file you’ve created above (using the example above: `/__forms`). + +4. Once the request is completed, you should show a success notification or navigate to another page. Here’s a simplified example of the form component: + + ```jsx + "use client"; + + export function FeedbackForm() { + const handleFormSubmit = async (event) => { + event.preventDefault(); + const formData = new FormData(event.target); + await fetch("https://github.com/__forms.html", { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: new URLSearchParams(formData).toString(), + }); + // Success and error handling ... + }; + + return ( +
+ + + + +
+ ); + } + ``` + +## Live demo + +For a more complete example which includes handling of submission states (success, error or pending), visit the [live demo](https://nextjs-platform-starter.netlify.app/classics) or explore the code for the [form component](https://github.com/netlify-templates/next-platform-starter/blob/main/components/feedback-form.jsx) and the [required static file](https://github.com/netlify-templates/next-platform-starter/blob/main/public/__forms.html). + +## Prevent silent failures + +To prevent silent failures of form detection or submission, we now trigger an intentional build failure when suspecting your code is incompatible: + +```txt +@netlify/plugin-nextjs@5 requires migration steps to support Netlify Forms. Refer to https://ntl.fyi/next-runtime-forms-migration for migration example. +``` + +This failure is triggered when both of the following conditions are met: + +- The adapter has found usage of `netlify` or `data-netlify` form attributes in your React code (which have no effect). +- No static HTML file was found in your `public` directory having form attributes (thus marking that you’ve implemented the approach laid out above). + +### Skip the check + +If you believe that a check failure is incorrect or would like to defer handling the issue to a later time, you can skip this check by adding a `NETLIFY_NEXT_VERIFY_FORMS` environment variable to your site, with the value `false`. diff --git a/pages/netlify/index.mdx b/pages/netlify/index.mdx new file mode 100644 index 0000000..cd301f5 --- /dev/null +++ b/pages/netlify/index.mdx @@ -0,0 +1,97 @@ +import { SITE } from "../../config"; +import { Callout } from "nextra/components"; + +# Next.js on Netlify + + + Netlify Next.js adapter v5 test status + + +Netlify's Next.js adapter automatically configures Netlify sites with key functionality, including cache control, on-demand revalidation, and image optimization. + +The adapter provisions serverless and edge functions as appropriate to handle your site’s server-side functionality (such as SSR, ISR and PPR pages, API endpoints, Server Actions, Edge Middleware, etc.), ensuring that functionality works out-of-the-box. + +We automatically verify compatibility with the latest stable version of Next.js, using the comprehensive end-to-end tests of the framework itself. To access up-to-date test results, use the badge above. + +## Get started + +The easiest way to get started is to deploy our Next.js platform starter template to your Netlify account. Use the button below to get started. + +[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/netlify-templates/next-platform-starter) + +### Prerequisites + +- Next.js version 13.5 and later (up to the latest stable version) +- [Node 18.x or later](https://docs.netlify.com/configure-builds/manage-dependencies/#node-js-and-javascript) +- The latest version of [Netlify CLI](https://docs.netlify.com/cli/get-started/) + +## Key features + +- **App Router:** Netlify fully supports the Next.js App Router, which supports more powerful nested layouts and React’s latest features, such as Server Components and Streaming. + +- **Automatic fine-grained caching:** thehe adapter uses fine-grained caching on Netlify to support the Next.js Full Route Cache and Data Cache. This means that static page responses are automatically cached at the edge and can be revalidated by path or by tag. + +- **On-demand and time-based revalidation:** both the App Router and Pages Router support on-demand and time-based revalidation, allowing you to revalidate and regenerate content at any time after a deploy. + +- **Image optimization:** the `next/image` component uses [Netlify Image CDN](https://docs.netlify.com/image-cdn/overview/) by default to ensure your images are optimized and served in the most efficient format. + +Note that while we also generally support experimental features (for example, Partial Prerendering) from their early stages, such features are not considered stable yet at the framework level. + +## Automatic framework detection + +Netlify automatically detects that you're using Next.js and provisions your site with the most up-to-date adapter. + +### Pin a specific adapter version + +To pin the Netlify Next.js adapter to a specific version, read [the Netlify docs](https://docs.netlify.com/frameworks/next-js/overview/). + +### Suggested configuration values + +When you [link a repository](https://docs.netlify.com/welcome/add-new-site/#import-from-an-existing-repository) for a Next.js project, Netlify provides a suggested build command and publish directory: `next build` and `.next`. + +If you’re using the CLI to run [Netlify Dev](https://docs.netlify.com/cli/local-development/) for a local development environment, Netlify suggests a dev command and port: `next` and `3000`. + +You can override suggested values or set them in a configuration file instead, but suggested values from automatic framework detection may help simplify the process of setting up a Next.js site on Netlify. + +For manual configuration, check out the [typical build settings](https://docs.netlify.com/frameworks/#next-js) for Next.js. + +## Limitations + +Currently, Netlify's Next.js adapter has the following limitations: + +- **SSR pages set to the `edge` runtime will run in your [functions region](https://docs.netlify.com/functions/optional-configuration/#region).** If edge-level performance is critical, we advise that you use static pages with edge functions instead. They are rendered at the origin, but are then cached at the edge and can be revalidated on demand. + +- **Rewrites in your Next.js configuration can’t point to static files in the `public` directory.** If you create `beforeFiles` rewrites in your `next.config.js`, they can’t point to static files in your site’s `public` directory. You can use middleware rewrites as an alternative. + +- **Netlify Forms compatibility:** Using Netlify Forms with the current adapter [requires a workaround](/netlify/forms). + +### pnpm support + +If you’re planning to use pnpm with Next.js to manage dependencies, you must do one of the following: + +- Set a `PNPM_FLAGS` [environment variable](https://docs.netlify.com/environment-variables/get-started/#create-environment-variables) with a value of `--shamefully-hoist`. This appends a `--shamefully-hoist` argument to the `pnpm install` command that Netlify runs. +- [Enable public hoisting](https://pnpm.io/npmrc#public-hoist-pattern) by adding an `.npmrc` file in the root of your project with this content: + + ```bash + public-hoist-pattern[]=* + ``` + +Learn more about using [pnpm on Netlify](https://docs.netlify.com/configure-builds/manage-dependencies/#pnpm). + +## Troubleshooting + +The OpenNext docs are specifically about using Netlify's Next.js adapter v5 and later. For older versions of the adapter, refer to the [Netlify docs](https://docs.netlify.com/frameworks/next-js/overview/). + +If you need help with any version of the adapter, visit [our support page](https://www.netlify.com/support) for various methods of finding answers and getting help. + +### More resources + +- [Typical Next.js build settings](https://docs.netlify.com/frameworks/#next-js) +- [Next.js framework documentation](https://nextjs.org/docs/getting-started) +- [Connect JavaScript client](https://docs.netlify.com/connect/access-data/#use-the-connect-client) - the recommended library for querying Connect data layer APIs in Next.js cached SSR sites. From a70c507303306832f412bdb8967ee5b1be97d9ed Mon Sep 17 00:00:00 2001 From: sommeeeR <91796856+sommeeeer@users.noreply.github.com> Date: Sun, 27 Oct 2024 16:00:55 +0100 Subject: [PATCH 014/150] add poweredByHeader in docs (#26) --- pages/aws/config.mdx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pages/aws/config.mdx b/pages/aws/config.mdx index 70ab0e1..66863e7 100644 --- a/pages/aws/config.mdx +++ b/pages/aws/config.mdx @@ -24,3 +24,13 @@ If you want to take a look at some simple configuration examples, you can check For more advanced use cases, you can check [how to implement custom overrides](/aws/config/custom_overrides). If you want to look at a full example, you can check [the full example](/aws/config/full_example). + + +### Opt out of default poweredByHeader + +By default Next.js will add the [`x-powered-by`]((https://nextjs.org/docs/app/api-reference/next-config-js/poweredByHeader)) header. OpenNext will also add a header `x-opennext`. To opt-out of this, open `next.config.js` and disable the poweredByHeader property in the configuration: +```ts +module.exports = { + poweredByHeader: false, +} +``` \ No newline at end of file From 4371529bf1e103136e63e4dba67342c357cc616e Mon Sep 17 00:00:00 2001 From: zack wilder Date: Mon, 4 Nov 2024 10:13:02 -0500 Subject: [PATCH 015/150] Update index.mdx (#29) --- pages/index.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pages/index.mdx b/pages/index.mdx index b52b10c..3dfb914 100644 --- a/pages/index.mdx +++ b/pages/index.mdx @@ -2,13 +2,13 @@ import { SITE } from "../config"; # OpenNext -Next.js, unlike Remix, Astro, or the other modern frontends, doesn't have a way to self-host across different platforms. You can run it as a Node.js application. But this doesn't work the same way as it does on Vercel. +Next.js, unlike Remix, Astro, or the other modern frontends, doesn't have a way to self-host across different platforms. You can run it as a Node.js application, but this doesn't work the same way as it does on Vercel. --- -There have been several attempts to fix this over the years. Broadly falling into two categories; open source framework specific implementations, or closed source product specific implementations. +There have been several attempts to fix this over the years, broadly falling into two categories: open source framework specific implementations, or closed source product specific implementations. -These can be really hard to maintain separately as Next.js is constantly being updated. +These can be really hard to maintain separately because Next.js is constantly being updated. OpenNext is an initiative to bring all these efforts together. @@ -24,6 +24,6 @@ If you'd like to join the effort, connect with us on [Discord](https://discord.g --- -OpenNext aims to support all Next.js features. And is widely deployed in production across multiple platforms. +OpenNext aims to support all Next.js features and is widely deployed in production across multiple platforms. [NHS England](https://github.com/nhs-england-tools/terraform-aws-opennext), [Udacity](https://engineering.udacity.com/deploying-next-js-on-the-edge-with-sst-is-sst-the-game-changer-its-claimed-to-be-1f05a0abc27c), [Gymshark UK](https://uk.gymshark.com), [SST](https://sst.dev), [Cloudflare](https://www.cloudflare.com) From f551bb440d384ee3bdb17f3a7184039f2f3b0ab8 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Fri, 8 Nov 2024 13:10:39 +0000 Subject: [PATCH 016/150] add link to bindings doc in the getting started local dev section (#30) --- pages/cloudflare/get-started.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 84a841d..3e47e5e 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -123,6 +123,8 @@ And you'll want to replace any uses of `getRequestContext` from `@cloudflare/nex You can continue to run `next dev` when developing locally. +During local development, you can access local versions of Cloudflare bindings as indicated in the [bindings documentation](./bindings). + In step 3, we also added the `npm run preview:worker`, which allows you to quickly preview your app running locally in the Workers runtime, rather than in Node.js. This allows you to test changes in the same runtime as your app will run in when deployed to Cloudflare. ##### 7. Deploy to Cloudflare Workers From f22d23688ba02ac296cb1ae73bf1a08e1147a5d6 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Fri, 8 Nov 2024 14:54:16 +0000 Subject: [PATCH 017/150] Update ordering of Cloudflare pages (#31) --- pages/cloudflare/_meta.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pages/cloudflare/_meta.json b/pages/cloudflare/_meta.json index ca0a2a6..2c667df 100644 --- a/pages/cloudflare/_meta.json +++ b/pages/cloudflare/_meta.json @@ -1,3 +1,8 @@ { - "index": "Overview" + "index": "Overview", + "get-started": "", + "bindings": "", + "caching": "", + "examples": "", + "troubleshooting": "" } From b9f4f2281188ef9a3ff7dec4676725de6ab63db4 Mon Sep 17 00:00:00 2001 From: conico974 Date: Tue, 12 Nov 2024 14:31:36 +0100 Subject: [PATCH 018/150] Improve aws config docs (#28) --- pages/aws/config/_meta.json | 1 + pages/aws/config/reference.mdx | 273 +++++++++++++++++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 pages/aws/config/reference.mdx diff --git a/pages/aws/config/_meta.json b/pages/aws/config/_meta.json index 4163e4c..662c997 100644 --- a/pages/aws/config/_meta.json +++ b/pages/aws/config/_meta.json @@ -1,6 +1,7 @@ { "simple_example": "Simple Example", "custom_overrides": "Custom Overrides", + "reference": "Reference", "full_example": "Full Example", "nx": "Nx Monorepo" } \ No newline at end of file diff --git a/pages/aws/config/reference.mdx b/pages/aws/config/reference.mdx new file mode 100644 index 0000000..912547a --- /dev/null +++ b/pages/aws/config/reference.mdx @@ -0,0 +1,273 @@ +Every option that you can use in `open-next.config.ts` will be listed here. This is the configuration file that you can use to customize the build. +You can look at the [full example](full_example) to see how you can use these options. + +import { Tabs } from 'nextra/components' + + + + Servers here refers to all the different build outputs (Lambda, Node, Deno etc). Each server can have its own options. This also includes some server/function that only need to run at build time. + + Each server config will be under it's own key in the config object. Here are all the servers that you can configure: + + - Default Server - Key: `default` This is the default server, similar to the server-function in open-next v2 + - Splitted Server - Key: `functions` This is only used if you want to split the server into multiple servers. This is a special case, under this key you will define every splitted server. + - External middleware - Key: `middleware` If you want to deploy your middleware separately from the default servers or functions, you can use this key. + - Revalidate Function - Key: `revalidate` This is a special server that will handle the revalidation queue. + - Image Optimization Server - Key: `imageOptimization` This server will handle `_next/image` optimization. + - Warmer Function - Key: `warmer` This server is meant to be used as a warmer for the lambda function. + - Initialization Function - Key: `initializationFunction` This is a special server that will run at build time to initialize the cache. By default it only initialize the tag cache. + + + + + All these servers share some common options that you can use to customize them. + + ### `minify` + + This will try to minify the output of the server including node_modules. It is a boolean and by default, it is set to `false`. + It could lead to some issues with some packages, so it is recommended to test your app with this option before deploying it. + + We will likely not fix issues related to this option, as it is usually library specific. + + ### `override` + + This is where you will be able to override some part of the server. For all of them you can provide what we call a `LazyLoadedOverride` which is a function that will return the override. For some example look at some [Custom overrides](custom_overrides). + All servers have some default override that you can override + + TODO: Add all the types for the custom LazyLoadedOverride here. In the meantime, just look at the [source file](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/types/open-next.ts) + + --- + + #### `wrapper` + + This is the entrypoint of the server. + Be aware that it might not be enough to change this to make it work on said platform. This is only the entrypoint, you might need to change other parts of the server to make it work on the platform. + + Possible values are: `aws-lambda`, `aws-lambda-streaming`, `node`, `cloudflare`, `dummy` or a `LazyLoadedOverride` that will return the wrapper. + + #### `converter` + + This is the converter that will be used to convert the input and output for the server. + + Possible values are: `aws-apigw-v2`, `aws-apigw-v1`, `aws-cloudfront`, `edge`, `node`, `sqs-revalidate`, `dummy` or a `LazyLoadedOverride` that will return the converter. + + #### `install` + + Install options for the server. This is used to install additional packages to this server + + For image optimization, it will install sharp by default + + ##### `packages` - Mandatory + + This is an array of packages that will be installed in the server. It is an array of string. + Installing stuff on the default server (or one of the splitted one) might require some extra config on Next side to avoid duplicates + + ##### `arch` + + This is the architecture of the server. It is a string and by default, it is set to `x64`. + + Possible values are: `x64`, `arm64` + + TODO: Add the other options and explain how to install packages on the default or splitted server functions + + + + ### `runtime` + + Runtime used for the server. The default server only support `node` or `deno`. + + The `edge` runtime can only be used for splitted server and only support one route per server. + This also requires the route to be using the edge runtime from Next.js. + + Possible values are: `node`, `deno`, `edge` + + ### `placement` + + Option to determine where the server will be deployed. On a single region or on multiple regions at the edge. + + This options does not have any effect on the build output, but is just an indication for IAC tools to know where to deploy the server. + + Possible values are: `regional`, `global` + + ### `experimentalBundledNextServer` + Bundle Next server into a single file. + This results in a way smaller bundle but it might break for some cases. + + This option is deprecated and doesn't work for Next 14.2+. + + ### `override` + + For both default and splitted server, in addition to `override` in the common options, you can also use the following options: + + #### `incrementalCache` + + Add possibility to override the default s3 cache. Used for fetch cache and html/rsc/json cache. + + Possible values are: `s3`, `s3-lite`, `dummy` or a `LazyLoadedOverride` that will return the incremental cache. + + #### `tagCache` + + Add possibility to override the default tag cache. Used for revalidateTags and revalidatePath. + + Possible values are: `dynamodb`, `dynamodb-lite`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. + + #### `queue` + + Add possibility to override the default queue. Used for ISR revalidation requests. + + Possible values are: `sqs`, `sqs-lite`, `dummy` or a `LazyLoadedOverride` that will return the queue. + + + Every splitted server will have the same options as the default server. In addition to that, you can use the following options: + + ### `routes` - Mandatory + + Here you should specify all the routes you want to use. + For app routes, you should use the `app/${name}/route` format or `app/${name}/page` for pages. + For pages, you should use the `page/${name}` format. + + For example: + ```ts + routes: ["app/api/test/route", "app/page", "pages/admin"] + ``` + + ### `patterns` - Mandatory + + Specify the patterns that will be used to match the routes. It is an array of string. + It needs to be cloudfront compatible. + + For example: + ```ts + patterns: [ + // This one will match all the routes that start with /api/ + "/api/*", + // For a single route, this one will only match /page + "/page", + ] + ``` + + + + ### `external` - Mandatory + Only possible value is true. This is used to specify that this server is an external middleware. + + ### `override` + + It uses the same options as the default server. `incrementalCache`, `tagCache` and `queue` are only used when `enableCacheInterception` is set to true. + + ### `originResolver` + + Origin resolver is used to resolve the origin for internal rewrite. By default, it uses the pattern-env origin resolver. + + Possible values are: `pattern-env`, `dummy` or a `LazyLoadedOverride` that will return the origin resolver. + + + Image optimization server is a special server that will handle the `_next/image` optimization. Besides the common options, you can use the following options: + + ### `loader` + The image loader is used to load the image from the source. + + Possible values are: `s3`, `host`, `dummy` or a `LazyLoadedOverride` that will return the loader. + + + Revalidate doesn't have any specific options. It only uses the common options. + + + Warmer is a special server that will be used to warm the lambda function. Besides the common options, you can use the following options: + + ### `invokeFunction` + + By default, works for lambda only. + If you override this, you'll need to handle the warmer event in the wrapper + + Possible values are: `aws-lambda`, `dummy` or a `LazyLoadedOverride` that will return the invoke function. + + + Initialization function is a special server that will run at build time to initialize the cache. By default, it only initializes the tag cache. Besides the common options, you can use the following options: + + ### `tagCache` + + Add possibility to override the default tag cache used for the initialization function. + + Possible values are: `dynamodb`, `dynamodb-lite`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. + + + + + +These options are at the top level of your config object. + +### `buildCommand` + +This is the command that will be run to build your Next.js app. By default, it tries to find your package manager and will run `npm run build`. It supports npm, pnpm, yarn (not pnp) and bun. + +If you want to specify a different command, you can do so here. + +### `appPath` + +The path to the root of the Next.js app's source code. This path is relative from the current process.cwd(). * + +By default, it is set to `.` + +### `buildOutputPath` + +The path to the target folder of build output from the `buildCommand` option (the path which will contain the `.next` and `.open-next` folders). This path is relative from the current process.cwd() + +By default, it is set to `.` + +### `packageJsonPath` + +The path to the package.json file of the Next.js app. This path is relative from the current process.cwd(). + +### `edgeExternals` - Advanced usage + +If you use the edge runtime somewhere (either in the middleware or in the functions), we compile 2 versions of the open-next.config.ts file. One for the node runtime and one for the edge runtime. + +This option allows you to specify the externals for the edge runtime used in esbuild for the compilation of open-next.config.ts +It is especially useful if you use some custom overrides only in node + +### `dangerous` + +These are options that you should only use if you know what you are doing. It can break your app at runtime if not used correctly. +It is also the place where you could find some experimental features. + +--- + + +#### `disableTagCache` + +This will disable the tag cache. You can disable it safely if you only use page router. +It is used for `revalidateTag` and `revalidatePath`. +It's a boolean and by default, it is set to `false`. + + +#### `disableIncrementalCache` + +This will disable the incremental cache. It is generally not recommended, as this is necessary for ISR **AND** SSG routes as well as the fetch cache. +It's a boolean and by default, it is set to `false`. + +#### `enableCacheInterception` - Experimental + +This will enable cache interception. It will allow you to intercept the cache system directly inside OpenNext routing layer and serve the page directly from the cache without going through `NextServer`. + +If the cache interception fail, the request will be forwarded to the `NextServer` as usual. + +#### `headersAndCookiesPriority` + +Function to determine which headers or cookies takes precedence. +By default, the middleware headers and cookies will override the handler headers and cookies. + +This is executed for every request and after next config headers and middleware has executed. +Here is a very simple example of how you can use it: + +```ts +// In this case, if the request starts with /api, the middleware headers and cookies will take precedence otherwise the handler headers and cookies will take precedence +headersAndCookiesPriority: (event) => { + if (event.rawPath.startsWith('/api')) { + return 'middleware'; + } + return 'handler'; +}, +``` + + \ No newline at end of file From 61d651bf6f34f6f170bc746664ede00f7080baa0 Mon Sep 17 00:00:00 2001 From: Agustinus Nathaniel Date: Mon, 18 Nov 2024 21:40:36 +0700 Subject: [PATCH 019/150] docs(netlify): fix typo (#33) --- pages/netlify/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/netlify/index.mdx b/pages/netlify/index.mdx index cd301f5..99d1fb5 100644 --- a/pages/netlify/index.mdx +++ b/pages/netlify/index.mdx @@ -35,7 +35,7 @@ The easiest way to get started is to deploy our Next.js platform starter templat - **App Router:** Netlify fully supports the Next.js App Router, which supports more powerful nested layouts and React’s latest features, such as Server Components and Streaming. -- **Automatic fine-grained caching:** thehe adapter uses fine-grained caching on Netlify to support the Next.js Full Route Cache and Data Cache. This means that static page responses are automatically cached at the edge and can be revalidated by path or by tag. +- **Automatic fine-grained caching:** the adapter uses fine-grained caching on Netlify to support the Next.js Full Route Cache and Data Cache. This means that static page responses are automatically cached at the edge and can be revalidated by path or by tag. - **On-demand and time-based revalidation:** both the App Router and Pages Router support on-demand and time-based revalidation, allowing you to revalidate and regenerate content at any time after a deploy. From c0d3199bbcebb6c995a3b34cca9a4823d9f76888 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Tue, 26 Nov 2024 11:14:39 +0100 Subject: [PATCH 020/150] sync aws doc with code (#34) Co-authored-by: conico974 --- pages/aws/config/custom_overrides.mdx | 38 ++++++++--------- pages/aws/config/full_example.mdx | 28 ++++++------- pages/aws/config/nx.mdx | 42 +++++++++---------- pages/aws/config/simple_example.mdx | 14 +++---- pages/aws/contribute.mdx | 4 +- pages/aws/contribute/local_run.mdx | 20 ++++----- .../aws/inner_workings/cache_interception.mdx | 4 +- 7 files changed, 75 insertions(+), 75 deletions(-) diff --git a/pages/aws/config/custom_overrides.mdx b/pages/aws/config/custom_overrides.mdx index 7e319a9..faac2ca 100644 --- a/pages/aws/config/custom_overrides.mdx +++ b/pages/aws/config/custom_overrides.mdx @@ -3,7 +3,7 @@ import { Callout } from 'nextra/components' In some cases the simple example is not enough, and you want to add more customization to your server. This is where the lazy loaded overrides come in. You can override any part of the server by providing a function that returns a promise that resolves to the override object. This is useful when you want to add custom logic to your server, like adding a custom queue, or adding a custom converter. -Be careful if you use the edge runtime (either in a function or by using the external middleware), we do 2 compilations of the `open-next.config.ts`, one for node and one for the edge runtime. If you're using some custom overrides, you likely want to add +Be careful if you use the edge runtime (either in a function or by using the external middleware), we do 2 compilations of the `open-next.config.ts`, one for node and one for the edge runtime. If you're using some custom overrides, you likely want to add ```ts edgeExternals: ['./customWrapper', './anyOtherOverrideUsed'] ``` @@ -13,14 +13,14 @@ to your `open-next.config.ts` to avoid the edge runtime to try to compile overri ## Custom converter -Sometimes you might want to modify the object received by OpenNext. For example `Config.YOUR_SECRET_KEY` from sst cannot be used in the middleware, so you might want to add it to the headers. This is where the custom converter comes in. You can add a custom converter to modify the object before it is passed to OpenNext. +Sometimes you might want to modify the object received by OpenNext. For example `Config.YOUR_SECRET_KEY` from sst cannot be used in the middleware, so you might want to add it to the headers. This is where the custom converter comes in. You can add a custom converter to modify the object before it is passed to OpenNext. You'll still have to use a fallback value during dev as this is not used by the dev server. ```ts // customConverter.ts -import converter from 'open-next/converters/aws-apigw-v2.js' -import type { Converter } from 'open-next/types/open-next' +import converter from '@opennextjs/aws/overrides/converters/aws-apigw-v2.js' +import type { Converter } from '@opennextjs/aws/types/overrides.js' import { Config } from 'sst/node/Config' const mySecretKey = Config.YOUR_SECRET_KEY @@ -28,7 +28,7 @@ export default { convertFrom: async (event) => { const result = await converter.convertFrom(event) return { - ...result, + ...result, headers: { ...result.headers, 'inserted-in-converter': '1', @@ -52,7 +52,7 @@ export default { ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js' const config = { default: { @@ -70,7 +70,7 @@ Here we provide a few examples for some custom wrapper. ```ts // customWrapper.ts -import defaultWrapper from 'open-next/wrappers/aws-lambda.js' +import defaultWrapper from '@opennextjs/aws/overrides/wrappers/aws-lambda.js' //Here you can define some globals declare global { @@ -88,7 +88,7 @@ export default defaultWrapper ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js' const config = { default: { override: { @@ -106,8 +106,8 @@ import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' // Here you need to mock the global if not present -// One way to avoid issues with different implementation would be to create an api endpoint -// that uses the exact same logic as the global you defined earlier, +// One way to avoid issues with different implementation would be to create an api endpoint +// that uses the exact same logic as the global you defined earlier, // and that is only available during development i.e. /api/dev/myApi if(!globalThis.myApi) { globalThis.myApi = async () => { @@ -117,7 +117,7 @@ if(!globalThis.myApi) { export function middleware(request: NextRequest) { // You can also send an error in the api endpoint itself - // Or you could add all the dev endpoint in their own lambda + // Or you could add all the dev endpoint in their own lambda // that you do not deploy in production if(request.nextUrl.pathname.startsWith('/api/dev') && process.env.NODE_ENV === 'production') { return NextResponse('This route is only available in development',{ @@ -129,7 +129,7 @@ export function middleware(request: NextRequest) { // ... your code here } - + ``` @@ -137,8 +137,8 @@ export function middleware(request: NextRequest) { ```ts // customWrapper.ts -import streamingWrapper from 'open-next/wrappers/aws-lambda.js' -import {WrapperHandler} from 'open-next/types/open-next' +import streamingWrapper from '@opennextjs/aws/overrides/wrappers/aws-lambda.js' +import type { WrapperHandler } from '@opennextjs/aws/types/overrides.js' import middy from '@middy/core' import httpSecurityHeaders from '@middy/http-security-headers' @@ -158,7 +158,7 @@ export default { ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js' const config = { default: { override: { @@ -182,11 +182,11 @@ import type { APIGatewayProxyEventV2, APIGatewayProxyResultV2, } from "aws-lambda"; -import type { StreamCreator } from "open-next/http/openNextResponse"; +import type { StreamCreator } from "@opennextjs/aws/http/openNextResponse.js"; import { Writable } from "node:stream"; -import { WarmerEvent, WarmerResponse } from "open-next/adapters/warmer-function"; -import type { WrapperHandler } from "open-next/types/open-next"; +import { WarmerEvent, WarmerResponse } from "@opennextjs/aws/adapters/warmer-function.js"; +import type { WrapperHandler } from "@opennextjs/aws/types/overrides.js"; type AwsLambdaEvent = | APIGatewayProxyEventV2 @@ -268,7 +268,7 @@ export default { ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js' const config = { default: { override: { diff --git a/pages/aws/config/full_example.mdx b/pages/aws/config/full_example.mdx index e0ace38..1415679 100644 --- a/pages/aws/config/full_example.mdx +++ b/pages/aws/config/full_example.mdx @@ -1,4 +1,4 @@ -Here is a detailed example of an `open-next.config.ts` file: +Here is a detailed example of an `open-next.config.ts` file: This file need to be at the same place as your `next.config.js` file `server` in here could refer to a lambda function, a docker container, a node server or whatever that can support running nodejs code. (Even cloudflare workers in the future) @@ -6,12 +6,12 @@ This file need to be at the same place as your `next.config.js` file For more information about the options here, take a look at the [components section](/aws/components/overview). ```ts -import type { OpenNextConfig } from 'open-next/types/open-next' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js' const config = { default: { // This is the default server, similar to the server-function in open-next v2 - // You don't have to provide the below, by default it will generate an output + // You don't have to provide the below, by default it will generate an output // for normal lambda as in open-next v2 - override: { + override: { wrapper: "aws-lambda-streaming", // This is necessary to enable lambda streaming // You can override any part that is a `LazyLoadedOverride` this way queue: () => Promise.resolve({ @@ -24,7 +24,7 @@ const config = { }, // Below we define the functions that we want to deploy in a different server // This is only used if you want to split the server into multiple servers - functions: { + functions: { ssr: { routes: [ "app/api/isr/route", "app/api/sse/route", "app/api/revalidateTag/route", // app dir Api routes @@ -37,7 +37,7 @@ const config = { }, // This enables the bundled next server which is faster and reduce the size of the server // This is also experimental and might not work in all cases - experimentalBundledNextServer: true + experimentalBundledNextServer: true }, pageSsr: { routes: ["pages/pageSsr"], // For page dir routes should be in the form `pages/${route}` without the extension, it should match the filesystem @@ -56,24 +56,24 @@ const config = { routes: ["app/ssr/page"], patterns: ["ssr"], override: {} - } + } }, - // By setting this, it will create another bundle for the middleware, - // and the middleware will be deployed in a separate server. + // By setting this, it will create another bundle for the middleware, + // and the middleware will be deployed in a separate server. // If not set middleware will be bundled inside the servers // It could be in lambda@edge, cloudflare workers, or anywhere else // By default it uses lambda@edge // This is not implemented in the reference construct implementation. // This is optional, but might be necessary if you split your app into multiple servers middleware: { - external: true + external: true } // Optional imageOptimization: { // This is the architecture of the image, it could be x64 or arm64 // This is necessary to bundle the proper version of sharp - arch: "x64", + arch: "x64", } // If you want to override the default build command, you can do it here @@ -83,14 +83,14 @@ const config = { dangerous: { // This will disable the tag cache // You can use it safely on page router, on app router it will break revalidateTag and revalidatePath - disableTagCache: true, + disableTagCache: true, // This will disable the incremental cache // This is generally not recommended, as this is necessary for ISR AND SSG routes as well as the fetch cache - disableIncrementalCache: true, + disableIncrementalCache: true, } //The path to the target folder of build output from the `buildCommand` option (the path which will contain the `.next` and `.open-next` folders). This path is relative from the current process.cwd() - Optional default to "." - buildOutputPath: "build", + buildOutputPath: "build", //The path to the root of the Next.js app's source code. This path is relative from the current process.cwd(). - Optional default to "." appPath: "app", diff --git a/pages/aws/config/nx.mdx b/pages/aws/config/nx.mdx index a0d034a..0493b2a 100644 --- a/pages/aws/config/nx.mdx +++ b/pages/aws/config/nx.mdx @@ -3,14 +3,14 @@ Here's a detailed exampled of how to add open-next + SST to an existing Nx works 1. install `open-next`: `pnpm add —save-dev open-next` -2. Update your `apps/next-site/next.config.js` add `output: ‘standalone’`, and you want to add `experimental.outputFileTracingRoot`, it should look a little like this: +2. Update your `apps/next-site/next.config.js` add `output: ‘standalone’`, and you want to add `experimental.outputFileTracingRoot`, it should look a little like this: ```javascript //@ts-check - + // eslint-disable-next-line @typescript-eslint/no-var-requires const { composePlugins, withNx } = require('@nx/next'); const { join } = require('node:path'); - + /** * @type {import('@nx/next/plugins/with-nx').WithNxOptions} **/ @@ -26,18 +26,18 @@ const nextConfig = { + outputFileTracingRoot: join(__dirname, '../../'), + }, }; - + const plugins = [ // Add more Next.js plugins to this list if needed. withNx, ]; - + module.exports = composePlugins(...plugins)(nextConfig); ``` -3. Create `open-next.config.js` inside your apps root directory, it should look a little something like this: +3. Create `open-next.config.js` inside your apps root directory, it should look a little something like this: ```javascript -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; const config = { default: {}, @@ -50,13 +50,13 @@ const config = { export default config; ``` -4. Set up nx's targets/tasks +4. Set up nx's targets/tasks Now we have open-next configuration set up, you can try to run `open-next build` and depending on whether you have already built your next app or not -it might even work. +it might even work. However, we don't want to rely on needing to manually running a build every time we want to deploy a change, so instead we can set up a target. -We do this in your project's `project.json` (in this case, living at `apps/next-site/project`), we want to find the targets object and update it: +We do this in your project's `project.json` (in this case, living at `apps/next-site/project`), we want to find the targets object and update it: ```diff { "name": "next-site", @@ -66,7 +66,7 @@ We do this in your project's `project.json` (in this case, living at `apps/next- "tags": [], "targets": { + "open-next-build": { // name of the target, this is what you will call -+ "executor": "nx:run-commands", ++ "executor": "nx:run-commands", + "dependsOn": ["build"], // this ensures that Nx will build our next app before running this command. + "cache": true, // cache the output, good for if you want to use DTE/Nx cloud + "outputs": ["{projectRoot}/.open-next"], // tell nx where the output lives @@ -79,7 +79,7 @@ We do this in your project's `project.json` (in this case, living at `apps/next- } ``` -Next we need to add the open-next directory to our eslint's `ignorePatterns` array +Next we need to add the open-next directory to our eslint's `ignorePatterns` array ```diff { "extends": [ @@ -120,13 +120,13 @@ now, when you run `nx open-next-build next-site`, nx will automatically build th 5. Deploying with SST -Now, we have a built app, ready to deploy, so how do we get it onto SST/AWS ? Good question! +Now, we have a built app, ready to deploy, so how do we get it onto SST/AWS ? Good question! We are using `sst ion` in this example. i will assume you have already have the cli installed, (if not, check here on how!)[https://ion.sst.dev/], but we will not use the SST cli to init this project, because it wants to add a package.json to your next app, and it will look like it's working, but you will end up with a big far server error (all because the package.json overrides whatever nx _thinks_ there should be, and it will miss a bunch of dependencies). we will instead manually set this up: - let's add the sst package with `pnpm add sst@ion`, and the required packages for SST to work with AWS `pnpm add --save-dev aws-cdk-lib constructs @types/aws-lambda` -- then we want to manually create an `sst.config.ts` file in `apps/next-site` that looks like this: +- then we want to manually create an `sst.config.ts` file in `apps/next-site` that looks like this: ```typescript /// @@ -150,7 +150,7 @@ export default $config({ - now, you probably see some type errors, as SST is not initialized yet, but we can resolve this by running ```bash -$ cd apps/next-site && sst install +$ cd apps/next-site && sst install ``` this will resolve the type issues and initialise SST. @@ -197,7 +197,7 @@ this will resolve the type issues and initialise SST. } ``` -- now, if you want to run `sst dev` you can do so with `sst dev "nx dev next-site"` similarly deploying can be done with `sst deploy`...but you probably want to set up that task chaining, again we can do that by adding a target to your app, and setting it's `dependsOn` to the `open-next-build`, here's what it might look like: +- now, if you want to run `sst dev` you can do so with `sst dev "nx dev next-site"` similarly deploying can be done with `sst deploy`...but you probably want to set up that task chaining, again we can do that by adding a target to your app, and setting it's `dependsOn` to the `open-next-build`, here's what it might look like: ```diff { @@ -208,9 +208,9 @@ this will resolve the type issues and initialise SST. "tags": [], "targets": { "open-next-build": { - "executor": "nx:run-commands", + "executor": "nx:run-commands", "dependsOn": ["build"], - "cache": true, + "cache": true, "outputs": ["{projectRoot}/.open-next"], "options": { "cwd": "apps/next-site", @@ -234,7 +234,7 @@ this will resolve the type issues and initialise SST. + "args": ["--stage=staging"] + }, + "dev": { -+ "args": ["--stage=development"] ++ "args": ["--stage=development"] + } + } + } @@ -244,9 +244,9 @@ this will resolve the type issues and initialise SST. ``` -now we can run (or if you want a custom stage, you can simply do `nx deploy next-site --stage this-is-my-stage` and it will be passed directly to the sst command). +now we can run (or if you want a custom stage, you can simply do `nx deploy next-site --stage this-is-my-stage` and it will be passed directly to the sst command). ```bash $ nx deploy next-site --configuration dev # using dev configuration (which sets the stage to development) # nx deploy next-site -c dev # OR -# nx deploy next-site --stage my-stage # Custom Stage +# nx deploy next-site --stage my-stage # Custom Stage ``` \ No newline at end of file diff --git a/pages/aws/config/simple_example.mdx b/pages/aws/config/simple_example.mdx index 5fde1fe..0ba089d 100644 --- a/pages/aws/config/simple_example.mdx +++ b/pages/aws/config/simple_example.mdx @@ -22,7 +22,7 @@ Here you can find the most common `open-next.config.ts` file examples that you c ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.ts'; const config = { default: { override: { @@ -37,7 +37,7 @@ export default config; ## Splitting the server ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; const config = { // This is the default server, similar to the server-function in open-next v2 // In this case we are not providing any override, so it will generate a normal lambda (i.e. no streaming) @@ -72,7 +72,7 @@ export default config;
```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; const config = { default: { override: { @@ -89,7 +89,7 @@ export default config; ## Running in Lambda@Edge ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; const config = { default: { placement: 'global', @@ -111,7 +111,7 @@ Be aware that this uses the exact same system for ISR/SSG as the default lambda ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; const config = { // In this case, the default server is meant to run as a classic Node server // To execute the server you need to run `node index.mjs` inside `.open-next/server-functions/default` @@ -146,7 +146,7 @@ This will generate 2 server functions, the default one and the edge one. The edg Edge runtime function have less cold start time, but you can only deploy one route per function. They also do not have the middleware bundled in the function, so you need to use external middleware if you need it in front of the edge function. ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; const config = { default: {}, functions: { @@ -169,7 +169,7 @@ With the default middleware configuration, it is bundled for a deployment in lam This is how you can do it: ```ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; const config = { default: {}, functions: { diff --git a/pages/aws/contribute.mdx b/pages/aws/contribute.mdx index 7c78267..eb47b23 100644 --- a/pages/aws/contribute.mdx +++ b/pages/aws/contribute.mdx @@ -3,7 +3,7 @@ To run `OpenNext` locally: 1. Clone [this repository](https://github.com/opennextjs/opennextjs-aws). 2. Build `open-next`: ```bash - cd open-next + cd opennextjs-aws pnpm build ``` 3. Run `open-next` in watch mode: @@ -13,7 +13,7 @@ To run `OpenNext` locally: 4. Now, you can make changes in `open-next` and build your Next.js app to test the changes. ```bash cd path/to/my/nextjs/app - path/to/open-next/packages/open-next/dist/index.js build + path/to/opennextjs-aws/packages/open-next/dist/index.js build ``` It can be a bit cumbersome to need to deploy every time you want to test changes. If your change is not dependent on the wrapper or the converter, then you can create a custom `open-next.config.ts` file, you can take a look [here](/aws/contribute/local_run) for more information. diff --git a/pages/aws/contribute/local_run.mdx b/pages/aws/contribute/local_run.mdx index 4a46179..666532b 100644 --- a/pages/aws/contribute/local_run.mdx +++ b/pages/aws/contribute/local_run.mdx @@ -3,16 +3,16 @@ When making some changes to OpenNext, it can be a bit cumbersome to need to depl To run `OpenNext` locally: ```bash # This is to build (the config-path is needed if you use a different name than the default one) -node /path/to/open-next/packages/open-next/dist/index.js build --config-path open-next.local.config.ts +node /path/to/opennextjs-aws/packages/open-next/dist/index.js build --config-path open-next.local.config.ts # Then to run the server node .open-next/server-functions/default/index.mjs ``` ```typescript -// open-next.local.config.ts - -// A good practice would be to use a different name so that it doesn't conflict +// open-next.local.config.ts - +// A good practice would be to use a different name so that it doesn't conflict // with your existing open-next.config.ts i.e. open-next.local.config.ts -import type {OpenNextConfig} from 'open-next/types/open-next' +import type {OpenNextConfig} from '@opennextjs/aws/types/open-next.js' const config = { default: { @@ -60,13 +60,13 @@ export default config // dev/wrapper.ts // You'll need to install express import express from 'express' -// The proxy is used to proxy the image optimization server +// The proxy is used to proxy the image optimization server // you don't have to use it, but image request will return 500 error import proxy from 'express-http-proxy' import { fork } from 'child_process' -import type { StreamCreator } from "open-next/http/openNextResponse"; -import type { WrapperHandler } from "open-next/types/open-next"; +import type { StreamCreator } from "@opennextjs/aws/http/openNextResponse.js"; +import type { WrapperHandler } from "@opennextjs/aws/types/overrides.js"; const wrapper: WrapperHandler = async (handler, converter) => { const app = express(); @@ -120,7 +120,7 @@ export default { ```typescript // dev/incrementalCache.ts -import type {IncrementalCache} from 'open-next/cache/incremental/types' +import type { IncrementalCache } from '@opennextjs/aws/types/overrides.js' import fs from 'node:fs/promises' import path from 'node:path' @@ -157,7 +157,7 @@ export default cache ```typescript // dev/queue.ts -import type {Queue} from 'open-next/queue/types' +import type { Queue } from '@opennextjs/aws/types/overrides.js' declare global { // This is declared in the global scope so that we can use it in the queue @@ -168,7 +168,7 @@ declare global { const queue: Queue = { name: 'dev-queue', send: async (message) => { - const prerenderManifest = (await import('open-next/adapters/config')).PrerenderManifest as any + const prerenderManifest = (await import('@opennextjs/aws/adapters/config.js')).PrerenderManifest as any const revalidateId : string = prerenderManifest.preview.previewModeId await globalThis.internalFetch(`http://localhost:3000${message.MessageBody.url}`, { method: "HEAD", diff --git a/pages/aws/inner_workings/cache_interception.mdx b/pages/aws/inner_workings/cache_interception.mdx index d0fbb1e..d19ec18 100644 --- a/pages/aws/inner_workings/cache_interception.mdx +++ b/pages/aws/inner_workings/cache_interception.mdx @@ -16,7 +16,7 @@ To enable cache interception, you need to add `enableCacheInterception` option i ```ts // open-next.config.ts -import type { OpenNextConfig } from 'open-next/types/open-next'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; const config = { default: { }, @@ -24,7 +24,7 @@ const config = { enableCacheInterception: true, }, } satisfies OpenNextConfig; - + export default config; ``` From 23e910f1277fec997900afeae15f0baaf6f38091 Mon Sep 17 00:00:00 2001 From: conico974 Date: Tue, 26 Nov 2024 12:14:03 +0100 Subject: [PATCH 021/150] Docs(aws): custom overrides for aws (#35) Co-authored-by: Victor Berchet --- pages/aws/config/_meta.json | 3 ++- pages/aws/config/overrides/_meta.json | 11 ++++++++++ pages/aws/config/overrides/converter.mdx | 9 ++++++++ pages/aws/config/overrides/image_loader.mdx | 5 +++++ .../config/overrides/incremental_cache.mdx | 8 +++++++ .../aws/config/overrides/invoke_function.mdx | 5 +++++ .../aws/config/overrides/origin_resolver.mdx | 6 +++++ .../overrides/proxy_external_request.mdx | 3 +++ pages/aws/config/overrides/queue.mdx | 8 +++++++ pages/aws/config/overrides/tag_cache.mdx | 12 ++++++++++ pages/aws/config/overrides/wrapper.mdx | 9 ++++++++ pages/aws/config/reference.mdx | 22 ++++++++++++------- pages/aws/contribute/local_run.mdx | 7 +++++- 13 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 pages/aws/config/overrides/_meta.json create mode 100644 pages/aws/config/overrides/converter.mdx create mode 100644 pages/aws/config/overrides/image_loader.mdx create mode 100644 pages/aws/config/overrides/incremental_cache.mdx create mode 100644 pages/aws/config/overrides/invoke_function.mdx create mode 100644 pages/aws/config/overrides/origin_resolver.mdx create mode 100644 pages/aws/config/overrides/proxy_external_request.mdx create mode 100644 pages/aws/config/overrides/queue.mdx create mode 100644 pages/aws/config/overrides/tag_cache.mdx create mode 100644 pages/aws/config/overrides/wrapper.mdx diff --git a/pages/aws/config/_meta.json b/pages/aws/config/_meta.json index 662c997..61715fd 100644 --- a/pages/aws/config/_meta.json +++ b/pages/aws/config/_meta.json @@ -3,5 +3,6 @@ "custom_overrides": "Custom Overrides", "reference": "Reference", "full_example": "Full Example", - "nx": "Nx Monorepo" + "nx": "Nx Monorepo", + "overrides": "Overrides" } \ No newline at end of file diff --git a/pages/aws/config/overrides/_meta.json b/pages/aws/config/overrides/_meta.json new file mode 100644 index 0000000..b936b59 --- /dev/null +++ b/pages/aws/config/overrides/_meta.json @@ -0,0 +1,11 @@ +{ + "wrapper": "Wrapper", + "converter": "Converter", + "incremental_cache": "Incremental Cache", + "tag_cache": "Tag Cache", + "queue": "Revalidation Queue", + "image_loader": "Image Loader", + "proxy_external_request": "External Request Proxy", + "origin_resolver": "Origin Resolver", + "invoke_function": "Invoke Function for the warmer" +} \ No newline at end of file diff --git a/pages/aws/config/overrides/converter.mdx b/pages/aws/config/overrides/converter.mdx new file mode 100644 index 0000000..ca2e624 --- /dev/null +++ b/pages/aws/config/overrides/converter.mdx @@ -0,0 +1,9 @@ +This override is meant to convert request and response provided from your wrapper to the internal types that are used by OpenNext. + +If you want to better understand how to implement your own Converter, the easiest way would be to take a look at one of the existing [included Converter](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/converters) + +Couple of things to note : +- If you use a `StreamCreator` in your wrapper, you probably don't need to do anything in the `convertTo` function. +- If used for the default, the image optimization, or one of the splitted server the internal types will be `InternalEvent` and `InternalResult` respectively. +- If used for the external middleware, the internal types will be `InternalEvent` and `InternalResult | MiddlewareOutputEvent` respectively. +- For the other servers, look up their respective types in the codebase. \ No newline at end of file diff --git a/pages/aws/config/overrides/image_loader.mdx b/pages/aws/config/overrides/image_loader.mdx new file mode 100644 index 0000000..459b14c --- /dev/null +++ b/pages/aws/config/overrides/image_loader.mdx @@ -0,0 +1,5 @@ +This override is used by OpenNext and more specifically by the image server to be able to load images from a custom source. Images are not bundled with the image server and are loaded from the source specified in the override. + +This is used for internal image only (i.e. src without host). External source are already handled by the image server. + +If you want to better understand how to implement your own ImageLoader, the easiest way would be to take a look at the existing [included ImageLoader](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/imageLoader). \ No newline at end of file diff --git a/pages/aws/config/overrides/incremental_cache.mdx b/pages/aws/config/overrides/incremental_cache.mdx new file mode 100644 index 0000000..de287ce --- /dev/null +++ b/pages/aws/config/overrides/incremental_cache.mdx @@ -0,0 +1,8 @@ +This override is used by the [`cache` adapter](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/adapters/cache.ts) that is provided by OpenNext to the NextServer. It is also used by OpenNext if `enableCacheInterception` is set to `true` in the configuration. + +It is used for retrieving and updating the ISR/SSG cache as well as the fetch cache used by Next.js. It does not handle anything related to cache tags (i.e. `revalidateTag` and `revalidatePath`) + +If you want to better understand how to implement your own IncrementalCache, the easiest way would be to take a look at the existing [included IncrementalCache](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/incrementalCache). + +One thing to note is that it is not used at build time, only at runtime. This means that you'll have to upload the cache yourself if you want to use the prebuilt routes/pages (And this is mandatory for ISR/SSG routes with `fallback:false`). +All the cache files are present in the `.open-next/cache` folder. The one under `BUILD_ID` are for the ISR/SSG cache and the one under `__fetch/BUILD_ID` are for the fetch cache. \ No newline at end of file diff --git a/pages/aws/config/overrides/invoke_function.mdx b/pages/aws/config/overrides/invoke_function.mdx new file mode 100644 index 0000000..ce7e464 --- /dev/null +++ b/pages/aws/config/overrides/invoke_function.mdx @@ -0,0 +1,5 @@ +This override is used by OpenNext to invoke the function for warmup purposes. It is only used in the warmer server. + +If you want to better understand how to implement your own InvokeFunction, the easiest way would be to take a look at the existing [included InvokeFunction](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/warmer). + +You could override this to provide some custom logic to invoke more or less function depending on the hour for example. diff --git a/pages/aws/config/overrides/origin_resolver.mdx b/pages/aws/config/overrides/origin_resolver.mdx new file mode 100644 index 0000000..09737cc --- /dev/null +++ b/pages/aws/config/overrides/origin_resolver.mdx @@ -0,0 +1,6 @@ +This override is used by OpenNext to resolve the origin of the request. This is for internal requests only and is needed to support the `external` middleware. +This is only used by the external middleware. + +At build time, we may not know where the splitted server will be deployed, so we need to resolve the origin at runtime. This is why we need this override. The origin is resolved by this override will need to be handled by the wrapper used. At the moment, only the `aws-cloudfront` and the `cloudflare-edge` wrapper are able to do so. + +If you want to better understand how to implement your own OriginResolver, the easiest way would be to take a look at the existing [included OriginResolver](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/originResolver). \ No newline at end of file diff --git a/pages/aws/config/overrides/proxy_external_request.mdx b/pages/aws/config/overrides/proxy_external_request.mdx new file mode 100644 index 0000000..f9e3a16 --- /dev/null +++ b/pages/aws/config/overrides/proxy_external_request.mdx @@ -0,0 +1,3 @@ +This override is used by OpenNext to proxy rewritten requests to external services. It is used either in the `external` middleware (if set) or in the default/splitted server if the middleware is bundled. + +If you want to better understand how to implement your own ProxyExternalRequest, the easiest way would be to take a look at the existing [included ProxyExternalRequest](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/proxyExternalRequest). \ No newline at end of file diff --git a/pages/aws/config/overrides/queue.mdx b/pages/aws/config/overrides/queue.mdx new file mode 100644 index 0000000..359ac8c --- /dev/null +++ b/pages/aws/config/overrides/queue.mdx @@ -0,0 +1,8 @@ +This override is used by OpenNext to trigger the revalidation of stale routes. +Before sending the response to the client, OpenNext will check if the route is stale and if it is, it will call the queue override to revalidate the route. + +If you want to better understand how to implement your own Queue, the easiest way would be to take a look at the existing [included Queue](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/queue). + +Couple of things to note : +- The default implementation use an SQS queue. This has the main advantage of being able to control the concurrency of the revalidations as well as avoiding trigerring the revalidation multiple times for the same route. +- You don't have to use a queue at all. You could trigger the revalidation directly in the Queue override itself. You can see a very simple implementation of this [in the `queue` override](/aws/contribute/local_run#devqueuets). \ No newline at end of file diff --git a/pages/aws/config/overrides/tag_cache.mdx b/pages/aws/config/overrides/tag_cache.mdx new file mode 100644 index 0000000..7cd278a --- /dev/null +++ b/pages/aws/config/overrides/tag_cache.mdx @@ -0,0 +1,12 @@ +This override is used by the [`cache` adapter](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/adapters/cache.ts) that is provided by OpenNext to the NextServer. It is also used by OpenNext if `enableCacheInterception` is set to `true` in the configuration and by the `initializationFunction` for prepopulating the cache. + +It is used for the cache tags (i.e. `revalidateTag` and `revalidatePath`). It does not handle anything related to the ISR/SSG cache or the fetch cache used by Next.js. +It's main role is to detremine if a path is stale based on the tags and also to update the tag cache when `revalidateTag` is called. + +The current implementation differs from the way Next.js standalone handle cache tags. In the standalone version, the cache tags are stored in a file, and every time a cache entry is accessed, it has to check for every tags if the entry is stale. This approach is very read heavy and doesn't work well with DB like DynamoDB. +We choose to go another way. We store tags for every path that exists in the cache. This way, we can easily know if a path is stale by just checking the path instead of every tags used. This approach is more write heavy but it's a tradeoff we are willing to make. +This also has the drawback of needing to prepopulate the cache with all the tags that are used in the application. This is done by the `initializationFunction`. + +We might allow to choose how cache tags are handled in the future depending on the `TagCache` implementation. If you need this feature, feel free to open an issue on the [GitHub repository](https://github.com/opennextjs/opennextjs-aws). + +If you want to better understand how to implement your own TagCache, the easiest way would be to take a look at the existing [included TagCache](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/tagCache). \ No newline at end of file diff --git a/pages/aws/config/overrides/wrapper.mdx b/pages/aws/config/overrides/wrapper.mdx new file mode 100644 index 0000000..913edcb --- /dev/null +++ b/pages/aws/config/overrides/wrapper.mdx @@ -0,0 +1,9 @@ +This is the main entrypoint of the server. It is used for every server and allow you to run either in serverless mode or as a long running server. + +If you want to better understand how to implement your own Wrapper, the easiest way would be to take a look at one of the existing [included Wrapper](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/wrappers). + +Couple of things to note : +- If you want to use streaming (for the `node` runtime of next), you'll need to create a `StreamCreator` and pass it to the `handler`. You can find some example in the [node](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/wrappers/node.ts) or [aws-lambda-streaming](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/wrappers/aws-lambda-streaming.ts) wrapper. +- If you don't use streaming (like in the default `aws-lambda` wrapper), you may still need to provide a fake `StreamCreator` to the `handler` to avoid a weird issue with Node itself (see [here](https://github.com/opennextjs/opennextjs-aws/blob/f685ddea8f8a5c82591dc02713aff7138f2d9896/packages/open-next/src/overrides/wrappers/aws-lambda.ts#L49-L65) for an example and a more thorough explanation). +- If you use the `edge` runtime of Next (either for the external middleware or for an `edge` route or page), you don't need the `StreamCreator` at all. +- If you are in a serverless environment and it supports `waitUntil`, you should define it here(see [here](https://github.com/opennextjs/opennextjs-aws/blob/f685ddea8f8a5c82591dc02713aff7138f2d9896/packages/open-next/src/overrides/wrappers/cloudflare.ts#L29)). This might not be necessary depending on where you run it (for example the `aws-lambda-streaming` or the `node` wrapper doesn't need it.) diff --git a/pages/aws/config/reference.mdx b/pages/aws/config/reference.mdx index 912547a..ce2cc89 100644 --- a/pages/aws/config/reference.mdx +++ b/pages/aws/config/reference.mdx @@ -38,14 +38,14 @@ import { Tabs } from 'nextra/components' --- - #### `wrapper` + #### [`wrapper`](overrides/wrapper) This is the entrypoint of the server. Be aware that it might not be enough to change this to make it work on said platform. This is only the entrypoint, you might need to change other parts of the server to make it work on the platform. Possible values are: `aws-lambda`, `aws-lambda-streaming`, `node`, `cloudflare`, `dummy` or a `LazyLoadedOverride` that will return the wrapper. - #### `converter` + #### [`converter`](overrides/converter) This is the converter that will be used to convert the input and output for the server. @@ -99,23 +99,29 @@ import { Tabs } from 'nextra/components' For both default and splitted server, in addition to `override` in the common options, you can also use the following options: - #### `incrementalCache` + #### [`incrementalCache`](overrides/incremental_cache) Add possibility to override the default s3 cache. Used for fetch cache and html/rsc/json cache. Possible values are: `s3`, `s3-lite`, `dummy` or a `LazyLoadedOverride` that will return the incremental cache. - #### `tagCache` + #### [`tagCache`](overrides/tag_cache) Add possibility to override the default tag cache. Used for revalidateTags and revalidatePath. Possible values are: `dynamodb`, `dynamodb-lite`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. - #### `queue` + #### [`queue`](overrides/queue) Add possibility to override the default queue. Used for ISR revalidation requests. Possible values are: `sqs`, `sqs-lite`, `dummy` or a `LazyLoadedOverride` that will return the queue. + + #### [`proxyExternalRequest`](overrides/proxy_external_request) + + Add possibility to override the default proxy for external request (i.e. next config external rewrites or middleware rewrites). Used in the external middleware or one of the server function. + + Possible values are: `node`, `fetch`, `dummy` or a `LazyLoadedOverride` that will return the proxy. Default is `node` Every splitted server will have the same options as the default server. In addition to that, you can use the following options: @@ -155,7 +161,7 @@ import { Tabs } from 'nextra/components' It uses the same options as the default server. `incrementalCache`, `tagCache` and `queue` are only used when `enableCacheInterception` is set to true. - ### `originResolver` + ### [`originResolver`](overrides/origin_resolver) Origin resolver is used to resolve the origin for internal rewrite. By default, it uses the pattern-env origin resolver. @@ -164,7 +170,7 @@ import { Tabs } from 'nextra/components' Image optimization server is a special server that will handle the `_next/image` optimization. Besides the common options, you can use the following options: - ### `loader` + ### [`loader`](overrides/image_loader) The image loader is used to load the image from the source. Possible values are: `s3`, `host`, `dummy` or a `LazyLoadedOverride` that will return the loader. @@ -175,7 +181,7 @@ import { Tabs } from 'nextra/components' Warmer is a special server that will be used to warm the lambda function. Besides the common options, you can use the following options: - ### `invokeFunction` + ### [`invokeFunction`](overrides/invoke_function) By default, works for lambda only. If you override this, you'll need to handle the warmer event in the wrapper diff --git a/pages/aws/contribute/local_run.mdx b/pages/aws/contribute/local_run.mdx index 666532b..f73d733 100644 --- a/pages/aws/contribute/local_run.mdx +++ b/pages/aws/contribute/local_run.mdx @@ -7,7 +7,7 @@ node /path/to/opennextjs-aws/packages/open-next/dist/index.js build --config-pat # Then to run the server node .open-next/server-functions/default/index.mjs ``` - +### open-next.local.config.ts ```typescript // open-next.local.config.ts - // A good practice would be to use a different name so that it doesn't conflict @@ -56,6 +56,8 @@ const config = { export default config ``` +### dev/wrapper.ts + ```typescript // dev/wrapper.ts // You'll need to install express @@ -118,6 +120,7 @@ export default { }; ``` +### dev/incrementalCache.ts ```typescript // dev/incrementalCache.ts import type { IncrementalCache } from '@opennextjs/aws/types/overrides.js' @@ -155,6 +158,8 @@ const cache: IncrementalCache = { export default cache ``` +### dev/queue.ts + ```typescript // dev/queue.ts import type { Queue } from '@opennextjs/aws/types/overrides.js' From 586372a547f4c2f7554a3c6c36df8ba80a223f31 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 29 Nov 2024 14:43:45 +0100 Subject: [PATCH 022/150] update the worker free plan size limit (#36) --- pages/cloudflare/troubleshooting.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pages/cloudflare/troubleshooting.mdx b/pages/cloudflare/troubleshooting.mdx index 1c06e1e..57f9770 100644 --- a/pages/cloudflare/troubleshooting.mdx +++ b/pages/cloudflare/troubleshooting.mdx @@ -11,11 +11,11 @@ Cloudflare Workers now support the majority of functionality from Cloudflare Pag If you need to deploy to Cloudflare Pages, you can use `@cloudflare/next-on-pages`, and follow the [Cloudflare Pages guides for deploying Next.js apps](https://developers.cloudflare.com/pages/framework-guides/nextjs/). -### "Your Worker exceeded the size limit of 1 MiB" +### "Your Worker exceeded the size limit of 3 MiB" -The Cloudflare Account you are deploying to is on the Workers Free plan, which [limits the size of each Worker to 1 MiB](https://developers.cloudflare.com/workers/platform/limits/#worker-size). When you subscribe to the Workers Paid plan, each Worker can be up to 10 MiB. +The Cloudflare Account you are deploying to is on the Workers Free plan, which [limits the size of each Worker to 3 MiB](https://developers.cloudflare.com/workers/platform/limits/#worker-size). When you subscribe to the Workers Paid plan, each Worker can be up to 10 MiB. -### My app fails to build when I import a specific NPM package +### My app fails to build when I import a specific NPM package First, make sure that the `nodejs_compat` compatibility flag is enabled, and your compatibility date is set to on or after "2024-09-23", in your `wrangler.toml` file. [Refer to the Workers docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) for more details on Node.js support in Cloudflare Workers. @@ -30,7 +30,7 @@ Some NPM packages define multiple exports. For example: }, ``` -When you use `@opennextjs/cloudflare`, [Wrangler](https://developers.cloudflare.com/workers/wrangler/) bundles your code before running it locally, or deploying it to Cloudflare. Wrangler has to choose which export to use, when you import a module. By default, Wrangler, which uses [esbuild](https://esbuild.github.io/), handles this in a way that is not compatible with some NPM packages. +When you use `@opennextjs/cloudflare`, [Wrangler](https://developers.cloudflare.com/workers/wrangler/) bundles your code before running it locally, or deploying it to Cloudflare. Wrangler has to choose which export to use, when you import a module. By default, Wrangler, which uses [esbuild](https://esbuild.github.io/), handles this in a way that is not compatible with some NPM packages. You may want to modify how Wrangler resolves multiple exports, such that when you import packages, the `node` export, if present, is used. You can do do by defining the following variables in a `.env` file within the root directory of your Next.js app: From af52ef07b98381130a5688c026cec6bb5699f5da Mon Sep 17 00:00:00 2001 From: AndreyMay <51962295+AndreyMay@users.noreply.github.com> Date: Sun, 15 Dec 2024 05:58:12 -0800 Subject: [PATCH 023/150] Instrumentation + Sentry (#38) --- pages/aws/common_issues.mdx | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/pages/aws/common_issues.mdx b/pages/aws/common_issues.mdx index 0209efc..49c66e7 100644 --- a/pages/aws/common_issues.mdx +++ b/pages/aws/common_issues.mdx @@ -62,3 +62,39 @@ If you are refreshing a dynamic/static route or going to that route directly fro This can also happen in app router when a client navigates via NextJS `` component. The issue might be that your having a folder or file in your `public` directory with an overlapping between the name and your route. In this case, you should rename that to something else. + + +#### `cannot find module './chunks/xxxx.js'` error + +Dynamic imports in `instrumentation.ts` will cause this error at runtime. Remove dynamic imports to resolve. + +#### Sentry server side setup + +The config recommended by Sentry docs uses dynamic imports in `instrumentation.ts`, which causes the above error. + +Here's a working Sentry config which resolves the error: + +`instrumentation.ts` +```typescript +import * as Sentry from '@sentry/nextjs'; +import { initSentry } from '../sentry.server.config'; + +export const onRequestError = Sentry.captureRequestError; + +export async function register() { + initSentry(process.env.NEXT_RUNTIME as 'nodejs' | 'edge'); +} +``` + +`sentry.server.config.ts` +```typescript +import * as Sentry from '@sentry/nextjs'; + +export const initSentry = (runtime: 'nodejs' | 'edge') => { + Sentry.init({ + dsn: 'https://.../', + + //...rest of your config + }); +}; +``` From dab4a6ff6ca9f9ec13075b4f0247583d512e7a38 Mon Sep 17 00:00:00 2001 From: Rob Stanford Date: Thu, 19 Dec 2024 13:57:49 +0000 Subject: [PATCH 024/150] docs: add execution order limitation to Netlify docs (#40) --- pages/netlify/index.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pages/netlify/index.mdx b/pages/netlify/index.mdx index 99d1fb5..adde8d5 100644 --- a/pages/netlify/index.mdx +++ b/pages/netlify/index.mdx @@ -69,6 +69,8 @@ Currently, Netlify's Next.js adapter has the following limitations: - **Rewrites in your Next.js configuration can’t point to static files in the `public` directory.** If you create `beforeFiles` rewrites in your `next.config.js`, they can’t point to static files in your site’s `public` directory. You can use middleware rewrites as an alternative. +- **Headers and Redirects are evaluated after middleware.** If you need to maintain the execution order specified in the Next.js [docs](https://nextjs.org/docs/app/building-your-application/routing/middleware#matching-paths) you will need to configure your [headers](https://docs.netlify.com/routing/headers/) and [redirects](https://docs.netlify.com/routing/redirects/) outside of Next.js using our platform primitives. + - **Netlify Forms compatibility:** Using Netlify Forms with the current adapter [requires a workaround](/netlify/forms). ### pnpm support From ad8b1eec9f0e2946c65b99243da8adef85203458 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Thu, 19 Dec 2024 16:01:40 +0100 Subject: [PATCH 025/150] sync with recent code changes (#37) --- pages/aws/config/custom_overrides.mdx | 5 +---- pages/aws/config/overrides/converter.mdx | 2 +- pages/aws/contribute/local_run.mdx | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pages/aws/config/custom_overrides.mdx b/pages/aws/config/custom_overrides.mdx index faac2ca..b873753 100644 --- a/pages/aws/config/custom_overrides.mdx +++ b/pages/aws/config/custom_overrides.mdx @@ -182,10 +182,10 @@ import type { APIGatewayProxyEventV2, APIGatewayProxyResultV2, } from "aws-lambda"; -import type { StreamCreator } from "@opennextjs/aws/http/openNextResponse.js"; import { Writable } from "node:stream"; import { WarmerEvent, WarmerResponse } from "@opennextjs/aws/adapters/warmer-function.js"; +import type { StreamCreator } from "@opennextjs/aws/types/open-next.js"; import type { WrapperHandler } from "@opennextjs/aws/types/overrides.js"; type AwsLambdaEvent = @@ -248,9 +248,6 @@ const handler: WrapperHandler = }, }); }, - onFinish: () => { - // Do nothing - }, }; const response = await handler(internalEvent, fakeStream); diff --git a/pages/aws/config/overrides/converter.mdx b/pages/aws/config/overrides/converter.mdx index ca2e624..8f1785f 100644 --- a/pages/aws/config/overrides/converter.mdx +++ b/pages/aws/config/overrides/converter.mdx @@ -5,5 +5,5 @@ If you want to better understand how to implement your own Converter, the easies Couple of things to note : - If you use a `StreamCreator` in your wrapper, you probably don't need to do anything in the `convertTo` function. - If used for the default, the image optimization, or one of the splitted server the internal types will be `InternalEvent` and `InternalResult` respectively. -- If used for the external middleware, the internal types will be `InternalEvent` and `InternalResult | MiddlewareOutputEvent` respectively. +- If used for the external middleware, the internal types will be `InternalEvent` and `InternalResult | MiddlewareResult` respectively. - For the other servers, look up their respective types in the codebase. \ No newline at end of file diff --git a/pages/aws/contribute/local_run.mdx b/pages/aws/contribute/local_run.mdx index f73d733..ec058eb 100644 --- a/pages/aws/contribute/local_run.mdx +++ b/pages/aws/contribute/local_run.mdx @@ -67,7 +67,7 @@ import express from 'express' import proxy from 'express-http-proxy' import { fork } from 'child_process' -import type { StreamCreator } from "@opennextjs/aws/http/openNextResponse.js"; +import type { StreamCreator } from "@opennextjs/aws/types/open-next.js"; import type { WrapperHandler } from "@opennextjs/aws/types/overrides.js"; const wrapper: WrapperHandler = async (handler, converter) => { From d0a8a11823e16b3ffd9cddb445e54c347f63c85a Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 20 Dec 2024 16:58:59 +0100 Subject: [PATCH 026/150] cloudflare: update docs for 0.3 (#41) --- pages/cloudflare/0.2/_meta.json | 7 ++ pages/cloudflare/0.2/bindings.mdx | 65 ++++++++++++ pages/cloudflare/0.2/caching.mdx | 36 +++++++ pages/cloudflare/0.2/examples.mdx | 23 +++++ pages/cloudflare/0.2/get-started.mdx | 138 ++++++++++++++++++++++++++ pages/cloudflare/0.2/index.mdx | 66 ++++++++++++ pages/cloudflare/_meta.json | 4 +- pages/cloudflare/caching.mdx | 8 +- pages/cloudflare/examples.mdx | 11 +- pages/cloudflare/get-started.mdx | 78 ++++++++++++--- pages/cloudflare/index.mdx | 25 +++-- pages/cloudflare/migrate-from-0.2.mdx | 83 ++++++++++++++++ 12 files changed, 517 insertions(+), 27 deletions(-) create mode 100644 pages/cloudflare/0.2/_meta.json create mode 100644 pages/cloudflare/0.2/bindings.mdx create mode 100644 pages/cloudflare/0.2/caching.mdx create mode 100644 pages/cloudflare/0.2/examples.mdx create mode 100644 pages/cloudflare/0.2/get-started.mdx create mode 100644 pages/cloudflare/0.2/index.mdx create mode 100644 pages/cloudflare/migrate-from-0.2.mdx diff --git a/pages/cloudflare/0.2/_meta.json b/pages/cloudflare/0.2/_meta.json new file mode 100644 index 0000000..9a7cfe5 --- /dev/null +++ b/pages/cloudflare/0.2/_meta.json @@ -0,0 +1,7 @@ +{ + "index": "Overview", + "get-started": "", + "bindings": "", + "caching": "", + "examples": "" +} \ No newline at end of file diff --git a/pages/cloudflare/0.2/bindings.mdx b/pages/cloudflare/0.2/bindings.mdx new file mode 100644 index 0000000..900e009 --- /dev/null +++ b/pages/cloudflare/0.2/bindings.mdx @@ -0,0 +1,65 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; + +### Bindings + +[Bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) allow your Worker to interact with resources on the Cloudflare Developer Platform. When you declare a binding on your Worker, you grant it a specific capability, such as being able to read and write files to an [R2](https://developers.cloudflare.com/r2/) bucket. + +#### How to configure your Next.js app so it can access bindings + +Install [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare), and then add a `wrangler.toml` file in the root directory of your Next.js app, as described in [Get Started](/cloudflare/get-started). + +#### How to access bindings in your Next.js app + +You can access [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) from any route of your Next.js app via `getCloudflareContext`: + +```js +import { getCloudflareContext } from "@opennextjs/cloudflare"; + +export async function GET(request) { + let responseText = "Hello World"; + + const myKv = (await getCloudflareContext()).env.MY_KV_NAMESPACE; + await myKv.put("foo", "bar"); + const foo = await myKv.get("foo"); + + return new Response(foo); +} +``` + +#### How to add bindings to your Worker + +Add bindings to your Worker by [adding them to your `wrangler.toml` configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). + +## TypeScript type declarations for bindings + +To ensure that the `env` object from `(await getCloudflareContext()).env` above has accurate TypeScript types, run the following Wrangler command to [generate types that match your Worker's configuration](https://developers.cloudflare.com/workers/languages/typescript/#generate-types-that-match-your-workers-configuration-experimental): + +``` +npx wrangler types --experimental-include-runtime +``` + +This will generate a `d.ts` file and (by default) save it to `.wrangler/types/runtime.d.ts`. You will be prompted in the command's output to add that file to your `tsconfig.json`'s `compilerOptions.types` array. + +If you would like to commit the file to git, you can provide a custom path. Here, for instance, the `runtime.d.ts` file will be saved to the root of your project: + +```bash +npx wrangler types --experimental-include-runtime="./runtime.d.ts" +``` + +To ensure that your types are always up-to-date, make sure to run `wrangler types --experimental-include-runtime` after any changes to your config file. + +## Other Cloudflare APIs (`cf`, `ctx`) + +You can access context about the incoming request from the [`cf` object](https://developers.cloudflare.com/workers/runtime-apis/request/#the-cf-property-requestinitcfproperties), as well as lifecycle methods from the [`ctx` object](https://developers.cloudflare.com/workers/runtime-apis/context) from the return value of [`getCloudflareContext()`](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src/api/get-cloudflare-context.ts): + +```js +import { getCloudflareContext } from "@opennextjs/cloudflare"; + + +export async function GET(request) { + const { env, cf, ctx } = await getCloudflareContext(); + + // ... +} +``` diff --git a/pages/cloudflare/0.2/caching.mdx b/pages/cloudflare/0.2/caching.mdx new file mode 100644 index 0000000..cbeb544 --- /dev/null +++ b/pages/cloudflare/0.2/caching.mdx @@ -0,0 +1,36 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; + +## Caching + +`@opennextjs/cloudflare` supports [caching](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#caching-data) and [revalidating](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#revalidating-data) data returned by subrequests you make in your app by calling [`fetch()`](https://developers.cloudflare.com/workers/runtime-apis/fetch/). + +By default, all `fetch()` subrequests made in your Next.js app are cached. Refer to the [Next.js documentation](https://nextjs.org/docs/app/building-your-application/caching#opting-out-1) for information about how to disable caching for an individual subrequest, or for an entire route. + +[The cache persists across deployments](https://nextjs.org/docs/app/building-your-application/caching#data-cache). You are responsible for revalidating/purging this cache. + + +Workers KV is eventually consistent, which means that it can take up to 60 seconds for updates to be reflected globally, when using the default TTL of 60 seconds. + + +### How to enable caching + +`@opennextjs/cloudflare` uses [Workers KV](https://developers.cloudflare.com/kv/) as the cache for your Next.js app. Workers KV is [fast](https://blog.cloudflare.com/faster-workers-kv) and uses Cloudflare's [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) to increase cache hit rates. When you write cached data to Workers KV, you write to storage that can be read by any Cloudflare location. This means your app can fetch data, cache it in KV, and then subsequent requests anywhere around the world can read from this cache. + +To enable caching, you must: + +#### 1. Create a KV namespace + +``` +npx wrangler@latest kv namespace create +``` + +#### 2. Add the KV namespace to your Worker + +The binding name used in your app's worker will be `NEXT_CACHE_WORKERS_KV` by default. This is configurable and can be changed by setting the `__OPENNEXT_KV_BINDING_NAME` build-time environment variable. + +``` +[[kv_namespaces]] +binding = "NEXT_CACHE_WORKERS_KV" +id = "" +``` diff --git a/pages/cloudflare/0.2/examples.mdx b/pages/cloudflare/0.2/examples.mdx new file mode 100644 index 0000000..2cdecbb --- /dev/null +++ b/pages/cloudflare/0.2/examples.mdx @@ -0,0 +1,23 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; + +## Examples + +To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: + +``` +npm create cloudflare@latest -- my-next-app --framework=next --experimental +``` + +### Basic starter projects + +Two basic example apps are included in the repository for `@opennextjs/cloudflare` package: + +- [*`create-next-app`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/create-next-app) — a Next.js project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +- [*`api`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/api) — a minimal Next.js project with a single API route + +You can use these to understand how to configure your Next.js app to use `@opennextjs/cloudflare`, or refer to [Get Started](/cloudflare/get-started). + +### Next.js Commerce Demo + +The [Next.js Commerce demo app](https://github.com/vercel/commerce/tree/v1) works with `@opennextjs/cloudflare`. You can view a deployed version of it [here](https://vercel-commerce-on-workers.web-experiments.workers.dev/). diff --git a/pages/cloudflare/0.2/get-started.mdx b/pages/cloudflare/0.2/get-started.mdx new file mode 100644 index 0000000..803fbe4 --- /dev/null +++ b/pages/cloudflare/0.2/get-started.mdx @@ -0,0 +1,138 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; + +### Get Started + +#### New apps + +To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: + +``` +npm create cloudflare@latest -- my-next-app --framework=next --experimental +``` + +#### Existing Next.js apps + +##### 1. Install @opennextjs/cloudflare + +First, install [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare): + +```sh +npm install --save-dev @opennextjs/cloudflare +``` + +##### 2. Install Wrangler, and add a `wrangler.toml` file + +Install the [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) as a devDependency: + +```npm +npm install -D wrangler@latest +``` + + +You must use Wrangler version `3.78.10` or later to deploy Next.js apps using `@opennextjs/cloudflare`. + + +Then, add a [`wrangler.toml`](https://developers.cloudflare.com/workers/wrangler/configuration/) file to the root directory of your Next.js app: + +```toml +main = ".worker-next/index.mjs" +name = "my-app" +compatibility_date = "2024-09-23" +compatibility_flags = ["nodejs_compat"] +assets = { directory = ".worker-next/assets", binding = "ASSETS" } +``` + + +As shown above, you must enable the [`nodejs_compat` compatibility flag](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) *and* set your [compatibility date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/) to `2024-09-23` or later, in order for your Next.js app to work with @opennextjs/cloudflare. + + +`wrangler.toml` is where you configure your Worker and define what resources it can access via [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings). + +##### 3. Update `package.json` + +Add the following to the scripts field of your `package.json` file: + +```json +"build:worker": "cloudflare", +"dev:worker": "wrangler dev --port 8771", +"preview:worker": "npm run build:worker && npm run dev:worker", +"deploy:worker": "npm run build:worker && wrangler deploy" +``` + +- `npm run build:worker`: Runs the [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter. This first builds your app by running `next build` behind the scenes, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. +- `npm run dev:worker`: Takes the output generated by `build:worker` and runs it locally in [workerd](https://github.com/cloudflare/workerd), the open-source Workers Runtime, allowing you to run the app locally in the same environment that it will run in production. If you instead run `next dev`, your app will run in Node.js, which is a different JavaScript runtime from the Workers runtime, with differences in behavior and APIs. +- `npm run preview:worker`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. +- `npm run deploy`: Builds your app, and then deploys it to Cloudflare + +### 4. Add caching with Workers KV + +See the [Caching docs](/cloudflare/0.2/caching) for information on enabling Next.js caching in your OpenNext project. + +### 5. Remove `@cloudflare/next-on-pages` (if necessary) + +If your Next.js app currently uses `@cloudflare/next-on-pages`, you'll want to remove it, and make a few changes. + +#### Remove `export const runtime = "edge";` + +Before deploying your app, remove the `export const runtime = "edge";` line from your `next.config.js` file. This line is not needed when using `@opennextjs/cloudflare`. + +#### Add `.worker-next` to `.gitignore` + +You should add `.worker-next` to your `.gitignore` file to prevent the build output from being committed to your repository. + +#### Uninstall `@cloudflare/next-on-pages` + +You should uninstall `@cloudflare/next-on-pages` and remove any references to it. + +In `package.json`: + +```diff +"scripts": { +- "pages:build": "npx @cloudflare/next-on-pages", +- "preview": "npm run pages:build && wrangler pages dev", +- "deploy": "npm run pages:build && wrangler pages deploy" + +"devDependencies": { +- "@cloudflare/next-on-pages": "*", +``` + +(remember to also remove [eslint-plugin-next-on-pages](https://www.npmjs.com/package/eslint-plugin-next-on-pages) from your `.eslintrc.js` file) + +You no longer need to call `setupDevPlatform()` in your `next.config.mjs` file: + +```diff title="next.config.mjs" +- import { setupDevPlatform } from '@cloudflare/next-on-pages/next-dev'; + +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +- if (process.env.NODE_ENV === 'development') { +- await setupDevPlatform(); +- } +``` + +And you'll want to replace any uses of `getRequestContext` from `@cloudflare/next-on-pages` with `getCloudflareContext` from `@opennextjs/cloudflare`: + +```diff +- import { getRequestContext } from "@cloudflare/next-on-pages"; ++ import { getCloudflareContext } from "@opennextjs/cloudflare"; +``` + +##### 6. Develop locally + +You can continue to run `next dev` when developing locally. + +During local development, you can access local versions of Cloudflare bindings as indicated in the [bindings documentation](./bindings). + +In step 3, we also added the `npm run preview:worker`, which allows you to quickly preview your app running locally in the Workers runtime, rather than in Node.js. This allows you to test changes in the same runtime as your app will run in when deployed to Cloudflare. + +##### 7. Deploy to Cloudflare Workers + +Either deploy via the command line: + +```sh +npm run deploy:worker +``` + +Or [connect a Github or Gitlab repository](https://developers.cloudflare.com/workers/ci-cd/), and Cloudflare will automatically build and deploy each pull request you merge to your production branch. diff --git a/pages/cloudflare/0.2/index.mdx b/pages/cloudflare/0.2/index.mdx new file mode 100644 index 0000000..02ba3dd --- /dev/null +++ b/pages/cloudflare/0.2/index.mdx @@ -0,0 +1,66 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; + +## Cloudflare + +The [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter lets you deploy Next.js apps to [Cloudflare Workers](https://developers.cloudflare.com/workers) using the [Node.js "runtime" from Next.js](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes). + + +[`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) is pre 1.0, and still in active development. You should try it, [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues), [share feedback](https://github.com/opennextjs/opennextjs-cloudflare/discussions), and contribute code to help make running Next.js apps on Cloudflare easier. We don't quite yet recommend using it for mission-critical production apps. + +You can also use [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cloudflare/next-on-pages) to deploy Next.js apps to Cloudflare Pages. You can review the differences in supported Next.js features below and by reviewing [the docs for `@cloudflare/next-on-pages`](https://developers.cloudflare.com/pages/framework-guides/nextjs/ssr/supported-features/), and understand the differences between Workers and Pages [here](https://developers.cloudflare.com/workers/static-assets/compatibility-matrix/). + + + +### Get Started + +##### New apps + +To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: + +``` +npm create cloudflare@latest -- my-next-app --framework=next --experimental +``` + +##### Existing Next.js apps + +Follow the guide [here](/cloudflare/0.2/get-started) to use [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) with an existing Next.js app. + +### Supported Next.js runtimes + +Next.js has [two "runtimes"](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes) — "Edge" and "Node.js". When you use `@opennextjs/cloudflare`, your app can use the Node.js runtime, which is more fully featured, and allows you to use the [Node.js APIs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) that are provided by the Cloudflare Workers runtime. + +This is an important difference from `@cloudflare/next-on-pages`, which only supports the "Edge" runtime. The Edge Runtime code in Next.js [intentionally constrains which APIs from Node.js can be used](https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack/plugins/middleware-plugin.ts#L820), and the "Edge" runtime does not support all Next.js features. + +### Supported Next.js versions + +`@opennextjs/cloudflare` is pre 1.0, and still in active development. We intend to support all minor and patch version of Next.js 13 and 14, as well as Next.js 15 when it is released. (currently a release candidate) + +To help improve compatibility, we encourage you to [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues) and contribute code! + +### Supported Next.js features + +- [x] [App Router](https://nextjs.org/docs/app) +- [x] [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) +- [x] [Dynamic routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) +- [x] [Static Site Generation (SSG)](https://nextjs.org/docs/app/building-your-application/rendering/server-components#static-rendering-default) +- [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/app/building-your-application/rendering/server-components) + +### Not Yet Supported Next.js features + +The following Next.js features are not yet supported — but we welcome both contributions and feedback! Tell us what you'd like to see, or what you'd like to add support for: + +- [ ] [Pages Router](https://nextjs.org/docs/pages) (you should use the App Router instead, which was introduced in Next.js 13) +- [ ] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) +- [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) +- [ ] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) +- [ ] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) +- [ ] [Experimental streaming support](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) + +### How @opennextjs/cloudflare Works + +The OpenNext Cloudflare adapter works by taking the Next.js build output and transforming it, so that it can run in Cloudflare Workers. + +When you add [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) as a dependency to your Next.js app, and then run `npx cloudflare` the adapter first builds your app by running `next build`, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. + +You can view the code for @opennextjs/cloudflare [here](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src) to understand what it does under the hood. diff --git a/pages/cloudflare/_meta.json b/pages/cloudflare/_meta.json index 2c667df..8d0c8fa 100644 --- a/pages/cloudflare/_meta.json +++ b/pages/cloudflare/_meta.json @@ -4,5 +4,7 @@ "bindings": "", "caching": "", "examples": "", - "troubleshooting": "" + "troubleshooting": "", + "migrate-from-0.2": "", + "0.2": "Release 0.2" } diff --git a/pages/cloudflare/caching.mdx b/pages/cloudflare/caching.mdx index b50eeab..50e02f3 100644 --- a/pages/cloudflare/caching.mdx +++ b/pages/cloudflare/caching.mdx @@ -3,12 +3,16 @@ import { Callout } from 'nextra/components'; ## Caching -`@opennextjs/cloudflare` supports [caching](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#caching-data) and [revalidating](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#revalidating-data) data returned by subrequests you make in your app by calling [`fetch()`](https://developers.cloudflare.com/workers/runtime-apis/fetch/). +`@opennextjs/cloudflare` supports [caching](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#caching-data). By default, all `fetch()` subrequests made in your Next.js app are cached. Refer to the [Next.js documentation](https://nextjs.org/docs/app/building-your-application/caching#opting-out-1) for information about how to disable caching for an individual subrequest, or for an entire route. [The cache persists across deployments](https://nextjs.org/docs/app/building-your-application/caching#data-cache). You are responsible for revalidating/purging this cache. +Note that [Revalidating](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#revalidating-data) is not yet supported. + +Next.js primes the cache at build time. The build time values are serverd by the [Workers Assets](https://developers.cloudflare.com/workers/static-assets/). + Workers KV is eventually consistent, which means that it can take up to 60 seconds for updates to be reflected globally, when using the default TTL of 60 seconds. @@ -27,7 +31,7 @@ npx wrangler@latest kv namespace create #### 2. Add the KV namespace to your Worker -The binding name used in your app's worker will be `NEXT_CACHE_WORKERS_KV` by default. This is configurable and can be changed by setting the `__OPENNEXT_KV_BINDING_NAME` build-time environment variable. +The binding name used in your app's worker is `NEXT_CACHE_WORKERS_KV`. ``` [[kv_namespaces]] diff --git a/pages/cloudflare/examples.mdx b/pages/cloudflare/examples.mdx index aba8420..ff0eb03 100644 --- a/pages/cloudflare/examples.mdx +++ b/pages/cloudflare/examples.mdx @@ -6,15 +6,22 @@ import { Callout } from 'nextra/components'; To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: ``` -npm create cloudflare@latest -- my-next-app --framework=next --experimental +npm create cloudflare@latest -- --template https://github.com/flarelabs-net/workers-next ``` + +The experimental template for the Next framework is still based on 0.2. +Use the template from `flarelabs-net/workers-next` as indicated above to use 0.3. + + ### Basic starter projects -Two basic example apps are included in the repository for `@opennextjs/cloudflare` package: +Basic example apps are included in the repository for `@opennextjs/cloudflare` package: - [*`create-next-app`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/create-next-app) — a Next.js project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). - [*`api`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/api) — a minimal Next.js project with a single API route +- [*`middleware`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/middleware) — a minimal Next.js project using middleware +- [*`vercel-blog-starter`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/vercel-blog-starter) — a blog project using SSG You can use these to understand how to configure your Next.js app to use `@opennextjs/cloudflare`, or refer to [Get Started](/cloudflare/get-started). diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 3e47e5e..bcce2aa 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -8,9 +8,14 @@ import { Callout } from 'nextra/components'; To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: ``` -npm create cloudflare@latest -- my-next-app --framework=next --experimental +npm create cloudflare@latest -- --template https://github.com/flarelabs-net/workers-next ``` + +The experimental template for the Next framework is still based on 0.2. +Use the template from `flarelabs-net/workers-next` as indicated above to use 0.3. + + #### Existing Next.js apps ##### 1. Install @opennextjs/cloudflare @@ -30,16 +35,19 @@ npm install -D wrangler@latest ``` -You must use Wrangler version `3.78.10` or later to deploy Next.js apps using `@opennextjs/cloudflare`. +You must use Wrangler version `3.99.0` or later to deploy Next.js apps using `@opennextjs/cloudflare`. Then, add a [`wrangler.toml`](https://developers.cloudflare.com/workers/wrangler/configuration/) file to the root directory of your Next.js app: ```toml -main = ".worker-next/index.mjs" +main = ".open-next/worker.js" name = "my-app" + compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat"] + +# The binding name must be "ASSETS" when the cache is enabled assets = { directory = ".worker-next/assets", binding = "ASSETS" } ``` @@ -49,12 +57,57 @@ As shown above, you must enable the [`nodejs_compat` compatibility flag](https:/ `wrangler.toml` is where you configure your Worker and define what resources it can access via [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings). -##### 3. Update `package.json` +##### 3. Add a `open-next.config.ts` file + +Then, add a [`open-next.config.ts`](https://opennext.js.org/aws/config) file to the root directory of your Next.js app: + +```ts +import type { OpenNextConfig } from "@opennextjs/aws/types/open-next"; +import cache from "@opennextjs/cloudflare/kvCache"; + +const config: OpenNextConfig = { + default: { + override: { + wrapper: "cloudflare-node", + converter: "edge", + // Set `incrementalCache` to "dummy" to disable KV cache + incrementalCache: async () => cache, + tagCache: "dummy", + queue: "dummy", + }, + }, + + middleware: { + external: true, + override: { + wrapper: "cloudflare-edge", + converter: "edge", + proxyExternalRequest: "fetch", + }, + }, +}; + +export default config; +``` + +You can either install the `@opennextjs/aws` NPM package to get the types or `open-next.config.ts` to the [`exclude`](https://www.typescriptlang.org/tsconfig/#exclude) configuration key of your `tsconfig.json`. + +##### 4. Add a `.dev.vars` file + +Then, add a [`.dev.vars`](https://developers.cloudflare.com/workers/testing/local-development/#local-only-environment-variables) file to the root directory of your Next.js app: + +```text +NEXTJS_ENV=development +``` + +The `NEXTJS_ENV` variable defines the environment to use when loading Next.js `.env` files. It defaults to "production" when not defined. + +##### 5. Update `package.json` Add the following to the scripts field of your `package.json` file: ```json -"build:worker": "cloudflare", +"build:worker": "opennextjs-cloudflare", "dev:worker": "wrangler dev --port 8771", "preview:worker": "npm run build:worker && npm run dev:worker", "deploy:worker": "npm run build:worker && wrangler deploy" @@ -65,21 +118,22 @@ Add the following to the scripts field of your `package.json` file: - `npm run preview:worker`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. - `npm run deploy`: Builds your app, and then deploys it to Cloudflare -### 4. Add caching with Workers KV +### 6. Add caching with Workers KV See the [Caching docs](/cloudflare/caching) for information on enabling Next.js caching in your OpenNext project. -### 5. Remove `@cloudflare/next-on-pages` (if necessary) +### 7. Remove `@cloudflare/next-on-pages` (if necessary) If your Next.js app currently uses `@cloudflare/next-on-pages`, you'll want to remove it, and make a few changes. #### Remove `export const runtime = "edge";` -Before deploying your app, remove the `export const runtime = "edge";` line from your `next.config.js` file. This line is not needed when using `@opennextjs/cloudflare`. +Before deploying your app, remove the `export const runtime = "edge";` line from your `next.config.js` file. +The edge runtime is not supported yet with `@opennextjs/cloudflare`. -#### Add `.worker-next` to `.gitignore` +#### Add `.open-next` to `.gitignore` -You should add `.worker-next` to your `.gitignore` file to prevent the build output from being committed to your repository. +You should add `.open-next` to your `.gitignore` file to prevent the build output from being committed to your repository. #### Uninstall `@cloudflare/next-on-pages` @@ -119,7 +173,7 @@ And you'll want to replace any uses of `getRequestContext` from `@cloudflare/nex + import { getCloudflareContext } from "@opennextjs/cloudflare"; ``` -##### 6. Develop locally +##### 8. Develop locally You can continue to run `next dev` when developing locally. @@ -127,7 +181,7 @@ During local development, you can access local versions of Cloudflare bindings a In step 3, we also added the `npm run preview:worker`, which allows you to quickly preview your app running locally in the Workers runtime, rather than in Node.js. This allows you to test changes in the same runtime as your app will run in when deployed to Cloudflare. -##### 7. Deploy to Cloudflare Workers +##### 9. Deploy to Cloudflare Workers Either deploy via the command line: diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index a1368ed..1e3ee1f 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -19,9 +19,14 @@ You can also use [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cl To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: ``` -npm create cloudflare@latest -- my-next-app --framework=next --experimental +npm create cloudflare@latest -- --template https://github.com/flarelabs-net/workers-next ``` + +The experimental template for the Next framework is still based on 0.2. +Use the template from `flarelabs-net/workers-next` as indicated above to use 0.3. + + ##### Existing Next.js apps Follow the guide [here](/cloudflare/get-started) to use [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) with an existing Next.js app. @@ -34,33 +39,33 @@ This is an important difference from `@cloudflare/next-on-pages`, which only sup ### Supported Next.js versions -`@opennextjs/cloudflare` is pre 1.0, and still in active development. We intend to support all minor and patch version of Next.js 13 and 14, as well as Next.js 15 when it is released. (currently a release candidate) +`@opennextjs/cloudflare` is pre 1.0, and still in active development. We intend to support all minor and patch version of Next.js 13, 14, and 15. To help improve compatibility, we encourage you to [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues) and contribute code! ### Supported Next.js features +Some Next.js features are not yet supported are not fully tested. +We will update the list as we progress towards releasing 1.0. + - [x] [App Router](https://nextjs.org/docs/app) - [x] [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) - [x] [Dynamic routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) - [x] [Static Site Generation (SSG)](https://nextjs.org/docs/app/building-your-application/rendering/server-components#static-rendering-default) - [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/app/building-your-application/rendering/server-components) - -### Not Yet Supported Next.js features - -The following Next.js features are not yet supported — but we welcome both contributions and feedback! Tell us what you'd like to see, or what you'd like to add support for: - +- [x] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) +- [x] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) - [ ] [Pages Router](https://nextjs.org/docs/pages) (you should use the App Router instead, which was introduced in Next.js 13) - [ ] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) - [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) -- [ ] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) -- [ ] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) - [ ] [Experimental streaming support](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) +We welcome both contributions and feedback! + ### How @opennextjs/cloudflare Works The OpenNext Cloudflare adapter works by taking the Next.js build output and transforming it, so that it can run in Cloudflare Workers. -When you add [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) as a dependency to your Next.js app, and then run `npx cloudflare` the adapter first builds your app by running `next build`, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. +When you add [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) as a dependency to your Next.js app, and then run `npx opennextjs-cloudflare` the adapter first builds your app by running `next build`, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. You can view the code for @opennextjs/cloudflare [here](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src) to understand what it does under the hood. diff --git a/pages/cloudflare/migrate-from-0.2.mdx b/pages/cloudflare/migrate-from-0.2.mdx new file mode 100644 index 0000000..e5ce039 --- /dev/null +++ b/pages/cloudflare/migrate-from-0.2.mdx @@ -0,0 +1,83 @@ +import { SITE } from '../../config'; +import { Callout } from 'nextra/components'; + +### Migrate from 0.2 + +The `@opennextjs/cloudflare` adapter is now more closely intgrated with `@opennextjs/aws`. + +You will need to update your projects based on the 0.2 release as described in the following sections. + +##### 1. Update the `wrangler.toml` file + +The entry point is now `.open-next/worker.js`, update `wrangler.toml` accordingly: + +```toml +# CHANGED: new entry point location +main = ".open-next/worker.js" +name = "my-app" + +compatibility_date = "2024-09-23" +compatibility_flags = ["nodejs_compat"] + +# The binding name must be "ASSETS" when the cache is enabled +# CHANGED: output folder location +assets = { directory = ".open-next/assets", binding = "ASSETS" } +``` + +##### 2. Add a `open-next.config.ts` file + +Add a [`open-next.config.ts`](https://opennext.js.org/aws/config) file to the root directory of your Next.js app: + +```ts +import type { OpenNextConfig } from "@opennextjs/aws/types/open-next"; +import cache from "@opennextjs/cloudflare/kvCache"; + +const config: OpenNextConfig = { + default: { + override: { + wrapper: "cloudflare-node", + converter: "edge", + // Set `incrementalCache` to "dummy" to disable KV cache + incrementalCache: async () => cache, + tagCache: "dummy", + queue: "dummy", + }, + }, + + middleware: { + external: true, + override: { + wrapper: "cloudflare-edge", + converter: "edge", + proxyExternalRequest: "fetch", + }, + }, +}; + +export default config; +``` + +You can either install the `@opennextjs/aws` NPM package to get the types or `open-next.config.ts` to the [`exclude`](https://www.typescriptlang.org/tsconfig/#exclude) configuration key of your `tsconfig.json`. + +##### 3. Add a `.dev.vars` file + +Add a [`.dev.vars`](https://developers.cloudflare.com/workers/testing/local-development/#local-only-environment-variables) file to the root directory of your Next.js app: + +```text +NEXTJS_ENV=development +``` + +The `NEXTJS_ENV` variable defines the environment to use when loading Next.js `.env` files. It defaults to "production" when not defined. + +##### 4. Update `package.json` + +The name of the CLI was changed to `opennextjs-cloudflare`: + +```json +"build:worker": "opennextjs-cloudflare", +``` + +##### 5 Add `.open-next` to `.gitignore` + +You should change `.worker-next` to `.open-next` in your `.gitignore` file to prevent the build output from being committed to your repository. +You can safely delete the content of the now unused `.worker-next`. \ No newline at end of file From ea3d65dd580d5460ad5f1c520e53ba81e2b426de Mon Sep 17 00:00:00 2001 From: Yanqi Zong Date: Fri, 20 Dec 2024 23:24:44 -0800 Subject: [PATCH 027/150] docs: update cloudflare get started docs (#42) --- pages/cloudflare/get-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index bcce2aa..7cd16fd 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -48,7 +48,7 @@ compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat"] # The binding name must be "ASSETS" when the cache is enabled -assets = { directory = ".worker-next/assets", binding = "ASSETS" } +assets = { directory = ".open-next/assets", binding = "ASSETS" } ``` From 1ed07331612029c951bbea6dafc172ae374dcce0 Mon Sep 17 00:00:00 2001 From: James Anderson Date: Mon, 6 Jan 2025 13:39:01 +0000 Subject: [PATCH 028/150] change `next build` references to the `package.json` `build` script (#46) --- pages/cloudflare/get-started.mdx | 2 +- pages/cloudflare/index.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 7cd16fd..eb3252a 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -113,7 +113,7 @@ Add the following to the scripts field of your `package.json` file: "deploy:worker": "npm run build:worker && wrangler deploy" ``` -- `npm run build:worker`: Runs the [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter. This first builds your app by running `next build` behind the scenes, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. +- `npm run build:worker`: Runs the [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter. This first builds your app by running the `build` script in your `package.json` (Next.js apps use `next build` by default), and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. The build command used by OpenNext can be overridden with the `buildCommand` option in your OpenNext config. - `npm run dev:worker`: Takes the output generated by `build:worker` and runs it locally in [workerd](https://github.com/cloudflare/workerd), the open-source Workers Runtime, allowing you to run the app locally in the same environment that it will run in production. If you instead run `next dev`, your app will run in Node.js, which is a different JavaScript runtime from the Workers runtime, with differences in behavior and APIs. - `npm run preview:worker`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. - `npm run deploy`: Builds your app, and then deploys it to Cloudflare diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 1e3ee1f..97bf801 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -66,6 +66,6 @@ We welcome both contributions and feedback! The OpenNext Cloudflare adapter works by taking the Next.js build output and transforming it, so that it can run in Cloudflare Workers. -When you add [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) as a dependency to your Next.js app, and then run `npx opennextjs-cloudflare` the adapter first builds your app by running `next build`, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. +When you add [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) as a dependency to your Next.js app, and then run `npx opennextjs-cloudflare` the adapter first builds your app by running the `build` script in your `package.json`, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. You can view the code for @opennextjs/cloudflare [here](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src) to understand what it does under the hood. From 2beac6f6d2cde5fb95d3a9960b01a5058a8568f1 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Tue, 7 Jan 2025 12:18:02 +0100 Subject: [PATCH 029/150] update and improve the Cloudflare adapter getting started guide (#45) --- pages/cloudflare/get-started.mdx | 125 +++++++++++++------------- pages/cloudflare/migrate-from-0.2.mdx | 2 +- 2 files changed, 62 insertions(+), 65 deletions(-) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index eb3252a..2d992de 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -23,46 +23,69 @@ Use the template from `flarelabs-net/workers-next` as indicated above to use 0.3 First, install [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare): ```sh -npm install --save-dev @opennextjs/cloudflare +npm install --save-dev @opennextjs/cloudflare@latest ``` -##### 2. Install Wrangler, and add a `wrangler.toml` file +##### 2. Install Wrangler Install the [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) as a devDependency: ```npm -npm install -D wrangler@latest +npm install --save-dev wrangler@latest ``` You must use Wrangler version `3.99.0` or later to deploy Next.js apps using `@opennextjs/cloudflare`. -Then, add a [`wrangler.toml`](https://developers.cloudflare.com/workers/wrangler/configuration/) file to the root directory of your Next.js app: +##### 3. Create a `wrangler.json` file -```toml -main = ".open-next/worker.js" -name = "my-app" - -compatibility_date = "2024-09-23" -compatibility_flags = ["nodejs_compat"] + +This step is optional since `@opennextjs/cloudflare` creates this file for you during the build process (if not already present). + -# The binding name must be "ASSETS" when the cache is enabled -assets = { directory = ".open-next/assets", binding = "ASSETS" } +A [`wrangler.json`](https://developers.cloudflare.com/workers/wrangler/configuration/) file is needed for your +application to be previewed and deployed, it is also where you configure your Worker and define what resources it can access via [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings). + +You can create one yourself with the following content: +```jsonc +{ + "main": ".open-next/worker.js", + "name": "my-app", + "compatibility_date": "2024-12-30", + "compatibility_flags": ["nodejs_compat"], + "assets": { + "directory": ".open-next/assets", + "binding": "ASSETS", + }, + "kv_namespaces": [ + // Create a KV binding with the binding name "NEXT_CACHE_WORKERS_KV" + // to enable the KV based caching: + // { + // "binding": "NEXT_CACHE_WORKERS_KV", + // "id": "" + // } + ], +} ``` -As shown above, you must enable the [`nodejs_compat` compatibility flag](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) *and* set your [compatibility date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/) to `2024-09-23` or later, in order for your Next.js app to work with @opennextjs/cloudflare. +As shown above: + - You must enable the [`nodejs_compat` compatibility flag](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) *and* set your [compatibility date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/) to `2024-09-23` or later, in order for your Next.js app to work with @opennextjs/cloudflare + - The `main` and `assets` values should also not be changed unless you modify the build output result in some way + - You can add a binding named `NEXT_CACHE_WORKERS_KV` to make use of Next.js' caching as described in the [Caching docs](/cloudflare/caching) -`wrangler.toml` is where you configure your Worker and define what resources it can access via [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings). +##### 4. Add an `open-next.config.ts` file -##### 3. Add a `open-next.config.ts` file + +This step is optional since `@opennextjs/cloudflare` creates this file for you during the build process (if not already present). + -Then, add a [`open-next.config.ts`](https://opennext.js.org/aws/config) file to the root directory of your Next.js app: +Add a [`open-next.config.ts`](https://opennext.js.org/aws/config) file to the root directory of your Next.js app: ```ts -import type { OpenNextConfig } from "@opennextjs/aws/types/open-next"; +import type { OpenNextConfig } from "@opennextjs/aws/types/open-next.js"; import cache from "@opennextjs/cloudflare/kvCache"; const config: OpenNextConfig = { @@ -70,7 +93,7 @@ const config: OpenNextConfig = { override: { wrapper: "cloudflare-node", converter: "edge", - // Set `incrementalCache` to "dummy" to disable KV cache + // set `incrementalCache` to "dummy" to disable KV cache incrementalCache: async () => cache, tagCache: "dummy", queue: "dummy", @@ -90,9 +113,11 @@ const config: OpenNextConfig = { export default config; ``` -You can either install the `@opennextjs/aws` NPM package to get the types or `open-next.config.ts` to the [`exclude`](https://www.typescriptlang.org/tsconfig/#exclude) configuration key of your `tsconfig.json`. + +To use the `OpenNextConfig` type as illustrated above (which is not necessary), you need to install the `@opennextjs/aws` NPM package as a dev dependency. + -##### 4. Add a `.dev.vars` file +##### 5. Add a `.dev.vars` file Then, add a [`.dev.vars`](https://developers.cloudflare.com/workers/testing/local-development/#local-only-environment-variables) file to the root directory of your Next.js app: @@ -102,7 +127,7 @@ NEXTJS_ENV=development The `NEXTJS_ENV` variable defines the environment to use when loading Next.js `.env` files. It defaults to "production" when not defined. -##### 5. Update `package.json` +##### 6. Update the `package.json` file Add the following to the scripts field of your `package.json` file: @@ -118,62 +143,34 @@ Add the following to the scripts field of your `package.json` file: - `npm run preview:worker`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. - `npm run deploy`: Builds your app, and then deploys it to Cloudflare -### 6. Add caching with Workers KV +##### 7. Add caching with Workers KV See the [Caching docs](/cloudflare/caching) for information on enabling Next.js caching in your OpenNext project. -### 7. Remove `@cloudflare/next-on-pages` (if necessary) - -If your Next.js app currently uses `@cloudflare/next-on-pages`, you'll want to remove it, and make a few changes. +##### 8. Remove any `export const runtime = "edge";` if present -#### Remove `export const runtime = "edge";` +Before deploying your app, remove the `export const runtime = "edge";` line from any of your source files. -Before deploying your app, remove the `export const runtime = "edge";` line from your `next.config.js` file. The edge runtime is not supported yet with `@opennextjs/cloudflare`. -#### Add `.open-next` to `.gitignore` +##### 9. Add `.open-next` to `.gitignore` You should add `.open-next` to your `.gitignore` file to prevent the build output from being committed to your repository. -#### Uninstall `@cloudflare/next-on-pages` - -You should uninstall `@cloudflare/next-on-pages` and remove any references to it. - -In `package.json`: +##### 10. Remove `@cloudflare/next-on-pages` (if necessary) -```diff -"scripts": { -- "pages:build": "npx @cloudflare/next-on-pages", -- "preview": "npm run pages:build && wrangler pages dev", -- "deploy": "npm run pages:build && wrangler pages deploy" - -"devDependencies": { -- "@cloudflare/next-on-pages": "*", -``` - -(remember to also remove [eslint-plugin-next-on-pages](https://www.npmjs.com/package/eslint-plugin-next-on-pages) from your `.eslintrc.js` file) - -You no longer need to call `setupDevPlatform()` in your `next.config.mjs` file: - -```diff title="next.config.mjs" -- import { setupDevPlatform } from '@cloudflare/next-on-pages/next-dev'; - -/** @type {import('next').NextConfig} */ -const nextConfig = {}; - -- if (process.env.NODE_ENV === 'development') { -- await setupDevPlatform(); -- } -``` +If your Next.js app currently uses `@cloudflare/next-on-pages`, you'll want to remove it, and make a few changes. -And you'll want to replace any uses of `getRequestContext` from `@cloudflare/next-on-pages` with `getCloudflareContext` from `@opennextjs/cloudflare`: +Uninstalling the [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cloudflare/next-on-pages) package as well as the [`eslint-plugin-next-on-pages`](https://www.npmjs.com/package/eslint-plugin-next-on-pages) package if present. -```diff -- import { getRequestContext } from "@cloudflare/next-on-pages"; -+ import { getCloudflareContext } from "@opennextjs/cloudflare"; -``` +Remove any reference of these packages from your source and configuration files. +This includes: + - `setupDevPlatform()` calls in your Next.js config file + - `getRequestContext` imports from `@cloudflare/next-on-pages` from your source files + (those can be replaced with `getCloudflareContext` calls from `@opennextjs/cloudflare`) + - next-on-pages eslint rules set in your Eslint config file -##### 8. Develop locally +##### 11. Develop locally You can continue to run `next dev` when developing locally. @@ -181,7 +178,7 @@ During local development, you can access local versions of Cloudflare bindings a In step 3, we also added the `npm run preview:worker`, which allows you to quickly preview your app running locally in the Workers runtime, rather than in Node.js. This allows you to test changes in the same runtime as your app will run in when deployed to Cloudflare. -##### 9. Deploy to Cloudflare Workers +##### 12. Deploy to Cloudflare Workers Either deploy via the command line: diff --git a/pages/cloudflare/migrate-from-0.2.mdx b/pages/cloudflare/migrate-from-0.2.mdx index e5ce039..aaf01b0 100644 --- a/pages/cloudflare/migrate-from-0.2.mdx +++ b/pages/cloudflare/migrate-from-0.2.mdx @@ -29,7 +29,7 @@ assets = { directory = ".open-next/assets", binding = "ASSETS" } Add a [`open-next.config.ts`](https://opennext.js.org/aws/config) file to the root directory of your Next.js app: ```ts -import type { OpenNextConfig } from "@opennextjs/aws/types/open-next"; +import type { OpenNextConfig } from "@opennextjs/aws/types/open-next.js"; import cache from "@opennextjs/cloudflare/kvCache"; const config: OpenNextConfig = { From 749db062b164439adc1b9dafb1584f56589c277f Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Tue, 7 Jan 2025 22:14:07 +0100 Subject: [PATCH 030/150] remove the no longer necessary Cloudflare's flarelabs template reference (#44) --- pages/cloudflare/examples.mdx | 7 +------ pages/cloudflare/get-started.mdx | 7 +------ pages/cloudflare/index.mdx | 6 +----- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/pages/cloudflare/examples.mdx b/pages/cloudflare/examples.mdx index ff0eb03..22c2ae3 100644 --- a/pages/cloudflare/examples.mdx +++ b/pages/cloudflare/examples.mdx @@ -6,14 +6,9 @@ import { Callout } from 'nextra/components'; To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: ``` -npm create cloudflare@latest -- --template https://github.com/flarelabs-net/workers-next +npm create cloudflare@latest -- my-next-app --framework=next --experimental ``` - -The experimental template for the Next framework is still based on 0.2. -Use the template from `flarelabs-net/workers-next` as indicated above to use 0.3. - - ### Basic starter projects Basic example apps are included in the repository for `@opennextjs/cloudflare` package: diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 2d992de..e34d41b 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -8,14 +8,9 @@ import { Callout } from 'nextra/components'; To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: ``` -npm create cloudflare@latest -- --template https://github.com/flarelabs-net/workers-next +npm create cloudflare@latest -- my-next-app --framework=next --experimental ``` - -The experimental template for the Next framework is still based on 0.2. -Use the template from `flarelabs-net/workers-next` as indicated above to use 0.3. - - #### Existing Next.js apps ##### 1. Install @opennextjs/cloudflare diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 97bf801..ed94138 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -19,13 +19,9 @@ You can also use [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cl To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: ``` -npm create cloudflare@latest -- --template https://github.com/flarelabs-net/workers-next +npm create cloudflare@latest -- my-next-app --framework=next --experimental ``` - -The experimental template for the Next framework is still based on 0.2. -Use the template from `flarelabs-net/workers-next` as indicated above to use 0.3. - ##### Existing Next.js apps From d534771dbf06960a461fba216c1f0297e009a244 Mon Sep 17 00:00:00 2001 From: James Anderson Date: Thu, 9 Jan 2025 10:44:51 +0000 Subject: [PATCH 031/150] remove v13 from supported versions (#47) --- pages/cloudflare/index.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index ed94138..00e8aa1 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -22,20 +22,19 @@ To create a new Next.js app, pre-configured to run on Cloudflare using @opennext npm create cloudflare@latest -- my-next-app --framework=next --experimental ``` - ##### Existing Next.js apps Follow the guide [here](/cloudflare/get-started) to use [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) with an existing Next.js app. ### Supported Next.js runtimes -Next.js has [two "runtimes"](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes) — "Edge" and "Node.js". When you use `@opennextjs/cloudflare`, your app can use the Node.js runtime, which is more fully featured, and allows you to use the [Node.js APIs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) that are provided by the Cloudflare Workers runtime. +Next.js has [two "runtimes"](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes) — "Edge" and "Node.js". When you use `@opennextjs/cloudflare`, your app should use the Node.js runtime, which is more fully featured, and allows you to use the [Node.js APIs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) that are provided by the Cloudflare Workers runtime. This is an important difference from `@cloudflare/next-on-pages`, which only supports the "Edge" runtime. The Edge Runtime code in Next.js [intentionally constrains which APIs from Node.js can be used](https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack/plugins/middleware-plugin.ts#L820), and the "Edge" runtime does not support all Next.js features. ### Supported Next.js versions -`@opennextjs/cloudflare` is pre 1.0, and still in active development. We intend to support all minor and patch version of Next.js 13, 14, and 15. +`@opennextjs/cloudflare` is pre 1.0, and still in active development. We intend to support all minor and patch versions of Next.js 14 and 15. To help improve compatibility, we encourage you to [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues) and contribute code! From e1881223876469f93ade5a3af07fc8a242e46299 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Mon, 13 Jan 2025 21:05:44 +0000 Subject: [PATCH 032/150] add warnings in the aws and cloudflare docs regarding the limited windows support (#49) --- pages/aws/index.mdx | 7 +++++++ pages/cloudflare/index.mdx | 5 +++++ shared/WindowsSupport.mdx | 12 ++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 shared/WindowsSupport.mdx diff --git a/pages/aws/index.mdx b/pages/aws/index.mdx index 6b741e8..3290d80 100644 --- a/pages/aws/index.mdx +++ b/pages/aws/index.mdx @@ -1,5 +1,6 @@ import { SITE } from '../../config'; import { Callout } from 'nextra/components'; +import WindowsSupport from '../../shared/WindowsSupport.mdx'; This docs is for the V3 of OpenNext. If you are looking for the V2 docs, you can find them [here](/aws/v2). @@ -44,4 +45,10 @@ OpenNext aims to support all Next.js 14 features. Some features are work in prog --- + + + + +--- + [Get started](/aws/get_started) with deploying your app with OpenNext and your favorite framework. diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 00e8aa1..58a42ae 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -1,5 +1,6 @@ import { SITE } from '../../config'; import { Callout } from 'nextra/components'; +import WindowsSupport from '../../shared/WindowsSupport.mdx'; ## Cloudflare @@ -57,6 +58,10 @@ We will update the list as we progress towards releasing 1.0. We welcome both contributions and feedback! +### Windows support + + + ### How @opennextjs/cloudflare Works The OpenNext Cloudflare adapter works by taking the Next.js build output and transforming it, so that it can run in Cloudflare Workers. diff --git a/shared/WindowsSupport.mdx b/shared/WindowsSupport.mdx new file mode 100644 index 0000000..647b7d1 --- /dev/null +++ b/shared/WindowsSupport.mdx @@ -0,0 +1,12 @@ +OpenNext can be used on Windows systems but Windows full support is not guaranteed because: + - historically the Next.js tooling itself has had Windows support issues + (and OpenNext is built on these tools) + - the OpenNext team has limited capacity and fully supporting Windows (given the point above) + has been determined to be a lower priority, thus the effort and testing on Windows is limited + +Given the above, you can develop your application under Windows at your own risk. If you don't have an alternative we +recommend either: + - running OpenNext using [WSL2](https://learn.microsoft.com/en-us/windows/wsl/), + - in a Linux Virtual Machine or + - develop your application using the standard Next.js tooling and deploy it using OpenNext in CI/CD systems such + as [GitHub Actions](https://github.com/features/actions) that run linux/MacOS environments \ No newline at end of file From b1ab51d365e60e691ae29fd2b25bc53957f66a3c Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Tue, 14 Jan 2025 12:22:52 +0000 Subject: [PATCH 033/150] remove all references to `wrangler.toml` (#48) --- pages/cloudflare/bindings.mdx | 4 ++-- pages/cloudflare/get-started.mdx | 6 +++--- pages/cloudflare/troubleshooting.mdx | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pages/cloudflare/bindings.mdx b/pages/cloudflare/bindings.mdx index 6efd272..dfd8aee 100644 --- a/pages/cloudflare/bindings.mdx +++ b/pages/cloudflare/bindings.mdx @@ -7,7 +7,7 @@ import { Callout } from 'nextra/components'; #### How to configure your Next.js app so it can access bindings -Install [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare), and then add a `wrangler.toml` file in the root directory of your Next.js app, as described in [Get Started](/cloudflare/get-started). +Install [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare), and then add a [wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/) in the root directory of your Next.js app, as described in [Get Started](/cloudflare/get-started#3-create-a-wranglerjson-file). #### How to access bindings in your Next.js app @@ -29,7 +29,7 @@ export async function GET(request) { #### How to add bindings to your Worker -Add bindings to your Worker by [adding them to your `wrangler.toml` configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). +Add bindings to your Worker by adding them to your [wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). ## TypeScript type declarations for bindings diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index e34d41b..8817ae9 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -33,16 +33,16 @@ npm install --save-dev wrangler@latest You must use Wrangler version `3.99.0` or later to deploy Next.js apps using `@opennextjs/cloudflare`. -##### 3. Create a `wrangler.json` file +##### 3. Create a wrangler configuration file This step is optional since `@opennextjs/cloudflare` creates this file for you during the build process (if not already present). -A [`wrangler.json`](https://developers.cloudflare.com/workers/wrangler/configuration/) file is needed for your +A [wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/) is needed for your application to be previewed and deployed, it is also where you configure your Worker and define what resources it can access via [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings). -You can create one yourself with the following content: +You can create one yourself in the root directory of your Next.js app with the name `wrangler.json` and the following content: ```jsonc { "main": ".open-next/worker.js", diff --git a/pages/cloudflare/troubleshooting.mdx b/pages/cloudflare/troubleshooting.mdx index 57f9770..f792339 100644 --- a/pages/cloudflare/troubleshooting.mdx +++ b/pages/cloudflare/troubleshooting.mdx @@ -17,7 +17,8 @@ The Cloudflare Account you are deploying to is on the Workers Free plan, which [ ### My app fails to build when I import a specific NPM package -First, make sure that the `nodejs_compat` compatibility flag is enabled, and your compatibility date is set to on or after "2024-09-23", in your `wrangler.toml` file. [Refer to the Workers docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) for more details on Node.js support in Cloudflare Workers. +First, make sure that the `nodejs_compat` compatibility flag is enabled, and your compatibility date is set to on or after "2024-09-23", in your [wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). +Refer to the [Node.js Workers docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) for more details on Node.js support in Cloudflare Workers. Some NPM packages define multiple exports. For example: From 4f91a0a440459fdee9d20f83ec38ac61f27f2ca8 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Tue, 14 Jan 2025 14:33:20 +0100 Subject: [PATCH 034/150] doc(cloudflare): updates (#50) --- pages/cloudflare/caching.mdx | 15 +++++++++++---- pages/cloudflare/get-started.mdx | 8 +++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/pages/cloudflare/caching.mdx b/pages/cloudflare/caching.mdx index 50e02f3..93411f3 100644 --- a/pages/cloudflare/caching.mdx +++ b/pages/cloudflare/caching.mdx @@ -33,8 +33,15 @@ npx wrangler@latest kv namespace create The binding name used in your app's worker is `NEXT_CACHE_WORKERS_KV`. -``` -[[kv_namespaces]] -binding = "NEXT_CACHE_WORKERS_KV" -id = "" +```jsonc +// wrangler.json +{ + // ... + "kv_namespaces": [ + { + "binding": "NEXT_CACHE_WORKERS_KV", + "id": "" + } + ] +} ``` diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 8817ae9..ccb2907 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -129,14 +129,16 @@ Add the following to the scripts field of your `package.json` file: ```json "build:worker": "opennextjs-cloudflare", "dev:worker": "wrangler dev --port 8771", -"preview:worker": "npm run build:worker && npm run dev:worker", -"deploy:worker": "npm run build:worker && wrangler deploy" +"preview": "npm run build:worker && npm run dev:worker", +"deploy": "npm run build:worker && wrangler deploy", +"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts", ``` - `npm run build:worker`: Runs the [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter. This first builds your app by running the `build` script in your `package.json` (Next.js apps use `next build` by default), and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. The build command used by OpenNext can be overridden with the `buildCommand` option in your OpenNext config. - `npm run dev:worker`: Takes the output generated by `build:worker` and runs it locally in [workerd](https://github.com/cloudflare/workerd), the open-source Workers Runtime, allowing you to run the app locally in the same environment that it will run in production. If you instead run `next dev`, your app will run in Node.js, which is a different JavaScript runtime from the Workers runtime, with differences in behavior and APIs. -- `npm run preview:worker`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. +- `npm run preview`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. - `npm run deploy`: Builds your app, and then deploys it to Cloudflare +- `cf-typegen`: Generates a `cloudflare-env.d.ts` file at the root of your project containing [the types for the `env`](https://developers.cloudflare.com/workers/wrangler/commands/#types). ##### 7. Add caching with Workers KV From 8165bc649176530e8c7571043d94061975a45354 Mon Sep 17 00:00:00 2001 From: conico974 Date: Fri, 17 Jan 2025 16:11:51 +0100 Subject: [PATCH 035/150] Docs for aws 3.4 (#51) --- pages/aws/config/overrides/_meta.json | 3 +- .../overrides/automatic_cdn_invalidation.mdx | 34 ++++ pages/aws/config/overrides/image_loader.mdx | 30 ++- .../config/overrides/incremental_cache.mdx | 65 +++++- pages/aws/config/overrides/queue.mdx | 36 +++- pages/aws/config/overrides/tag_cache.mdx | 32 ++- pages/aws/config/overrides/wrapper.mdx | 59 ++++++ pages/aws/contribute/local_run.mdx | 186 +++--------------- 8 files changed, 276 insertions(+), 169 deletions(-) create mode 100644 pages/aws/config/overrides/automatic_cdn_invalidation.mdx diff --git a/pages/aws/config/overrides/_meta.json b/pages/aws/config/overrides/_meta.json index b936b59..5e89222 100644 --- a/pages/aws/config/overrides/_meta.json +++ b/pages/aws/config/overrides/_meta.json @@ -7,5 +7,6 @@ "image_loader": "Image Loader", "proxy_external_request": "External Request Proxy", "origin_resolver": "Origin Resolver", - "invoke_function": "Invoke Function for the warmer" + "invoke_function": "Invoke Function for the warmer", + "automatic_cdn_invalidation": "Automatic CDN Invalidation" } \ No newline at end of file diff --git a/pages/aws/config/overrides/automatic_cdn_invalidation.mdx b/pages/aws/config/overrides/automatic_cdn_invalidation.mdx new file mode 100644 index 0000000..268c8dc --- /dev/null +++ b/pages/aws/config/overrides/automatic_cdn_invalidation.mdx @@ -0,0 +1,34 @@ +import {Callout} from 'nextra/components' + +Available since `@opennextjs/aws` 3.4.0 + +This override is used by OpenNext when routes have been On-Demand revalidated and the CDN needs to be updated. It is not called for ISR revalidation. +It will be called for `revalidatePath`, `revalidateTag` and `res.revalidate()`. + +If you want to better understand how to implement your own Automatic CDN Invalidation, the easiest way would be to take a look at the existing [included Automatic CDN Invalidation](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/cdnInvalidation) + +## Included Automatic CDN Invalidation + +### dummy + +The Dummy AutomaticCDNInvalidation is a dummy implementation that will do nothing. It is the default implementation. + +### cloudfront + + +Cloudfront invalidation can be very expensive. Manual CloudFront path invalidation incurs costs. According to the [AWS CloudFront pricing page](https://aws.amazon.com/cloudfront/pricing/): + +> No additional charge for the first 1,000 paths requested for invalidation each month. Thereafter, $0.005 per path requested for invalidation. + +This implementation will send an invalidation request for every route that needs to be invalidated (the request invalidates 2 paths, one for the route itself and one for the data route). + +Tag cache invalidation could end up triggering thousands of invalidation requests. + +Only use this implementation if you are aware of the costs and are willing to pay for it. + + +The CloudFront Automatic CDN Invalidation will invalidate the cache of the CloudFront distribution. + +##### Requirements + +- You need to provide the `CLOUDFRONT_DISTRIBUTION_ID` environment variable to your server. \ No newline at end of file diff --git a/pages/aws/config/overrides/image_loader.mdx b/pages/aws/config/overrides/image_loader.mdx index 459b14c..2520cdf 100644 --- a/pages/aws/config/overrides/image_loader.mdx +++ b/pages/aws/config/overrides/image_loader.mdx @@ -2,4 +2,32 @@ This override is used by OpenNext and more specifically by the image server to b This is used for internal image only (i.e. src without host). External source are already handled by the image server. -If you want to better understand how to implement your own ImageLoader, the easiest way would be to take a look at the existing [included ImageLoader](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/imageLoader). \ No newline at end of file +If you want to better understand how to implement your own ImageLoader, the easiest way would be to take a look at the existing [included ImageLoader](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/imageLoader). + +## Included ImageLoader + +### s3 + +The S3 ImageLoader will load images from an S3 bucket. It is used by default if you don't provide any ImageLoader in your configuration. +It uses the `@aws-sdk/client-s3` to interact with S3. + +##### Requirements + +- You need to provide the `BUCKET_KEY_PREFIX`, `BUCKET_NAME` environment variables to your server. + +### host + +The Host ImageLoader will load images from the host. +This implementation will directly fetch the image from the host. + +##### Requirements + +The host should be provided in the headers of the request, either in the `X-Forwarded-Host` or the `Host` header. + +### fs-dev + +The FsDev ImageLoader is a simple implementation that loads images from the `.open-next/assets` folder and interact with it using the filesystem. It is useful for development purposes only. + +### dummy + +The Dummy ImageLoader is a dummy implementation that will throw an exception. It should not be used. \ No newline at end of file diff --git a/pages/aws/config/overrides/incremental_cache.mdx b/pages/aws/config/overrides/incremental_cache.mdx index de287ce..0e9ca3d 100644 --- a/pages/aws/config/overrides/incremental_cache.mdx +++ b/pages/aws/config/overrides/incremental_cache.mdx @@ -1,3 +1,5 @@ +import { Callout } from 'nextra/components'; + This override is used by the [`cache` adapter](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/adapters/cache.ts) that is provided by OpenNext to the NextServer. It is also used by OpenNext if `enableCacheInterception` is set to `true` in the configuration. It is used for retrieving and updating the ISR/SSG cache as well as the fetch cache used by Next.js. It does not handle anything related to cache tags (i.e. `revalidateTag` and `revalidatePath`) @@ -5,4 +7,65 @@ It is used for retrieving and updating the ISR/SSG cache as well as the fetch ca If you want to better understand how to implement your own IncrementalCache, the easiest way would be to take a look at the existing [included IncrementalCache](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/incrementalCache). One thing to note is that it is not used at build time, only at runtime. This means that you'll have to upload the cache yourself if you want to use the prebuilt routes/pages (And this is mandatory for ISR/SSG routes with `fallback:false`). -All the cache files are present in the `.open-next/cache` folder. The one under `BUILD_ID` are for the ISR/SSG cache and the one under `__fetch/BUILD_ID` are for the fetch cache. \ No newline at end of file +All the cache files are present in the `.open-next/cache` folder. The one under `BUILD_ID` are for the ISR/SSG cache and the one under `__fetch/BUILD_ID` are for the fetch cache. + +## Included IncrementalCache + +### s3 + +The S3 IncrementalCache will store fetch and ISR/SSG cache in an S3 bucket. It is used by default if you don't provide any IncrementalCache in your configuration. +It uses the `@aws-sdk/client-s3` to interact with S3. + +##### Requirements + +- You need to provide the `CACHE_BUCKET_REGION`, `CACHE_BUCKET_KEY_PREFIX`, `CACHE_BUCKET_NAME` environment variables to your server. + +### s3-lite + +The S3Lite IncrementalCache will store fetch and ISR/SSG cache in an S3 bucket +This implementation is a lighter version of the `s3` IncrementalCache as it uses `aws4fetch` to interact with S3. + +##### Requirements + +- You need to provide the `CACHE_BUCKET_REGION`, `CACHE_BUCKET_KEY_PREFIX`, `CACHE_BUCKET_NAME`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment variables to your server. + +### dummy + +The Dummy IncrementalCache is a dummy implementation that throws exceptions for every method. It should not be used unless you want to disable the cache. + +### fs-dev + +The FsDev IncrementalCache is a simple implementation that stores the cache in the `.open-next/cache` folder and interact with it using the filesystem. It is useful for development purposes only. + +##### Requirements + +It needs to run on the local filesystem, and expect to be run from the OpenNext output. + +### multi-tier-ddb-s3 + + +Because of how it works, this implementation is only eventually consistent and errors during update could cause inconsistencies between the local cache in some instances and the S3 cache. + +It could also end up being slower (and more expensive) than simpler implementations if used in a low traffic serverless environment. + + +The MultiTierDdbS3 IncrementalCache is a more complex implementation. +Cache are stored in a local In Memory LRU cache as well as in S3. DynamoDB is used to keep local cache in sync between multiple instances of the server. +It uses `aws4fetch` to interact with S3 and DynamoDB. + +##### How does it work + +On get : +1. When a cache is requested, it first checks the local cache. If the cache is not found, it will fetch it from S3 and store it in the local cache. +2. If the local cache exist for this key, it will check metadata in DynamoDB to see if the cache is still valid. If it is not, it will fetch the cache from S3 and store it in the local cache. +3. If the local cache is valid, it will return it. + +On update : +1. When a cache is updated, it will first try to update the cache in S3. +2. If the update is successful, it will update the metadata in DynamoDB. +3. Finally, it will update the local cache. + +##### Requirements + +- You need to provide the `CACHE_BUCKET_REGION`, `CACHE_BUCKET_KEY_PREFIX`, `CACHE_BUCKET_NAME`, `CACHE_DYNAMO_TABLE`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN`, `OPEN_NEXT_LOCAL_CACHE_TTL_MS` (optional), `OPEN_NEXT_LOCAL_CACHE_SIZE`(optional) environment variables to your server. +- DynamoDB table should have a primary key `path` of type `String` and a sort key `tag` of type `String`. (It can reuse the same table as the one used by the default `tagCache`) \ No newline at end of file diff --git a/pages/aws/config/overrides/queue.mdx b/pages/aws/config/overrides/queue.mdx index 359ac8c..c081ca3 100644 --- a/pages/aws/config/overrides/queue.mdx +++ b/pages/aws/config/overrides/queue.mdx @@ -1,3 +1,5 @@ +import {Callout} from 'nextra/components' + This override is used by OpenNext to trigger the revalidation of stale routes. Before sending the response to the client, OpenNext will check if the route is stale and if it is, it will call the queue override to revalidate the route. @@ -5,4 +7,36 @@ If you want to better understand how to implement your own Queue, the easiest wa Couple of things to note : - The default implementation use an SQS queue. This has the main advantage of being able to control the concurrency of the revalidations as well as avoiding trigerring the revalidation multiple times for the same route. -- You don't have to use a queue at all. You could trigger the revalidation directly in the Queue override itself. You can see a very simple implementation of this [in the `queue` override](/aws/contribute/local_run#devqueuets). \ No newline at end of file +- You don't have to use a queue at all. You could trigger the revalidation directly in the Queue override itself. You can see a very simple implementation of this [in the `queue` override](/aws/contribute/local_run#devqueuets). + +## Included Queue + +### sqs + +The SQS Queue will send a message to an SQS queue for each route that needs to be revalidated. It is used by default if you don't provide any Queue in your configuration. +It uses the `@aws-sdk/client-sqs` to interact with SQS. + +#### Requirements + +- You need to provide the `QUEUE_URL` environment variable to your server. + +### sqs-lite + +The SQSLite Queue will send a message to an SQS queue for each route that needs to be revalidated. +This implementation is a lighter version of the `sqs` Queue as it uses `aws4fetch` to interact with SQS. + +#### Requirements + +- You need to provide the `QUEUE_URL`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment variables to your server. + +### direct + +The Direct Queue will directly trigger the revalidation of the route in the Queue override itself. It is useful for development purposes and when you don't want to use a queue. + + +Be careful with this implementation as it could lead to multiple revalidations of the same route. + + +### dummy + +The Dummy Queue is a dummy implementation that will throw an exception. It should not be used unless you want to disable ISR. \ No newline at end of file diff --git a/pages/aws/config/overrides/tag_cache.mdx b/pages/aws/config/overrides/tag_cache.mdx index 7cd278a..47575dd 100644 --- a/pages/aws/config/overrides/tag_cache.mdx +++ b/pages/aws/config/overrides/tag_cache.mdx @@ -9,4 +9,34 @@ This also has the drawback of needing to prepopulate the cache with all the tags We might allow to choose how cache tags are handled in the future depending on the `TagCache` implementation. If you need this feature, feel free to open an issue on the [GitHub repository](https://github.com/opennextjs/opennextjs-aws). -If you want to better understand how to implement your own TagCache, the easiest way would be to take a look at the existing [included TagCache](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/tagCache). \ No newline at end of file +If you want to better understand how to implement your own TagCache, the easiest way would be to take a look at the existing [included TagCache](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/tagCache). + +## Included TagCache + +### dynamodb + +The DynamoDB TagCache will store the cache tags in a DynamoDB table. It is used by default if you don't provide any TagCache in your configuration. +It uses the `@aws-sdk/client-dynamodb` to interact with DynamoDB. + +##### Requirements + +- You need to provide the `CACHE_DYNAMO_TABLE`, `CACHE_BUCKET_REGION` environment variable to your server. +- DynamoDB table should have a primary key `path` of type `String` and a sort key `tag` of type `String`. (It can reuse the same table as the one used by the default `tagCache`) + +### dynamodb-lite + +The DynamoDBLite TagCache will store the cache tags in a DynamoDB table. +This implementation is a lighter version of the `dynamodb` TagCache as it uses `aws4fetch` to interact with DynamoDB. + +##### Requirements + +- You need to provide the `CACHE_DYNAMO_TABLE`, `CACHE_BUCKET_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment variables to your server. +- DynamoDB table should have a primary key `path` of type `String` and a sort key `tag` of type `String`. (It can reuse the same table as the one used by the default `tagCache`) + +### dummy + +The Dummy TagCache is a dummy implementation that will throw an exception. It should not be used unless you want to disable cache tags. + +### fs-dev + +The FsDev TagCache is a simple implementation that stores the cache tags in a file in the `.open-next/cache` folder and interact with it using the filesystem. It is useful for development purposes only. \ No newline at end of file diff --git a/pages/aws/config/overrides/wrapper.mdx b/pages/aws/config/overrides/wrapper.mdx index 913edcb..3d81b00 100644 --- a/pages/aws/config/overrides/wrapper.mdx +++ b/pages/aws/config/overrides/wrapper.mdx @@ -7,3 +7,62 @@ Couple of things to note : - If you don't use streaming (like in the default `aws-lambda` wrapper), you may still need to provide a fake `StreamCreator` to the `handler` to avoid a weird issue with Node itself (see [here](https://github.com/opennextjs/opennextjs-aws/blob/f685ddea8f8a5c82591dc02713aff7138f2d9896/packages/open-next/src/overrides/wrappers/aws-lambda.ts#L49-L65) for an example and a more thorough explanation). - If you use the `edge` runtime of Next (either for the external middleware or for an `edge` route or page), you don't need the `StreamCreator` at all. - If you are in a serverless environment and it supports `waitUntil`, you should define it here(see [here](https://github.com/opennextjs/opennextjs-aws/blob/f685ddea8f8a5c82591dc02713aff7138f2d9896/packages/open-next/src/overrides/wrappers/cloudflare.ts#L29)). This might not be necessary depending on where you run it (for example the `aws-lambda-streaming` or the `node` wrapper doesn't need it.) + + +## Included Wrappers + +### aws-lambda + +The `aws-lambda` Wrapper is the default wrapper for AWS Lambda. It is used by default if you don't provide any Wrapper in your configuration. + +#### Features +- [ ] Streaming +- [ ] Proper support for `waitUntil` + +### aws-lambda-streaming + +The `aws-lambda-streaming` Wrapper is a wrapper that allows you to use streaming in AWS Lambda. Streaming must be enabled for this lambda. + +#### Features +- [x] Streaming +- [x] Proper support for `waitUntil` + +### cloudflare-edge + +The `cloudflare-edge` Wrapper is the wrapper for Cloudflare Workers. It should be used for the external middleware and for the `edge` runtime of Next. + +#### Features +- [x] Streaming +- [x] Proper support for `waitUntil` + +### cloudflare-node + +The `cloudflare-node` Wrapper is the wrapper for Cloudflare Workers. It should be used only with the `node` runtime of Next and if you use `@opennextjs/cloudflare`. + +#### Features +- [x] Streaming +- [x] Proper support for `waitUntil` + +### node + +The `node` Wrapper is the wrapper for classic Node.js Server. This one is a long running server. + +#### Features +- [x] Streaming +- [x] Proper support for `waitUntil` + +### express-dev + +The `express-dev` Wrapper is the wrapper for a classic Express server. It is a long running process and should be used for development purposes only. + +#### Features +- [x] Streaming +- [x] Proper support for `waitUntil` + +### dummy + +The `dummy` Wrapper is a dummy implementation that will just forward the event and `StreamCreator` to the handler. + +#### Features +- [ ] Streaming +- [ ] Proper support for `waitUntil` \ No newline at end of file diff --git a/pages/aws/contribute/local_run.mdx b/pages/aws/contribute/local_run.mdx index ec058eb..970a2cf 100644 --- a/pages/aws/contribute/local_run.mdx +++ b/pages/aws/contribute/local_run.mdx @@ -1,4 +1,5 @@ -When making some changes to OpenNext, it can be a bit cumbersome to need to deploy every time you want to test changes. If your change is not dependent on the wrapper or the converter, then you can create a custom `open-next.config.ts` file (you can use another name so that it doesn't conflict with your existing `open-next.config.ts`). Here is an example with a bunch of custom overrides: +When making some changes to OpenNext, it can be a bit cumbersome to need to deploy every time you want to test changes. If your change is not dependent on the wrapper or the converter, then you can create a custom `open-next.config.ts` file (you can use another name so that it doesn't conflict with your existing `open-next.config.ts`). + To run `OpenNext` locally: ```bash @@ -12,179 +13,36 @@ node .open-next/server-functions/default/index.mjs // open-next.local.config.ts - // A good practice would be to use a different name so that it doesn't conflict // with your existing open-next.config.ts i.e. open-next.local.config.ts -import type {OpenNextConfig} from '@opennextjs/aws/types/open-next.js' +// You could also customize it by using custom overrides if you need to. +import type {OpenNextConfig} from "@opennextjs/aws/types/open-next.js" -const config = { +export default { default: { - override:{ - // We use a custom wrapper so that we can use static assets and image optimization locally - wrapper: () => import('./dev/wrapper').then(m => m.default), - // ISR and SSG won't work properly locally without this - Remove if you only need SSR - incrementalCache: () => import('./dev/incrementalCache').then(m => m.default), - // ISR requires a queue to work properly - Remove if you only need SSR or SSG - queue: () => import('./dev/queue').then(m => m.default), - converter: 'node', + override: { + wrapper: "express-dev", + converter: "node", + incrementalCache: "fs-dev", + queue: "direct", + tagCache: "fs-dev" } }, - // You don't need this part if you don't use image optimization or don't need it in your test + imageOptimization: { - // Image optimization only work on linux, and you have to use the correct architecture for your system - arch: 'x64', override: { - wrapper: 'node', - converter: 'node', + wrapper: "dummy", + converter: "dummy" + }, + loader: "fs-dev", + // This part is not needed on arm linux, and image optimization will only work in linux + install: { + arch: "x64", + packages: ["sharp"] } - // If you need to test with local assets, you'll have to override the imageLoader as well }, - dangerous: { - // We disable the cache tags as it will usually not be needed locally for testing - // It's only used for next/cache revalidateTag and revalidatePath - // If you need it you'll have to override the tagCache as well - disableTagCache: true, - - - // You can uncomment this line if you only need to test SSR - //disableIncrementalCache: true, - }, - // You can override the build command so that you don't have to rebuild the app every time - // You need to have run the default build command at least once - buildCommand: 'echo "no build command"', - edgeExternals: ['./dev/wrapper', './dev/incrementalCache', './dev/queue'], + // You can override the build command here so that you don't have to rebuild next every time you make a change + //buildCommand: "echo 'No build command'", } satisfies OpenNextConfig export default config ``` - -### dev/wrapper.ts - -```typescript -// dev/wrapper.ts -// You'll need to install express -import express from 'express' -// The proxy is used to proxy the image optimization server -// you don't have to use it, but image request will return 500 error -import proxy from 'express-http-proxy' -import { fork } from 'child_process' - -import type { StreamCreator } from "@opennextjs/aws/types/open-next.js"; -import type { WrapperHandler } from "@opennextjs/aws/types/overrides.js"; - -const wrapper: WrapperHandler = async (handler, converter) => { - const app = express(); - // To serve static assets - app.use(express.static('../../assets')) - - //Launch image server fork - fork('../../image-optimization-function/index.mjs', [], { - env: { - NODE_ENV: 'development', - PORT: '3001', - } - }) - app.use('/_next/image', proxy('localhost:3001')) - - app.all('*', async (req, res) => { - const internalEvent = await converter.convertFrom(req); - const _res : StreamCreator = { - writeHeaders: (prelude) => { - res.writeHead(prelude.statusCode, prelude.headers); - res.uncork(); - return res; - }, - onFinish: () => { - // Is it necessary to do something here? - }, - }; - await handler(internalEvent, _res); - }); - - const server = app.listen(parseInt(process.env.PORT ?? "3000", 10), ()=> { - console.log(`Server running on port ${process.env.PORT ?? 3000}`); - }) - - - app.on('error', (err) => { - console.error('error', err); - }); - - return () => { - server.close(); - }; -}; - -export default { - wrapper, - name: "dev-node", - supportStreaming: true, -}; -``` - -### dev/incrementalCache.ts -```typescript -// dev/incrementalCache.ts -import type { IncrementalCache } from '@opennextjs/aws/types/overrides.js' - -import fs from 'node:fs/promises' -import path from 'node:path' - -const buildId = process.env.NEXT_BUILD_ID -const basePath= path.resolve(process.cwd(), `../../cache/${buildId}`) - -const getCacheKey = (key: string) => { - return path.join(basePath, `${key}.cache`) -} - -const cache: IncrementalCache = { - name: 'dev-fs', - get: async (key: string) => { - const fileData = await fs.readFile(getCacheKey(key), 'utf-8') - const data = JSON.parse(fileData) - const {mtime} = await fs.stat(getCacheKey(key)) - return { - value: data, - lastModified: mtime.getTime(), - } - }, - set: async (key, value, isFetch) => { - const data = JSON.stringify(value) - await fs.writeFile(getCacheKey(key), data) - }, - delete: async (key) => { - await fs.rm(getCacheKey(key)) - } -} - -export default cache -``` - -### dev/queue.ts - -```typescript -// dev/queue.ts -import type { Queue } from '@opennextjs/aws/types/overrides.js' - -declare global { - // This is declared in the global scope so that we can use it in the queue - // We need to use this one as next overrides the global fetch - var internalFetch: typeof fetch -} - -const queue: Queue = { - name: 'dev-queue', - send: async (message) => { - const prerenderManifest = (await import('@opennextjs/aws/adapters/config.js')).PrerenderManifest as any - const revalidateId : string = prerenderManifest.preview.previewModeId - await globalThis.internalFetch(`http://localhost:3000${message.MessageBody.url}`, { - method: "HEAD", - headers: { - "x-prerender-revalidate": revalidateId, - "x-isr": "1", - }, - },) - console.log('sending message', message) - }, -} - -export default queue -``` From 29393e43c406dad06201020f965f94bba0ce7fd9 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 17 Jan 2025 16:41:10 +0100 Subject: [PATCH 036/150] doc: Composable Caching is not supported yet (#52) --- pages/aws/comparison.mdx | 38 +++++++++++++++++++------------------- pages/aws/index.mdx | 5 +++-- pages/cloudflare/index.mdx | 3 ++- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/pages/aws/comparison.mdx b/pages/aws/comparison.mdx index f03a52c..1f0a522 100644 --- a/pages/aws/comparison.mdx +++ b/pages/aws/comparison.mdx @@ -1,25 +1,25 @@ -It should be noted that open-next does not actually deploy the app. It only bundles everything for your IAC to deploy it. +It should be noted that open-next does not actually deploy the app. It only bundles everything for your IAC to deploy it. Here is a table comparing the different options to deploy a next.js app: -| Features | OpenNext | Vercel | AWS Amplify | Docker Standalone | -| --- | --- | --- | --- | --- | -| **Function splitting** | Yes | Yes | No | No | -| **Multiple deployment target** ¹ | Yes | Yes ² | No | No | -| **Serverless** | Yes | Yes | Yes | No ³ | -| **Warmer function** | Yes | No | No | Not necessary | -| **External middleware** | Yes ⁴ | Yes | No | No | -| **Edge runtime support** | Partial Support ⁵ | Yes | Embedded ⁶ | Embedded ⁶ | -| **ISR** | Yes | Yes | Yes | Yes ⁷ | -| **On-Demand Revalidation** | Yes ⁸ | Yes | No | Yes ⁸ | -| **Custom server** | Yes ⁹ | No | No | Yes | +| Features | OpenNext | Vercel | AWS Amplify | Docker Standalone | +| -------------------------------- | ----------------- | ------ | ----------- | ----------------- | +| **Function splitting** | Yes | Yes | No | No | +| **Multiple deployment target** ¹ | Yes | Yes ² | No | No | +| **Serverless** | Yes | Yes | Yes | No ³ | +| **Warmer function** | Yes | No | No | Not necessary | +| **External middleware** | Yes ⁴ | Yes | No | No | +| **Edge runtime support** | Partial Support ⁵ | Yes | Embedded ⁶ | Embedded ⁶ | +| **ISR** | Yes | Yes | Yes | Yes ⁷ | +| **On-Demand Revalidation** | Yes ⁸ | Yes | No | Yes ⁸ | +| **Custom server** | Yes ⁹ | No | No | Yes | 1. Multiple deployment target means that you can deploy the same app to different target like some part to ECS, some part to Lambda etc... 2. Vercel supports only serverless Node (backed by AWS Lambda) and Edge runtime (backed by cloudflare workers) -2. You can deploy a dockerized next.js app to AWS lambda using AWS Lambda Web adapter, but some part like ISR will not work as expected -3. OpenNext supports external middleware, but it is not enabled by default. -4. OpenNext supports edge runtime in node, but every route needs to be deployed separately. OpenNext supports edge runtime in cloudflare workers, but only for app router api routes. -5. Embedded means that the edge runtime is embedded inside the bundle. It emulates a fake edge runtime inside the prod environment. -6. You might experience some inconsistencies with ISR if you have a CDN in front of your app. Next always set the cache-control header to `s-maxage=REVALIDATION_TIME, stale-while-revalidate`, it means that your data (json or rsc) and your html might be out of sync. -7. You need to invalidate the CDN manually. For OpenNext, here is an example for cloudfront -8. OpenNext supports custom server, but it is not enabled by default. You can have a custom server even in a serverless environment. \ No newline at end of file +3. You can deploy a dockerized next.js app to AWS lambda using AWS Lambda Web adapter, but some part like ISR will not work as expected +4. OpenNext supports external middleware, but it is not enabled by default. +5. OpenNext supports edge runtime in node, but every route needs to be deployed separately. OpenNext supports edge runtime in cloudflare workers, but only for app router api routes. +6. Embedded means that the edge runtime is embedded inside the bundle. It emulates a fake edge runtime inside the prod environment. +7. You might experience some inconsistencies with ISR if you have a CDN in front of your app. Next always set the cache-control header to `s-maxage=REVALIDATION_TIME, stale-while-revalidate`, it means that your data (json or rsc) and your html might be out of sync. +8. You need to invalidate the CDN manually. For OpenNext, here is an example for cloudfront +9. OpenNext supports custom server, but it is not enabled by default. You can have a custom server even in a serverless environment. diff --git a/pages/aws/index.mdx b/pages/aws/index.mdx index 3290d80..39d6e43 100644 --- a/pages/aws/index.mdx +++ b/pages/aws/index.mdx @@ -28,7 +28,7 @@ We need your help keeping it up to date and feature complete. Make sure to [**jo --- -OpenNext aims to support all Next.js 14 features. Some features are work in progress. Please open a [new issue](https://github.com/opennextjs/opennextjs-aws/issues/new) to let us know! +OpenNext aims to support all Next.js 15 features. Some features are work in progress. Please open a [new issue](https://github.com/opennextjs/opennextjs-aws/issues/new) to let us know! - [x] App & Pages Router - [x] API routes @@ -41,7 +41,8 @@ OpenNext aims to support all Next.js 14 features. Some features are work in prog - [x] [NextAuth.js](https://next-auth.js.org) - [x] [Running in lambda@edge](/aws/config/simple_example#running-in-lambdaedge) - [x] [No cold start](/aws/inner_workings/components/warmer) -- [x] Experimental streaming support +- [x] Support for after +- [ ] [Composable Caching](https://nextjs.org/blog/composable-caching) (`'use cache'`) is a Next.js 15 feature and not supported yet. --- diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 58a42ae..580a8dc 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -54,7 +54,8 @@ We will update the list as we progress towards releasing 1.0. - [ ] [Pages Router](https://nextjs.org/docs/pages) (you should use the App Router instead, which was introduced in Next.js 13) - [ ] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) - [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) -- [ ] [Experimental streaming support](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) +- [ ] [Support for after](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) +- [ ] [Composable Caching](https://nextjs.org/blog/composable-caching) (`'use cache'`) is a Next.js 15 feature and not supported yet. We welcome both contributions and feedback! From fa42384274a957ed4da3cd80bad5667dc8f33228 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Tue, 21 Jan 2025 11:28:49 +0100 Subject: [PATCH 037/150] Add schema to wrangler.json (#53) --- pages/cloudflare/get-started.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index ccb2907..4a3a37a 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -45,6 +45,7 @@ application to be previewed and deployed, it is also where you configure your Wo You can create one yourself in the root directory of your Next.js app with the name `wrangler.json` and the following content: ```jsonc { + "$schema": "node_modules/wrangler/config-schema.json", "main": ".open-next/worker.js", "name": "my-app", "compatibility_date": "2024-12-30", From 414bc8543cdc36ab76bdd14bd7cc7eae1287a177 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Fri, 24 Jan 2025 21:28:17 +0000 Subject: [PATCH 038/150] add missing backticks to `@opennextjs/cloudflare` references (#56) --- pages/cloudflare/examples.mdx | 2 +- pages/cloudflare/get-started.mdx | 2 +- pages/cloudflare/index.mdx | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pages/cloudflare/examples.mdx b/pages/cloudflare/examples.mdx index 22c2ae3..ca3c6bd 100644 --- a/pages/cloudflare/examples.mdx +++ b/pages/cloudflare/examples.mdx @@ -3,7 +3,7 @@ import { Callout } from 'nextra/components'; ## Examples -To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: +To create a new Next.js app, pre-configured to run on Cloudflare using `@opennextjs/cloudflare`, run: ``` npm create cloudflare@latest -- my-next-app --framework=next --experimental diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 4a3a37a..b93a4b3 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -5,7 +5,7 @@ import { Callout } from 'nextra/components'; #### New apps -To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: +To create a new Next.js app, pre-configured to run on Cloudflare using `@opennextjs/cloudflare`, run: ``` npm create cloudflare@latest -- my-next-app --framework=next --experimental diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 580a8dc..4156bbd 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -17,7 +17,7 @@ You can also use [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cl ##### New apps -To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run: +To create a new Next.js app, pre-configured to run on Cloudflare using `@opennextjs/cloudflare`, run: ``` npm create cloudflare@latest -- my-next-app --framework=next --experimental @@ -63,10 +63,10 @@ We welcome both contributions and feedback! -### How @opennextjs/cloudflare Works +### How `@opennextjs/cloudflare` Works The OpenNext Cloudflare adapter works by taking the Next.js build output and transforming it, so that it can run in Cloudflare Workers. When you add [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) as a dependency to your Next.js app, and then run `npx opennextjs-cloudflare` the adapter first builds your app by running the `build` script in your `package.json`, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. -You can view the code for @opennextjs/cloudflare [here](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src) to understand what it does under the hood. +You can view the code for `@opennextjs/cloudflare` [here](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src) to understand what it does under the hood. From 032edf97efd81ea0e2e8bab64e4377311848b30c Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Fri, 24 Jan 2025 21:28:31 +0000 Subject: [PATCH 039/150] remove doc comment in Cloudflare get started telling people to use the app router instead of the pages one (#55) --- pages/cloudflare/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 4156bbd..0457ca1 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -51,7 +51,7 @@ We will update the list as we progress towards releasing 1.0. - [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/app/building-your-application/rendering/server-components) - [x] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) - [x] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) -- [ ] [Pages Router](https://nextjs.org/docs/pages) (you should use the App Router instead, which was introduced in Next.js 13) +- [ ] [Pages Router](https://nextjs.org/docs/pages) - [ ] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) - [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) - [ ] [Support for after](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) From 3ad453ff1c4ea3de2dacf7678e90e3a0c9ef9b7f Mon Sep 17 00:00:00 2001 From: Lubomir Georgiev Date: Thu, 23 Jan 2025 14:59:30 +0200 Subject: [PATCH 040/150] doc(cloudflare): Add a SaaS template to the examples page --- pages/cloudflare/examples.mdx | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/pages/cloudflare/examples.mdx b/pages/cloudflare/examples.mdx index ca3c6bd..fddad40 100644 --- a/pages/cloudflare/examples.mdx +++ b/pages/cloudflare/examples.mdx @@ -23,3 +23,33 @@ You can use these to understand how to configure your Next.js app to use `@openn ### Next.js Commerce Demo The [Next.js Commerce demo app](https://github.com/vercel/commerce/tree/v1) works with `@opennextjs/cloudflare`. You can view a deployed version of it [here](https://vercel-commerce-on-workers.web-experiments.workers.dev/). + +### Fully-featured SaaS starter kit + +The [Cloudflare Workers SaaS template](https://github.com/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template) is a fully-featured SaaS app that works with `@opennextjs/cloudflare` and utilizes lots of other Cloudflare services. +Here is a list of some of the features it includes: + +- Custom authentication with password and Google SSO + - Session storage in Cloudflare KV + - Drizzle ORM and Cloudflare D1 + - Forgot password + - Change password + - Change user settings +- Shadcn for the UI +- Light/Dark Theme +- Loading states and animations +- Toast alerts and notifications +- Landing page +- SEO optimization +- Protection with Cloudflare Turnstile Captcha +- Transactional email templates with react-email and integration with Resend and Brevo +- Rate Limiting with Cloudflare KV to prevent abuse +- Validation for all user actions with react-zsa and zod +- Completely type safe +- Comprehensive eslint config +- Integrated with Cursor AI +- .cursorrules +- A markdown project documentation that Cursor can refer to for more context and better responses +- Detailed documentation for local development and production deployment +- Automatic deployment using Github Actions and the Wrangler CLI +- And more... From 63c942e8896c3442a290439871a2717895c59442 Mon Sep 17 00:00:00 2001 From: Lubomir Georgiev Date: Thu, 23 Jan 2025 20:23:48 +0200 Subject: [PATCH 041/150] doc(cloudflare): Shorten the features list of the SaaS template example --- pages/cloudflare/examples.mdx | 39 ++++++++++++++++------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/pages/cloudflare/examples.mdx b/pages/cloudflare/examples.mdx index fddad40..c9191e7 100644 --- a/pages/cloudflare/examples.mdx +++ b/pages/cloudflare/examples.mdx @@ -30,26 +30,23 @@ The [Cloudflare Workers SaaS template](https://github.com/LubomirGeorgiev/cloudf Here is a list of some of the features it includes: - Custom authentication with password and Google SSO - - Session storage in Cloudflare KV - - Drizzle ORM and Cloudflare D1 - - Forgot password - - Change password - - Change user settings -- Shadcn for the UI -- Light/Dark Theme -- Loading states and animations -- Toast alerts and notifications -- Landing page -- SEO optimization -- Protection with Cloudflare Turnstile Captcha + - Session storage in Cloudflare KV + - Forgot password + - Change password + - Change user settings +- Security + - Protection with Cloudflare Turnstile Captcha + - Rate Limiting with Cloudflare KV to prevent abuse + - Validation for all user actions with react-zsa and zod +- Database: Drizzle ORM and Cloudflare D1 +- UI: Shadcn, Tailwind CSS and Hero UI (formely NextUI) - Transactional email templates with react-email and integration with Resend and Brevo -- Rate Limiting with Cloudflare KV to prevent abuse -- Validation for all user actions with react-zsa and zod -- Completely type safe -- Comprehensive eslint config -- Integrated with Cursor AI -- .cursorrules -- A markdown project documentation that Cursor can refer to for more context and better responses -- Detailed documentation for local development and production deployment -- Automatic deployment using Github Actions and the Wrangler CLI +- Dev Experience + - Completely type safe + - Comprehensive eslint config + - Integrated with Cursor AI + - .cursorrules + - A markdown project documentation that Cursor can refer to for more context and better responses + - Detailed documentation for local development and production deployment + - Automatic deployment using Github Actions and the Wrangler CLI - And more... From 704182acc27dc1d005053ca3cb6fcd32f86da1b1 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Mon, 27 Jan 2025 09:07:08 +0100 Subject: [PATCH 042/150] fixup! create a "Community projects" section --- pages/cloudflare/_meta.json | 1 + pages/cloudflare/community.mdx | 31 +++++++++++++++++++++++++++++++ pages/cloudflare/examples.mdx | 27 --------------------------- 3 files changed, 32 insertions(+), 27 deletions(-) create mode 100644 pages/cloudflare/community.mdx diff --git a/pages/cloudflare/_meta.json b/pages/cloudflare/_meta.json index 8d0c8fa..a1ffc43 100644 --- a/pages/cloudflare/_meta.json +++ b/pages/cloudflare/_meta.json @@ -4,6 +4,7 @@ "bindings": "", "caching": "", "examples": "", + "community": "Community projects", "troubleshooting": "", "migrate-from-0.2": "", "0.2": "Release 0.2" diff --git a/pages/cloudflare/community.mdx b/pages/cloudflare/community.mdx new file mode 100644 index 0000000..212a898 --- /dev/null +++ b/pages/cloudflare/community.mdx @@ -0,0 +1,31 @@ +import { SITE } from '../../config'; +import { Callout } from 'nextra/components'; + +## Projects from the community + +### Fully-featured SaaS starter kit + +The [Cloudflare Workers SaaS template](https://github.com/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template) is a fully-featured SaaS app that works with `@opennextjs/cloudflare` and utilizes lots of other Cloudflare services. +Here is a list of some of the features it includes: + +- Custom authentication with password and Google SSO + - Session storage in Cloudflare KV + - Forgot password + - Change password + - Change user settings +- Security + - Protection with Cloudflare Turnstile Captcha + - Rate Limiting with Cloudflare KV to prevent abuse + - Validation for all user actions with react-zsa and zod +- Database: Drizzle ORM and Cloudflare D1 +- UI: Shadcn, Tailwind CSS and Hero UI (formely NextUI) +- Transactional email templates with react-email and integration with Resend and Brevo +- Dev Experience + - Completely type safe + - Comprehensive eslint config + - Integrated with Cursor AI + - .cursorrules + - A markdown project documentation that Cursor can refer to for more context and better responses + - Detailed documentation for local development and production deployment + - Automatic deployment using Github Actions and the Wrangler CLI +- And more... diff --git a/pages/cloudflare/examples.mdx b/pages/cloudflare/examples.mdx index c9191e7..ca3c6bd 100644 --- a/pages/cloudflare/examples.mdx +++ b/pages/cloudflare/examples.mdx @@ -23,30 +23,3 @@ You can use these to understand how to configure your Next.js app to use `@openn ### Next.js Commerce Demo The [Next.js Commerce demo app](https://github.com/vercel/commerce/tree/v1) works with `@opennextjs/cloudflare`. You can view a deployed version of it [here](https://vercel-commerce-on-workers.web-experiments.workers.dev/). - -### Fully-featured SaaS starter kit - -The [Cloudflare Workers SaaS template](https://github.com/LubomirGeorgiev/cloudflare-workers-nextjs-saas-template) is a fully-featured SaaS app that works with `@opennextjs/cloudflare` and utilizes lots of other Cloudflare services. -Here is a list of some of the features it includes: - -- Custom authentication with password and Google SSO - - Session storage in Cloudflare KV - - Forgot password - - Change password - - Change user settings -- Security - - Protection with Cloudflare Turnstile Captcha - - Rate Limiting with Cloudflare KV to prevent abuse - - Validation for all user actions with react-zsa and zod -- Database: Drizzle ORM and Cloudflare D1 -- UI: Shadcn, Tailwind CSS and Hero UI (formely NextUI) -- Transactional email templates with react-email and integration with Resend and Brevo -- Dev Experience - - Completely type safe - - Comprehensive eslint config - - Integrated with Cursor AI - - .cursorrules - - A markdown project documentation that Cursor can refer to for more context and better responses - - Detailed documentation for local development and production deployment - - Automatic deployment using Github Actions and the Wrangler CLI -- And more... From 14a58d949b27bcae103df38c77141b4f7b376150 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Mon, 27 Jan 2025 09:12:05 +0100 Subject: [PATCH 043/150] doc(cloudflare): Add a SaaS template to the examples page (#58) Co-authored-by: Lubomir Georgiev From 986c90422ecb96c2f59853522aa01c34fb349a86 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Mon, 27 Jan 2025 18:04:43 +0000 Subject: [PATCH 044/150] cloudflare: update docs to 0.4 (#57) Co-authored-by: Victor Berchet --- pages/cloudflare/0.3/_meta.json | 7 + pages/cloudflare/0.3/bindings.mdx | 65 ++++++ pages/cloudflare/0.3/caching.mdx | 47 +++++ pages/cloudflare/0.3/examples.mdx | 25 +++ pages/cloudflare/0.3/get-started.mdx | 187 ++++++++++++++++++ pages/cloudflare/0.3/index.mdx | 72 +++++++ pages/cloudflare/_meta.json | 4 +- pages/cloudflare/bindings.mdx | 6 +- pages/cloudflare/get-started.mdx | 24 ++- ...om-0.2.mdx => migrate-from-0.2-to-0.3.mdx} | 4 +- pages/cloudflare/migrate-from-0.3-to-0.4.mdx | 38 ++++ 11 files changed, 471 insertions(+), 8 deletions(-) create mode 100644 pages/cloudflare/0.3/_meta.json create mode 100644 pages/cloudflare/0.3/bindings.mdx create mode 100644 pages/cloudflare/0.3/caching.mdx create mode 100644 pages/cloudflare/0.3/examples.mdx create mode 100644 pages/cloudflare/0.3/get-started.mdx create mode 100644 pages/cloudflare/0.3/index.mdx rename pages/cloudflare/{migrate-from-0.2.mdx => migrate-from-0.2-to-0.3.mdx} (98%) create mode 100644 pages/cloudflare/migrate-from-0.3-to-0.4.mdx diff --git a/pages/cloudflare/0.3/_meta.json b/pages/cloudflare/0.3/_meta.json new file mode 100644 index 0000000..53a20a0 --- /dev/null +++ b/pages/cloudflare/0.3/_meta.json @@ -0,0 +1,7 @@ +{ + "index": "Overview", + "get-started": "", + "bindings": "", + "caching": "", + "examples": "" +} diff --git a/pages/cloudflare/0.3/bindings.mdx b/pages/cloudflare/0.3/bindings.mdx new file mode 100644 index 0000000..ee412f0 --- /dev/null +++ b/pages/cloudflare/0.3/bindings.mdx @@ -0,0 +1,65 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; + +### Bindings + +[Bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) allow your Worker to interact with resources on the Cloudflare Developer Platform. When you declare a binding on your Worker, you grant it a specific capability, such as being able to read and write files to an [R2](https://developers.cloudflare.com/r2/) bucket. + +#### How to configure your Next.js app so it can access bindings + +Install [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare), and then add a [wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/) in the root directory of your Next.js app, as described in [Get Started](/cloudflare/get-started#3-create-a-wranglerjson-file). + +#### How to access bindings in your Next.js app + +You can access [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) from any route of your Next.js app via `getCloudflareContext`: + +```js +import { getCloudflareContext } from "@opennextjs/cloudflare"; + +export async function GET(request) { + let responseText = "Hello World"; + + const myKv = (await getCloudflareContext()).env.MY_KV_NAMESPACE; + await myKv.put("foo", "bar"); + const foo = await myKv.get("foo"); + + return new Response(foo); +} +``` + +#### How to add bindings to your Worker + +Add bindings to your Worker by adding them to your [wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). + +## TypeScript type declarations for bindings + +To ensure that the `env` object from `(await getCloudflareContext()).env` above has accurate TypeScript types, run the following Wrangler command to [generate types that match your Worker's configuration](https://developers.cloudflare.com/workers/languages/typescript/#generate-types-that-match-your-workers-configuration-experimental): + +``` +npx wrangler types --experimental-include-runtime +``` + +This will generate a `d.ts` file and (by default) save it to `.wrangler/types/runtime.d.ts`. You will be prompted in the command's output to add that file to your `tsconfig.json`'s `compilerOptions.types` array. + +If you would like to commit the file to git, you can provide a custom path. Here, for instance, the `runtime.d.ts` file will be saved to the root of your project: + +```bash +npx wrangler types --experimental-include-runtime="./runtime.d.ts" +``` + +To ensure that your types are always up-to-date, make sure to run `wrangler types --experimental-include-runtime` after any changes to your config file. + +## Other Cloudflare APIs (`cf`, `ctx`) + +You can access context about the incoming request from the [`cf` object](https://developers.cloudflare.com/workers/runtime-apis/request/#the-cf-property-requestinitcfproperties), as well as lifecycle methods from the [`ctx` object](https://developers.cloudflare.com/workers/runtime-apis/context) from the return value of [`getCloudflareContext()`](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src/api/get-cloudflare-context.ts): + +```js +import { getCloudflareContext } from "@opennextjs/cloudflare"; + + +export async function GET(request) { + const { env, cf, ctx } = await getCloudflareContext(); + + // ... +} +``` diff --git a/pages/cloudflare/0.3/caching.mdx b/pages/cloudflare/0.3/caching.mdx new file mode 100644 index 0000000..5e4688e --- /dev/null +++ b/pages/cloudflare/0.3/caching.mdx @@ -0,0 +1,47 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; + +## Caching + +`@opennextjs/cloudflare` supports [caching](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#caching-data). + +By default, all `fetch()` subrequests made in your Next.js app are cached. Refer to the [Next.js documentation](https://nextjs.org/docs/app/building-your-application/caching#opting-out-1) for information about how to disable caching for an individual subrequest, or for an entire route. + +[The cache persists across deployments](https://nextjs.org/docs/app/building-your-application/caching#data-cache). You are responsible for revalidating/purging this cache. + +Note that [Revalidating](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#revalidating-data) is not yet supported. + +Next.js primes the cache at build time. The build time values are serverd by the [Workers Assets](https://developers.cloudflare.com/workers/static-assets/). + + +Workers KV is eventually consistent, which means that it can take up to 60 seconds for updates to be reflected globally, when using the default TTL of 60 seconds. + + +### How to enable caching + +`@opennextjs/cloudflare` uses [Workers KV](https://developers.cloudflare.com/kv/) as the cache for your Next.js app. Workers KV is [fast](https://blog.cloudflare.com/faster-workers-kv) and uses Cloudflare's [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) to increase cache hit rates. When you write cached data to Workers KV, you write to storage that can be read by any Cloudflare location. This means your app can fetch data, cache it in KV, and then subsequent requests anywhere around the world can read from this cache. + +To enable caching, you must: + +#### 1. Create a KV namespace + +``` +npx wrangler@latest kv namespace create +``` + +#### 2. Add the KV namespace to your Worker + +The binding name used in your app's worker is `NEXT_CACHE_WORKERS_KV`. + +```jsonc +// wrangler.json +{ + // ... + "kv_namespaces": [ + { + "binding": "NEXT_CACHE_WORKERS_KV", + "id": "" + } + ] +} +``` diff --git a/pages/cloudflare/0.3/examples.mdx b/pages/cloudflare/0.3/examples.mdx new file mode 100644 index 0000000..deafb82 --- /dev/null +++ b/pages/cloudflare/0.3/examples.mdx @@ -0,0 +1,25 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; + +## Examples + +To create a new Next.js app, pre-configured to run on Cloudflare using `@opennextjs/cloudflare`, run: + +``` +npm create cloudflare@latest -- my-next-app --framework=next --experimental +``` + +### Basic starter projects + +Basic example apps are included in the repository for `@opennextjs/cloudflare` package: + +- [*`create-next-app`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/create-next-app) — a Next.js project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +- [*`api`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/api) — a minimal Next.js project with a single API route +- [*`middleware`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/middleware) — a minimal Next.js project using middleware +- [*`vercel-blog-starter`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/vercel-blog-starter) — a blog project using SSG + +You can use these to understand how to configure your Next.js app to use `@opennextjs/cloudflare`, or refer to [Get Started](/cloudflare/get-started). + +### Next.js Commerce Demo + +The [Next.js Commerce demo app](https://github.com/vercel/commerce/tree/v1) works with `@opennextjs/cloudflare`. You can view a deployed version of it [here](https://vercel-commerce-on-workers.web-experiments.workers.dev/). diff --git a/pages/cloudflare/0.3/get-started.mdx b/pages/cloudflare/0.3/get-started.mdx new file mode 100644 index 0000000..b3b5668 --- /dev/null +++ b/pages/cloudflare/0.3/get-started.mdx @@ -0,0 +1,187 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; + +### Get Started + +#### New apps + +To create a new Next.js app, pre-configured to run on Cloudflare using `@opennextjs/cloudflare`, run: + +``` +npm create cloudflare@latest -- my-next-app --framework=next --experimental +``` + +#### Existing Next.js apps + +##### 1. Install @opennextjs/cloudflare + +First, install [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare): + +```sh +npm install --save-dev @opennextjs/cloudflare@latest +``` + +##### 2. Install Wrangler + +Install the [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) as a devDependency: + +```npm +npm install --save-dev wrangler@latest +``` + + +You must use Wrangler version `3.99.0` or later to deploy Next.js apps using `@opennextjs/cloudflare`. + + +##### 3. Create a wrangler configuration file + + +This step is optional since `@opennextjs/cloudflare` creates this file for you during the build process (if not already present). + + +A [wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/) is needed for your +application to be previewed and deployed, it is also where you configure your Worker and define what resources it can access via [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings). + +You can create one yourself in the root directory of your Next.js app with the name `wrangler.json` and the following content: +```jsonc +{ + "$schema": "node_modules/wrangler/config-schema.json", + "main": ".open-next/worker.js", + "name": "my-app", + "compatibility_date": "2024-12-30", + "compatibility_flags": ["nodejs_compat"], + "assets": { + "directory": ".open-next/assets", + "binding": "ASSETS", + }, + "kv_namespaces": [ + // Create a KV binding with the binding name "NEXT_CACHE_WORKERS_KV" + // to enable the KV based caching: + // { + // "binding": "NEXT_CACHE_WORKERS_KV", + // "id": "" + // } + ], +} +``` + + +As shown above: + - You must enable the [`nodejs_compat` compatibility flag](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) *and* set your [compatibility date](https://developers.cloudflare.com/workers/configuration/compatibility-dates/) to `2024-09-23` or later, in order for your Next.js app to work with @opennextjs/cloudflare + - The `main` and `assets` values should also not be changed unless you modify the build output result in some way + - You can add a binding named `NEXT_CACHE_WORKERS_KV` to make use of Next.js' caching as described in the [Caching docs](/cloudflare/caching) + + +##### 4. Add an `open-next.config.ts` file + + +This step is optional since `@opennextjs/cloudflare` creates this file for you during the build process (if not already present). + + +Add a [`open-next.config.ts`](https://opennext.js.org/aws/config) file to the root directory of your Next.js app: + +```ts +import type { OpenNextConfig } from "@opennextjs/aws/types/open-next.js"; +import cache from "@opennextjs/cloudflare/kvCache"; + +const config: OpenNextConfig = { + default: { + override: { + wrapper: "cloudflare-node", + converter: "edge", + // set `incrementalCache` to "dummy" to disable KV cache + incrementalCache: async () => cache, + tagCache: "dummy", + queue: "dummy", + }, + }, + + middleware: { + external: true, + override: { + wrapper: "cloudflare-edge", + converter: "edge", + proxyExternalRequest: "fetch", + }, + }, +}; + +export default config; +``` + + +To use the `OpenNextConfig` type as illustrated above (which is not necessary), you need to install the `@opennextjs/aws` NPM package as a dev dependency. + + +##### 5. Add a `.dev.vars` file + +Then, add a [`.dev.vars`](https://developers.cloudflare.com/workers/testing/local-development/#local-only-environment-variables) file to the root directory of your Next.js app: + +```text +NEXTJS_ENV=development +``` + +The `NEXTJS_ENV` variable defines the environment to use when loading Next.js `.env` files. It defaults to "production" when not defined. + +##### 6. Update the `package.json` file + +Add the following to the scripts field of your `package.json` file: + +```json +"build:worker": "opennextjs-cloudflare", +"dev:worker": "wrangler dev --port 8771", +"preview": "npm run build:worker && npm run dev:worker", +"deploy": "npm run build:worker && wrangler deploy", +"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts", +``` + +- `npm run build:worker`: Runs the [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter. This first builds your app by running the `build` script in your `package.json` (Next.js apps use `next build` by default), and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. The build command used by OpenNext can be overridden with the `buildCommand` option in your OpenNext config. +- `npm run dev:worker`: Takes the output generated by `build:worker` and runs it locally in [workerd](https://github.com/cloudflare/workerd), the open-source Workers Runtime, allowing you to run the app locally in the same environment that it will run in production. If you instead run `next dev`, your app will run in Node.js, which is a different JavaScript runtime from the Workers runtime, with differences in behavior and APIs. +- `npm run preview`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. +- `npm run deploy`: Builds your app, and then deploys it to Cloudflare +- `cf-typegen`: Generates a `cloudflare-env.d.ts` file at the root of your project containing [the types for the `env`](https://developers.cloudflare.com/workers/wrangler/commands/#types). + +##### 7. Add caching with Workers KV + +See the [Caching docs](/cloudflare/caching) for information on enabling Next.js caching in your OpenNext project. + +##### 8. Remove any `export const runtime = "edge";` if present + +Before deploying your app, remove the `export const runtime = "edge";` line from any of your source files. + +The edge runtime is not supported yet with `@opennextjs/cloudflare`. + +##### 9. Add `.open-next` to `.gitignore` + +You should add `.open-next` to your `.gitignore` file to prevent the build output from being committed to your repository. + +##### 10. Remove `@cloudflare/next-on-pages` (if necessary) + +If your Next.js app currently uses `@cloudflare/next-on-pages`, you'll want to remove it, and make a few changes. + +Uninstalling the [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cloudflare/next-on-pages) package as well as the [`eslint-plugin-next-on-pages`](https://www.npmjs.com/package/eslint-plugin-next-on-pages) package if present. + +Remove any reference of these packages from your source and configuration files. +This includes: + - `setupDevPlatform()` calls in your Next.js config file + - `getRequestContext` imports from `@cloudflare/next-on-pages` from your source files + (those can be replaced with `getCloudflareContext` calls from `@opennextjs/cloudflare`) + - next-on-pages eslint rules set in your Eslint config file + +##### 11. Develop locally + +You can continue to run `next dev` when developing locally. + +During local development, you can access local versions of Cloudflare bindings as indicated in the [bindings documentation](./bindings). + +In step 3, we also added the `npm run preview:worker`, which allows you to quickly preview your app running locally in the Workers runtime, rather than in Node.js. This allows you to test changes in the same runtime as your app will run in when deployed to Cloudflare. + +##### 12. Deploy to Cloudflare Workers + +Either deploy via the command line: + +```sh +npm run deploy:worker +``` + +Or [connect a Github or Gitlab repository](https://developers.cloudflare.com/workers/ci-cd/), and Cloudflare will automatically build and deploy each pull request you merge to your production branch. diff --git a/pages/cloudflare/0.3/index.mdx b/pages/cloudflare/0.3/index.mdx new file mode 100644 index 0000000..3c5e7c3 --- /dev/null +++ b/pages/cloudflare/0.3/index.mdx @@ -0,0 +1,72 @@ +import { SITE } from '../../../config'; +import { Callout } from 'nextra/components'; +import WindowsSupport from '../../../shared/WindowsSupport.mdx'; + +## Cloudflare + +The [`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter lets you deploy Next.js apps to [Cloudflare Workers](https://developers.cloudflare.com/workers) using the [Node.js "runtime" from Next.js](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes). + + +[`@opennextjs/cloudflare`](https://www.npmjs.com/package/@opennextjs/cloudflare) is pre 1.0, and still in active development. You should try it, [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues), [share feedback](https://github.com/opennextjs/opennextjs-cloudflare/discussions), and contribute code to help make running Next.js apps on Cloudflare easier. We don't quite yet recommend using it for mission-critical production apps. + +You can also use [`@cloudflare/next-on-pages`](https://www.npmjs.com/package/@cloudflare/next-on-pages) to deploy Next.js apps to Cloudflare Pages. You can review the differences in supported Next.js features below and by reviewing [the docs for `@cloudflare/next-on-pages`](https://developers.cloudflare.com/pages/framework-guides/nextjs/ssr/supported-features/), and understand the differences between Workers and Pages [here](https://developers.cloudflare.com/workers/static-assets/compatibility-matrix/). + + + +### Get Started + +##### New apps + +To create a new Next.js app, pre-configured to run on Cloudflare using `@opennextjs/cloudflare`, run: + +``` +npm create cloudflare@latest -- my-next-app --framework=next --experimental +``` + +##### Existing Next.js apps + +Follow the guide [here](/cloudflare/get-started) to use [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) with an existing Next.js app. + +### Supported Next.js runtimes + +Next.js has [two "runtimes"](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes) — "Edge" and "Node.js". When you use `@opennextjs/cloudflare`, your app should use the Node.js runtime, which is more fully featured, and allows you to use the [Node.js APIs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/) that are provided by the Cloudflare Workers runtime. + +This is an important difference from `@cloudflare/next-on-pages`, which only supports the "Edge" runtime. The Edge Runtime code in Next.js [intentionally constrains which APIs from Node.js can be used](https://github.com/vercel/next.js/blob/canary/packages/next/src/build/webpack/plugins/middleware-plugin.ts#L820), and the "Edge" runtime does not support all Next.js features. + +### Supported Next.js versions + +`@opennextjs/cloudflare` is pre 1.0, and still in active development. We intend to support all minor and patch versions of Next.js 14 and 15. + +To help improve compatibility, we encourage you to [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues) and contribute code! + +### Supported Next.js features + +Some Next.js features are not yet supported are not fully tested. +We will update the list as we progress towards releasing 1.0. + +- [x] [App Router](https://nextjs.org/docs/app) +- [x] [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) +- [x] [Dynamic routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) +- [x] [Static Site Generation (SSG)](https://nextjs.org/docs/app/building-your-application/rendering/server-components#static-rendering-default) +- [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/app/building-your-application/rendering/server-components) +- [x] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) +- [x] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) +- [ ] [Pages Router](https://nextjs.org/docs/pages) +- [ ] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) +- [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) +- [ ] [Support for after](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) +- [ ] [Composable Caching](https://nextjs.org/blog/composable-caching) (`'use cache'`) is a Next.js 15 feature and not supported yet. + +We welcome both contributions and feedback! + +### Windows support + + + +### How `@opennextjs/cloudflare` Works + +The OpenNext Cloudflare adapter works by taking the Next.js build output and transforming it, so that it can run in Cloudflare Workers. + +When you add [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) as a dependency to your Next.js app, and then run `npx opennextjs-cloudflare` the adapter first builds your app by running the `build` script in your `package.json`, and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. + +You can view the code for `@opennextjs/cloudflare` [here](https://github.com/opennextjs/opennextjs-cloudflare/blob/main/packages/cloudflare/src) to understand what it does under the hood. diff --git a/pages/cloudflare/_meta.json b/pages/cloudflare/_meta.json index a1ffc43..d0150a0 100644 --- a/pages/cloudflare/_meta.json +++ b/pages/cloudflare/_meta.json @@ -6,6 +6,8 @@ "examples": "", "community": "Community projects", "troubleshooting": "", - "migrate-from-0.2": "", + "migrate-from-0.3-to-0.4": "Migrate from 0.3", + "0.3": "Release 0.3", + "migrate-from-0.2-to-0.3": "", "0.2": "Release 0.2" } diff --git a/pages/cloudflare/bindings.mdx b/pages/cloudflare/bindings.mdx index dfd8aee..48dbbfe 100644 --- a/pages/cloudflare/bindings.mdx +++ b/pages/cloudflare/bindings.mdx @@ -19,7 +19,7 @@ import { getCloudflareContext } from "@opennextjs/cloudflare"; export async function GET(request) { let responseText = "Hello World"; - const myKv = (await getCloudflareContext()).env.MY_KV_NAMESPACE; + const myKv = getCloudflareContext().env.MY_KV_NAMESPACE; await myKv.put("foo", "bar"); const foo = await myKv.get("foo"); @@ -33,7 +33,7 @@ Add bindings to your Worker by adding them to your [wrangler configuration file] ## TypeScript type declarations for bindings -To ensure that the `env` object from `(await getCloudflareContext()).env` above has accurate TypeScript types, run the following Wrangler command to [generate types that match your Worker's configuration](https://developers.cloudflare.com/workers/languages/typescript/#generate-types-that-match-your-workers-configuration-experimental): +To ensure that the `env` object from `getCloudflareContext().env` above has accurate TypeScript types, run the following Wrangler command to [generate types that match your Worker's configuration](https://developers.cloudflare.com/workers/languages/typescript/#generate-types-that-match-your-workers-configuration-experimental): ``` npx wrangler types --experimental-include-runtime @@ -58,7 +58,7 @@ import { getCloudflareContext } from "@opennextjs/cloudflare"; export async function GET(request) { - const { env, cf, ctx } = await getCloudflareContext(); + const { env, cf, ctx } = getCloudflareContext(); // ... } diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index b93a4b3..c35d63c 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -172,9 +172,29 @@ This includes: You can continue to run `next dev` when developing locally. -During local development, you can access local versions of Cloudflare bindings as indicated in the [bindings documentation](./bindings). +Modify your Next.js configuration file to import and call the `initOpenNextCloudflareForDev` utility +from the `@cloudflare/next-on-pages` package. This makes sure that the Next.js dev server can optimally integrate with the open-next +cloudflare adapter and it is necessary for using bindings during local development. -In step 3, we also added the `npm run preview:worker`, which allows you to quickly preview your app running locally in the Workers runtime, rather than in Node.js. This allows you to test changes in the same runtime as your app will run in when deployed to Cloudflare. +This is an example of a Next.js configuration file calling the utility: +```js +// next.config.mjs + +import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; + +initOpenNextCloudflareForDev(); + +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; +``` + +After having added the `initOpenNextCloudflareForDev()` call in your Next.js configuration file, you will be able, during local +development, to access in any of your server code, local versions of Cloudflare bindings as indicated in the [bindings documentation](./bindings). + +In step 3, we also added the `npm run preview:worker`, which allows you to quickly preview your app running locally in the Workers runtime, +rather than in Node.js. This allows you to test changes in the same runtime as your app will run in when deployed to Cloudflare. ##### 12. Deploy to Cloudflare Workers diff --git a/pages/cloudflare/migrate-from-0.2.mdx b/pages/cloudflare/migrate-from-0.2-to-0.3.mdx similarity index 98% rename from pages/cloudflare/migrate-from-0.2.mdx rename to pages/cloudflare/migrate-from-0.2-to-0.3.mdx index aaf01b0..68160a6 100644 --- a/pages/cloudflare/migrate-from-0.2.mdx +++ b/pages/cloudflare/migrate-from-0.2-to-0.3.mdx @@ -1,7 +1,7 @@ import { SITE } from '../../config'; import { Callout } from 'nextra/components'; -### Migrate from 0.2 +### Migrate from 0.2 to 0.3 The `@opennextjs/cloudflare` adapter is now more closely intgrated with `@opennextjs/aws`. @@ -80,4 +80,4 @@ The name of the CLI was changed to `opennextjs-cloudflare`: ##### 5 Add `.open-next` to `.gitignore` You should change `.worker-next` to `.open-next` in your `.gitignore` file to prevent the build output from being committed to your repository. -You can safely delete the content of the now unused `.worker-next`. \ No newline at end of file +You can safely delete the content of the now unused `.worker-next`. diff --git a/pages/cloudflare/migrate-from-0.3-to-0.4.mdx b/pages/cloudflare/migrate-from-0.3-to-0.4.mdx new file mode 100644 index 0000000..81c9df5 --- /dev/null +++ b/pages/cloudflare/migrate-from-0.3-to-0.4.mdx @@ -0,0 +1,38 @@ +import { SITE } from '../../config'; +import { Callout } from 'nextra/components'; + +### Migrate from 0.3 (to 0.4) + +The `@opennextjs/cloudflare@0.4.0` introduced a new `initOpenNextCloudflareForDev` utility and made `getCloudflareContext` synchronous, +we'll explore those two differences below, and how they effect applications built using `0.3.x` versions of the adapter. + +##### `initOpenNextCloudflareForDev` + +`initOpenNextCloudflareForDev` is a new utility that needs to be added to the Next.js configuration file in order to integrate the adapter +with the Next.js dev server. If you don't plan on using the `next dev` command you can skip this section, otherwise update your Next.js +configuration file to import and call the utility. + +Example: +```js +// next.config.mjs + +import { initOpenNextCloudflareForDev } from "@opennextjs/cloudflare"; + +initOpenNextCloudflareForDev(); + +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; +``` + +##### Synchronous `getCloudflareContext` synchronous + +`getCloudflareContext` is now synchronous. +a promise that resolves to it. + +This means that if you had code that `await`ed `getCloudflareContext()` calls, such `await`s are no longer necessary and +can be removed. + +If your application is instead combining the result of `getCloudflareContext()` with on Ecmascript Promises APIs such as +`then`, `catch` and `finally` those need to be removed since the function's result, as mentioned is no longer a promise. From 88dbbca79a148ee9cdfb6484042ac1633aa43b81 Mon Sep 17 00:00:00 2001 From: Leander Iversen Date: Wed, 29 Jan 2025 12:50:20 +0000 Subject: [PATCH 045/150] Fix reference to OpenNextConfig type in streaming example (#59) --- pages/aws/config/simple_example.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/aws/config/simple_example.mdx b/pages/aws/config/simple_example.mdx index 0ba089d..6a3dbe0 100644 --- a/pages/aws/config/simple_example.mdx +++ b/pages/aws/config/simple_example.mdx @@ -22,7 +22,7 @@ Here you can find the most common `open-next.config.ts` file examples that you c ```ts -import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.ts'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; const config = { default: { override: { From 511a541d62a8af237a2e0f6be9d8b4b3c915ef46 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Fri, 31 Jan 2025 11:15:21 +0100 Subject: [PATCH 046/150] Mark PPR as supported on cloudflare (#60) --- pages/cloudflare/index.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 0457ca1..63644f8 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -51,10 +51,10 @@ We will update the list as we progress towards releasing 1.0. - [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/app/building-your-application/rendering/server-components) - [x] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) - [x] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) +- [x] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) +- [ ] [Support for after](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) - [ ] [Pages Router](https://nextjs.org/docs/pages) - [ ] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) -- [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) -- [ ] [Support for after](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) - [ ] [Composable Caching](https://nextjs.org/blog/composable-caching) (`'use cache'`) is a Next.js 15 feature and not supported yet. We welcome both contributions and feedback! From 3a8c94824c379d7acfab5bfe93eb628da1a60381 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Sat, 1 Feb 2025 07:03:09 +0100 Subject: [PATCH 047/150] Bump actions in GH workflows (#63) --- .github/workflows/check.yml | 2 +- .github/workflows/nextjs.yml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 1aa9b11..2a2fc68 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -10,6 +10,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - uses: ./.github/actions/build-docs diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index da5cb73..f0fe1d8 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -32,10 +32,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v2 - name: Setup Pages - uses: actions/configure-pages@v2 + uses: actions/configure-pages@v4 with: # Automatically inject basePath in your Next.js configuration file and disable # server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized). @@ -50,7 +50,7 @@ jobs: - name: Static HTML export with Next.js run: bun next export - name: Upload artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v3 with: path: ./${{ env.working-directory }}/out @@ -64,4 +64,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v4 From 6d3a2b6fe9125919a5555b27be841dd4cba69530 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Sat, 1 Feb 2025 07:50:18 +0100 Subject: [PATCH 048/150] cloudflare: fix package name (#65) --- pages/cloudflare/get-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index c35d63c..ad5fbf1 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -173,7 +173,7 @@ This includes: You can continue to run `next dev` when developing locally. Modify your Next.js configuration file to import and call the `initOpenNextCloudflareForDev` utility -from the `@cloudflare/next-on-pages` package. This makes sure that the Next.js dev server can optimally integrate with the open-next +from the `@opennextjs/cloudflare` package. This makes sure that the Next.js dev server can optimally integrate with the open-next cloudflare adapter and it is necessary for using bindings during local development. This is an example of a Next.js configuration file calling the utility: From a68951fc975ed6471d06a680ac57cc0f5b6af293 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Sat, 1 Feb 2025 08:36:25 +0100 Subject: [PATCH 049/150] Add HowTo NextAuth on cloudflare (#61) Co-authored-by: Dario Piotrowicz --- pages/cloudflare/_meta.json | 1 + pages/cloudflare/howtos/NextAuth.mdx | 31 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 pages/cloudflare/howtos/NextAuth.mdx diff --git a/pages/cloudflare/_meta.json b/pages/cloudflare/_meta.json index d0150a0..aff2153 100644 --- a/pages/cloudflare/_meta.json +++ b/pages/cloudflare/_meta.json @@ -3,6 +3,7 @@ "get-started": "", "bindings": "", "caching": "", + "howtos": "How-Tos", "examples": "", "community": "Community projects", "troubleshooting": "", diff --git a/pages/cloudflare/howtos/NextAuth.mdx b/pages/cloudflare/howtos/NextAuth.mdx new file mode 100644 index 0000000..7c7fa0f --- /dev/null +++ b/pages/cloudflare/howtos/NextAuth.mdx @@ -0,0 +1,31 @@ + +## [NextAuth.js](https://next-auth.js.org/) + +NextAuth.js is an open-source authentication solution for Next.js applications. + +### Solving a broken build + +NextAuth.js relies on [`createCipheriv`](https://nodejs.org/docs/v22.13.1/api/crypto.html#cryptocreatecipherivalgorithm-key-iv-options) from [`node:crypto`](https://nodejs.org/docs/v22.13.1/api/crypto.html). + +`createCipheriv` is not currently implemented by the workerd runtime so apps using NextAuth.js with the default configuration break at build time. + +However you can configure NextAuth.js to use custom implementations of the `encode` and `decode` functions that do not use the unimplemented Node APIs. Implementations built on top of [`SubtleCrypto`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) can run on workerd. + +The NextAuth.js configuration file should look like: + +```js +import { encode, decode } from "@/lib/webcrypto"; + +export const NEXT_AUTH_CONFIG = { + // ... + jwt: { + encode, + decode, + }, +}; +``` + +Kudos to Arnav Gupta ([`@arnavgupta00`](https://github.com/arnavgupta00)) for coming up with the solution. +You can find an example of this on his [example repository](https://github.com/arnavgupta00/deployment-cf-workers-prisma-nextauth). + +Related issues: [`workers-sdk#206`](https://github.com/opennextjs/opennextjs-cloudflare/issues/206) and [`workerd#3277`](https://github.com/cloudflare/workerd/issues/3277). From c7be49c6880bc75f37220a659705139bc525b5d4 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Wed, 5 Feb 2025 12:42:20 +0100 Subject: [PATCH 050/150] update cloudflare docs (#68) Co-authored-by: Alex Patterson --- pages/cloudflare/get-started.mdx | 14 +++++--------- pages/cloudflare/index.mdx | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index ad5fbf1..8f20c2c 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -128,16 +128,12 @@ The `NEXTJS_ENV` variable defines the environment to use when loading Next.js `. Add the following to the scripts field of your `package.json` file: ```json -"build:worker": "opennextjs-cloudflare", -"dev:worker": "wrangler dev --port 8771", -"preview": "npm run build:worker && npm run dev:worker", -"deploy": "npm run build:worker && wrangler deploy", +"preview": "opennextjs-cloudflare && wrangler dev", +"deploy": "opennextjs-cloudflare && wrangler deploy", "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts", ``` -- `npm run build:worker`: Runs the [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) adapter. This first builds your app by running the `build` script in your `package.json` (Next.js apps use `next build` by default), and then transforms the build output to a format that you can run locally using [Wrangler](https://developers.cloudflare.com/workers/wrangler/), and deploy to Cloudflare. The build command used by OpenNext can be overridden with the `buildCommand` option in your OpenNext config. -- `npm run dev:worker`: Takes the output generated by `build:worker` and runs it locally in [workerd](https://github.com/cloudflare/workerd), the open-source Workers Runtime, allowing you to run the app locally in the same environment that it will run in production. If you instead run `next dev`, your app will run in Node.js, which is a different JavaScript runtime from the Workers runtime, with differences in behavior and APIs. -- `npm run preview`: Runs `build:worker` and then `dev:worker`, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. +- `npm run preview`: Builds your app and serves it locally, allowing you to quickly preview your app running locally in the Workers runtime, via a single command. - `npm run deploy`: Builds your app, and then deploys it to Cloudflare - `cf-typegen`: Generates a `cloudflare-env.d.ts` file at the root of your project containing [the types for the `env`](https://developers.cloudflare.com/workers/wrangler/commands/#types). @@ -193,7 +189,7 @@ export default nextConfig; After having added the `initOpenNextCloudflareForDev()` call in your Next.js configuration file, you will be able, during local development, to access in any of your server code, local versions of Cloudflare bindings as indicated in the [bindings documentation](./bindings). -In step 3, we also added the `npm run preview:worker`, which allows you to quickly preview your app running locally in the Workers runtime, +In step 3, we also added the `npm run preview`, which allows you to quickly preview your app running locally in the Workers runtime, rather than in Node.js. This allows you to test changes in the same runtime as your app will run in when deployed to Cloudflare. ##### 12. Deploy to Cloudflare Workers @@ -201,7 +197,7 @@ rather than in Node.js. This allows you to test changes in the same runtime as y Either deploy via the command line: ```sh -npm run deploy:worker +npm run deploy ``` Or [connect a Github or Gitlab repository](https://developers.cloudflare.com/workers/ci-cd/), and Cloudflare will automatically build and deploy each pull request you merge to your production branch. diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 63644f8..e5c3a9c 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -52,8 +52,8 @@ We will update the list as we progress towards releasing 1.0. - [x] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) - [x] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) - [x] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) +- [x] [Pages Router](https://nextjs.org/docs/pages) - [ ] [Support for after](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) -- [ ] [Pages Router](https://nextjs.org/docs/pages) - [ ] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) - [ ] [Composable Caching](https://nextjs.org/blog/composable-caching) (`'use cache'`) is a Next.js 15 feature and not supported yet. From eb005a63c82b1b36af14f3c89a31b9760bb3fff5 Mon Sep 17 00:00:00 2001 From: James Anderson Date: Mon, 10 Feb 2025 15:05:31 +0000 Subject: [PATCH 051/150] rename kvCache to kv-cache (#70) --- pages/cloudflare/get-started.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/get-started.mdx b/pages/cloudflare/get-started.mdx index 8f20c2c..7252fd4 100644 --- a/pages/cloudflare/get-started.mdx +++ b/pages/cloudflare/get-started.mdx @@ -82,7 +82,7 @@ Add a [`open-next.config.ts`](https://opennext.js.org/aws/config) file to the ro ```ts import type { OpenNextConfig } from "@opennextjs/aws/types/open-next.js"; -import cache from "@opennextjs/cloudflare/kvCache"; +import cache from "@opennextjs/cloudflare/kv-cache"; const config: OpenNextConfig = { default: { From b9895550083a4890d7babf3dbb08166a79be093e Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Tue, 11 Feb 2025 12:31:36 +0100 Subject: [PATCH 052/150] cloudflare: clarify supported version (#73) --- pages/cloudflare/index.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index e5c3a9c..07d577f 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -35,7 +35,7 @@ This is an important difference from `@cloudflare/next-on-pages`, which only sup ### Supported Next.js versions -`@opennextjs/cloudflare` is pre 1.0, and still in active development. We intend to support all minor and patch versions of Next.js 14 and 15. +`@opennextjs/cloudflare` is pre 1.0, and still in active development. We intend to support all minor and patch versions of Next.js 15 and the latest minor of Next.js 14. To help improve compatibility, we encourage you to [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues) and contribute code! From f5312a47a7d0a45fac1782132ec39cf252b1e6a0 Mon Sep 17 00:00:00 2001 From: Victor Berchet Date: Tue, 11 Feb 2025 12:34:07 +0100 Subject: [PATCH 053/150] doc(cloudflare) add an HowTo for Stripe (#72) --- pages/cloudflare/howtos/_meta.json | 4 ++++ pages/cloudflare/howtos/stripeAPI.mdx | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 pages/cloudflare/howtos/_meta.json create mode 100644 pages/cloudflare/howtos/stripeAPI.mdx diff --git a/pages/cloudflare/howtos/_meta.json b/pages/cloudflare/howtos/_meta.json new file mode 100644 index 0000000..1676dce --- /dev/null +++ b/pages/cloudflare/howtos/_meta.json @@ -0,0 +1,4 @@ +{ + "NextAuth": "NextAuth", + "stripeAPI": "Stripe API" +} diff --git a/pages/cloudflare/howtos/stripeAPI.mdx b/pages/cloudflare/howtos/stripeAPI.mdx new file mode 100644 index 0000000..621cecf --- /dev/null +++ b/pages/cloudflare/howtos/stripeAPI.mdx @@ -0,0 +1,16 @@ + +## [Stripe API](https://www.npmjs.com/package/stripe) + +When [creating a Stripe object](https://docs.stripe.com/js/initializing), the default http client implementation is based on `node:https` which is not implemented on Workers. + +However you can use an http client based on fetch ([`FetchHttpClient`](https://github.com/stripe/stripe-node/blob/54d423e5d1118dc35c4b76260889826003e00e9f/src/net/FetchHttpClient.ts)) via the `httpClient` option: + +```ts +import Stripe from "stripe"; + +const stripe = Stripe(STRIPE_API_KEY, { + // Cloudflare Workers use the Fetch API for their API requests. + httpClient: Stripe.createFetchHttpClient() +}); +``` + From b4b3113265d4dba92c32f493dd14eb9ac5d4a3a2 Mon Sep 17 00:00:00 2001 From: James Anderson Date: Wed, 12 Feb 2025 14:48:16 +0000 Subject: [PATCH 054/150] update cloudflare docs for memory queue (#74) --- pages/cloudflare/caching.mdx | 37 ++++++++++++++++++++++++++++++------ pages/cloudflare/index.mdx | 2 +- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/pages/cloudflare/caching.mdx b/pages/cloudflare/caching.mdx index 93411f3..356af4f 100644 --- a/pages/cloudflare/caching.mdx +++ b/pages/cloudflare/caching.mdx @@ -9,8 +9,6 @@ By default, all `fetch()` subrequests made in your Next.js app are cached. Refer [The cache persists across deployments](https://nextjs.org/docs/app/building-your-application/caching#data-cache). You are responsible for revalidating/purging this cache. -Note that [Revalidating](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#revalidating-data) is not yet supported. - Next.js primes the cache at build time. The build time values are serverd by the [Workers Assets](https://developers.cloudflare.com/workers/static-assets/). @@ -19,17 +17,19 @@ Workers KV is eventually consistent, which means that it can take up to 60 secon ### How to enable caching -`@opennextjs/cloudflare` uses [Workers KV](https://developers.cloudflare.com/kv/) as the cache for your Next.js app. Workers KV is [fast](https://blog.cloudflare.com/faster-workers-kv) and uses Cloudflare's [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) to increase cache hit rates. When you write cached data to Workers KV, you write to storage that can be read by any Cloudflare location. This means your app can fetch data, cache it in KV, and then subsequent requests anywhere around the world can read from this cache. +`@opennextjs/cloudflare` supports multiple caching mechanisms through a project's OpenNext configuration. + +#### Incremental Static Regeneration (ISR) -To enable caching, you must: +The ISR adapter for Cloudflare uses [Workers KV](https://developers.cloudflare.com/kv/) as the cache for your Next.js app. Workers KV is [fast](https://blog.cloudflare.com/faster-workers-kv) and uses Cloudflare's [Tiered Cache](https://developers.cloudflare.com/cache/how-to/tiered-cache/) to increase cache hit rates. When you write cached data to Workers KV, you write to storage that can be read by any Cloudflare location. This means your app can fetch data, cache it in KV, and then subsequent requests anywhere around the world can read from this cache. Pricing information can be found in the Cloudflare [docs](https://developers.cloudflare.com/workers/platform/pricing/#workers-kv). -#### 1. Create a KV namespace +##### 1. Create a KV namespace ``` npx wrangler@latest kv namespace create ``` -#### 2. Add the KV namespace to your Worker +##### 2. Add the KV namespace to your Worker The binding name used in your app's worker is `NEXT_CACHE_WORKERS_KV`. @@ -45,3 +45,28 @@ The binding name used in your app's worker is `NEXT_CACHE_WORKERS_KV`. ] } ``` + +#### 3. Configure the cache + +In your project's OpenNext config, enable the KV cache and set up a queue. + +The memory queue will send revalidation requests to a page when needed, and offers support for de-duplicating requests on a per-isolate basis. There might still be duplicate requests under high traffic or across regions. + +```ts +// open-next.config.ts +import incrementalCache from "@opennextjs/cloudflare/kv-cache"; +import memoryQueue from "@opennextjs/cloudflare/memory-queue"; + +const config: OpenNextConfig = { + default: { + override: { + // ... + incrementalCache: () => incrementalCache, + queue: () => memoryQueue, + }, + }, + // ... +}; + +export default config; +``` diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 07d577f..8cdbca7 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -53,8 +53,8 @@ We will update the list as we progress towards releasing 1.0. - [x] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) - [x] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) - [x] [Pages Router](https://nextjs.org/docs/pages) +- [x] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) - [ ] [Support for after](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) -- [ ] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) - [ ] [Composable Caching](https://nextjs.org/blog/composable-caching) (`'use cache'`) is a Next.js 15 feature and not supported yet. We welcome both contributions and feedback! From ed16d3ede60206ea747e8c64fb04689825b82d10 Mon Sep 17 00:00:00 2001 From: sommeeeR <91796856+sommeeeer@users.noreply.github.com> Date: Mon, 24 Feb 2025 13:16:32 +0100 Subject: [PATCH 055/150] refactor: custom overrides (#77) --- pages/aws/config/custom_overrides.mdx | 153 ++++++++++++++++++++++++-- 1 file changed, 145 insertions(+), 8 deletions(-) diff --git a/pages/aws/config/custom_overrides.mdx b/pages/aws/config/custom_overrides.mdx index b873753..d255abb 100644 --- a/pages/aws/config/custom_overrides.mdx +++ b/pages/aws/config/custom_overrides.mdx @@ -13,7 +13,7 @@ to your `open-next.config.ts` to avoid the edge runtime to try to compile overri ## Custom converter -Sometimes you might want to modify the object received by OpenNext. For example `Config.YOUR_SECRET_KEY` from sst cannot be used in the middleware, so you might want to add it to the headers. This is where the custom converter comes in. You can add a custom converter to modify the object before it is passed to OpenNext. +Sometimes you might want to modify the object received by OpenNext. For example `Config.YOUR_SECRET_KEY` from SST cannot be used in the middleware, so you might want to add it to the headers. This is where the custom converter comes in. You can add a custom converter to modify the object before it is passed to OpenNext. You'll still have to use a fallback value during dev as this is not used by the dev server. @@ -276,19 +276,156 @@ const config = { ``` ## Custom Incremental cache -TODO -## Custom queue -TODO +You can take inspiration from our [`fs-dev`](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/incrementalCache/fs-dev.ts) override which uses the file system to store the incremental cache. You need an `open-next.config.ts` with this: + +```ts +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.ts'; +const config = { + default: { + override: { + // can be any of our included ones or your own custom override + incrementalCache: () => import('./customIncrementalCache').then((mod) => mod.default), + }, + }, +} satisfies OpenNextConfig; + +export default config; +``` + +[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/incrementalCache) ones are `'s3' | 's3-lite' | 'multi-tier-ddb-s3' | 'fs-dev' | 'dummy'` + +## Custom Queue + +By default it will use SQS queue to revalidate stale routes. You can read more about this [here](/aws/config/overrides/queue). To create your own custom override you can take inspiration by looking at our [included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/queue) implementations. You need an `open-next.config.ts` with this: + +```ts +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.ts'; +const config = { + default: { + override: { + // can be any of our included ones or your own custom override + queue: () => import('./customQueue').then((mod) => mod.default), + }, + }, +} satisfies OpenNextConfig; + +export default config; +``` + +[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/queue) ones are `'sqs' | 'sqs-lite' | 'direct' | 'dummy'` ## Custom Tag cache -TODO + +To override the tag cache you can take inspiration by looking at the [`fs-dev`](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/tagCache/fs-dev.ts) override that uses the filesystem. You can read more about this override [here](/aws/config/overrides/tag_cache). You need an `open-next.config.ts` with this: + +```ts +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.ts'; +const config = { + default: { + override: { + // can be any of our included ones or your own custom override + tagCache: () => import('./customTagCache').then((mod) => mod.default), + }, + }, +} satisfies OpenNextConfig; + +export default config; +``` + +[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/tagCache) ones are `'dynamodb' | 'dynamodb-lite' | 'fs-dev' | 'dummy'` ## Custom Origin Resolver -TODO + +This override is only used internally by OpenNext to resolve the origin of the request if you have an `external` middleware. You can take inspiration from looking at our included [`pattern-env`](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/originResolver/pattern-env.ts) override. You need an `open-next.config.ts` with this: + +```ts +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; +const config = { + default: {}, + middleware: { + // must be true for the originResolver to be used + external: true, + // can be any of our included ones or your own custom override + originResolver: () => import('./customOriginResolver').then((mod) => mod.default), + }, +} satisfies OpenNextConfig; + +export default config; +``` + +[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/originResolver) ones are `'pattern-env' | 'dummy'` ## Custom Image Loader -TODO + +This override is used in the image optimization server to load an image from a custom source. You can look at our implemention of using the file system [here](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/imageLoader/fs-dev.ts). You need an `open-next.config.ts` with this: + +```ts +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; +const config = { + default: {}, + imageOptimization: { + loader: () => import('./customImageLoader').then((mod) => mod.default), + }, +} satisfies OpenNextConfig; + +export default config; +``` + +[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/imageLoader) ones are `'s3' | 's3-lite' | 'host' | 'fs-dev' | 'dummy'` ## Custom Warmer Invoke -TODO \ No newline at end of file + +To have a custom override for the warmer invoke you can take inspiration by looking at our [`aws-lambda`](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/warmer/aws-lambda.ts) override. You need an `open-next.config.ts` with this: + +```ts +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; +const config = { + default: {}, + warmer: { + invokeFunction: () => import('./customWarmer').then((mod) => mod.default), + }, +} satisfies OpenNextConfig; + +export default config; +``` + +[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/warmer) ones are `'aws-lambda' | 'dummy'` + +## Custom CDN Invalidation + +To have a custom override for the CDN Invalidation you can take inspiration by looking at our [`cloudfront`](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/cdnInvalidation/cloudfront.ts) override. You need an `open-next.config.ts` with this: + +```ts +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; +const config = { + default: { + override: { + cdnInvalidation: () => import('./customCdnInvalidation').then((mod) => mod.default), + } + }, +} satisfies OpenNextConfig; + +export default config; +``` + +[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/cdnInvalidation) ones are `'cloudfront' | 'dummy'` + +## Custom External Request Proxy + +This is used by OpenNext to proxy rewritten requests to external services. You can read more about it [here](/aws/config/overrides/proxy_external_request). To have a custom override for the External Request Proxy you can take inspiration by looking at our [`fetch`](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/proxyExternalRequest/fetch.ts) override. You need an `open-next.config.ts` with this: + +```ts +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; +const config = { + default: { + override: { + proxyExternalRequest: () => import('./customProxyExternalRequest').then((mod) => mod.default), + } + }, +} satisfies OpenNextConfig; + +export default config; +``` + +[Included](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/proxyExternalRequest) ones are `'fetch' | 'node' | 'dummy'` From b77a1d024d603e72e1edb64991c8b23aad61c0e0 Mon Sep 17 00:00:00 2001 From: sommeeeR <91796856+sommeeeer@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:06:24 +0100 Subject: [PATCH 056/150] refactor: get started, config and simple example (#76) Co-authored-by: khuezy Co-authored-by: conico974 --- pages/aws/config.mdx | 2 +- pages/aws/config/simple_example.mdx | 20 ++++++-------------- pages/aws/get_started.mdx | 4 ++-- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/pages/aws/config.mdx b/pages/aws/config.mdx index 66863e7..f5cebda 100644 --- a/pages/aws/config.mdx +++ b/pages/aws/config.mdx @@ -28,7 +28,7 @@ If you want to look at a full example, you can check [the full example](/aws/con ### Opt out of default poweredByHeader -By default Next.js will add the [`x-powered-by`]((https://nextjs.org/docs/app/api-reference/next-config-js/poweredByHeader)) header. OpenNext will also add a header `x-opennext`. To opt-out of this, open `next.config.js` and disable the poweredByHeader property in the configuration: +By default Next.js will add the [`x-powered-by`](https://nextjs.org/docs/app/api-reference/config/next-config-js/poweredByHeader) header. OpenNext will also add a header `x-opennext`. To opt-out of this, open `next.config.js` and disable the poweredByHeader property in the configuration: ```ts module.exports = { poweredByHeader: false, diff --git a/pages/aws/config/simple_example.mdx b/pages/aws/config/simple_example.mdx index 6a3dbe0..77d3b0c 100644 --- a/pages/aws/config/simple_example.mdx +++ b/pages/aws/config/simple_example.mdx @@ -4,19 +4,7 @@ Here you can find the most common `open-next.config.ts` file examples that you c ## Streaming with lambda - - AWS has a bunch of different implementations of streaming in production. You - might be lucky and have a fully working one, but you might have one that are - not suitable for production. Be aware that there is nothing to do to prevent - AWS from breaking your deployment (same code and same runtime might break from - one day to another) [Thread - 1](https://discord.com/channels/983865673656705025/1230482660913184800) - [Thread - 2](https://discord.com/channels/983865673656705025/1249368592558985247)
{' '} -
On some AWS accounts the response can hang if the body is empty. There - is a workaround for that on OpenNext 3.0.3+, setting environment variable - `OPEN_NEXT_FORCE_NON_EMPTY_RESPONSE` to `"true"`. This will ensure that the - stream body is not empty.

+ If you have an issue with streaming send a message on [discord](https://discord.com/channels/1283128968140161065/1286094576788177059) and contact AWS support to let them know of the issue. @@ -34,6 +22,10 @@ const config = { export default config; ``` +Be aware that there has been some issues in the past with AWS breaking streaming from one day to another. This seems to be resolved now. +[Thread 1](https://discord.com/channels/983865673656705025/1230482660913184800) +[Thread 2](https://discord.com/channels/983865673656705025/1249368592558985247) + ## Splitting the server ```ts @@ -105,7 +97,7 @@ export default config; ## Bundle for a classic Node server (With function splitting) -This is not implemented in sst yet. You'll have to use your own IAC construct to deploy this. +This is not implemented in SST yet. You'll have to use your own IAC construct to deploy this. Be aware that this uses the exact same system for ISR/SSG as the default lambda setup. So it will have to have all the proper permissions and env variable to interact with S3, DynamoDB and SQS (Or whatever you override it with). You can see [here](/aws/inner_workings/components/server/node#special-overrides) for more details diff --git a/pages/aws/get_started.mdx b/pages/aws/get_started.mdx index 5c715ad..2aab40c 100644 --- a/pages/aws/get_started.mdx +++ b/pages/aws/get_started.mdx @@ -12,7 +12,7 @@ For more information, check out the SST docs: https://sst.dev/docs/start/aws/nex ### Other Frameworks -The OpenNext community has contributed deployment options for a few other frameworks. +The OpenNext community has contributed deployment options for a few other frameworks. Many of these are no longer maintained, so newer versions of OpenNext may not be supported. - CDK (TS): https://github.com/jetbridge/cdk-nextjs - CDK (TS, Java, Go, Py, .NET): https://github.com/datasprayio/open-next-cdk @@ -24,7 +24,7 @@ The OpenNext community has contributed deployment options for a few other framew To use these, you'll need to run the following inside your Next.js app. ```bash -$ npx open-next@latest build +$ npx @opennextjs/aws@latest build ``` If you are using OpenNext to deploy using a framework that is not listed here, please let us know so we can add it to the list. From 6d4b9c5819e8c1df653dc21296929a827198e8d4 Mon Sep 17 00:00:00 2001 From: sommeeeR <91796856+sommeeeer@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:11:59 +0100 Subject: [PATCH 057/150] refactor: full example, reference and nx (#78) Co-authored-by: conico974 --- pages/aws/config/full_example.mdx | 172 +++++++++++++++++++++--------- pages/aws/config/nx.mdx | 10 +- pages/aws/config/reference.mdx | 62 ++++++++--- 3 files changed, 173 insertions(+), 71 deletions(-) diff --git a/pages/aws/config/full_example.mdx b/pages/aws/config/full_example.mdx index 1415679..b99e963 100644 --- a/pages/aws/config/full_example.mdx +++ b/pages/aws/config/full_example.mdx @@ -1,24 +1,40 @@ -Here is a detailed example of an `open-next.config.ts` file: -This file need to be at the same place as your `next.config.js` file +Here is a detailed example of an `open-next.config.ts` file. This file need to be at the same place as your `next.config.js` file -`server` in here could refer to a lambda function, a docker container, a node server or whatever that can support running nodejs code. (Even cloudflare workers in the future) +`server` in here could refer to a lambda function, a docker container, a node server or whatever that can support running nodejs code. Even Cloudflare workers (require to use `@opennextjs/cloudflare`). -For more information about the options here, take a look at the [components section](/aws/components/overview). +For more information about the options here, take a look at the [reference section](/aws/config/reference). ```ts -import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js' +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { - default: { // This is the default server, similar to the server-function in open-next v2 + default: { + // This is the default server, similar to the server-function in open-next v2 // You don't have to provide the below, by default it will generate an output // for normal lambda as in open-next v2 override: { - wrapper: "aws-lambda-streaming", // This is necessary to enable lambda streaming + // This is necessary to enable lambda streaming, defaults to aws-lambda + wrapper: 'aws-lambda-streaming', + // Convert the input and output of the server, defaults to aws-apigw-v2 + converter: 'aws-apigw-v2', + // Used for fetch cache and html/rsc/json cache, defaults to s3 + incrementalCache: 's3', + // Used for external rewrites, defaults to node + proxyExternalRequest: 'node', + tagCache: 'dynamodb', // Used for revalidatePath and revalidateTag, defaults to dynamodb // You can override any part that is a `LazyLoadedOverride` this way - queue: () => Promise.resolve({ - send: async (message) => { - //Your custom code here - } - }) + queue: () => + Promise.resolve({ + send: async (message) => { + //Your custom code here + }, + }), + }, + // this will install sharp to your default server function + // only for example purposes, you most likely should not use this + // this can be used on every server to install additional packages + install: { + packages: ['sharp@0.33.5'], + arch: 'arm64', }, minify: true, // This will minify the output }, @@ -27,36 +43,44 @@ const config = { functions: { ssr: { routes: [ - "app/api/isr/route", "app/api/sse/route", "app/api/revalidateTag/route", // app dir Api routes - "app/route1/page", "app/route2/page", // app dir pages - "pages/route3" // page dir pages - ], // For app dir, you need to include route|page, no need to include layout or loading - patterns: ['api/*', 'route1', 'route2', 'route3'], // patterns needs to be in a cloudfront compatible format, this will be used to generate the output + 'app/api/isr/route', + 'app/api/sse/route', + 'app/api/revalidateTag/route', // app dir Api routes + 'app/route1/page', + 'app/route2/page', // app dir pages + 'pages/route3', // page dir pages + ], // For app dir, you need to include route|page, no need to include layout or loading + // patterns needs to be in a cloudfront compatible format + // this will be used to generate the output + patterns: ['api/*', 'route1', 'route2', 'route3'], override: { - wrapper: "aws-lambda-streaming", + wrapper: 'aws-lambda-streaming', }, // This enables the bundled next server which is faster and reduce the size of the server // This is also experimental and might not work in all cases - experimentalBundledNextServer: true + experimentalBundledNextServer: true, // deprecated and not supported in next 14.2+ }, pageSsr: { - routes: ["pages/pageSsr"], // For page dir routes should be in the form `pages/${route}` without the extension, it should match the filesystem + // For page dir routes should be in the form `pages/${route}` without the extension + // It should match the filesystem + routes: ['pages/pageSsr'], // BUILD_ID is a special case, it will be replaced with the actual build id - patterns: [ 'pageSsr', "_next/data/BUILD_ID/pageSsr.json"], + patterns: ['pageSsr', '_next/data/BUILD_ID/pageSsr.json'], override: { - wrapper: "node", - converter: "node", - // This is necessary to generate the dockerfile and for the implementation to know that it needs to deploy on docker + wrapper: 'node', + converter: 'node', + // This is necessary to generate the dockerfile and + // for the implementation to know that it needs to deploy on docker // You can also provide a string here which will be used to create the dockerfile generateDockerfile: true, }, }, edge: { - runtime: "edge", - routes: ["app/ssr/page"], - patterns: ["ssr"], - override: {} - } + runtime: 'edge', + routes: ['app/ssr/page'], + patterns: ['ssr'], + override: {}, + }, }, // By setting this, it will create another bundle for the middleware, // and the middleware will be deployed in a separate server. @@ -66,19 +90,48 @@ const config = { // This is not implemented in the reference construct implementation. // This is optional, but might be necessary if you split your app into multiple servers middleware: { - external: true - } - + external: true, + }, // Optional imageOptimization: { - // This is the architecture of the image, it could be x64 or arm64 + loader: "s3-lite", // Can be overridden with a LazyLoadedOverride // This is necessary to bundle the proper version of sharp - arch: "x64", - } - + // You can customize this to your needs + // By default it will install with these options: + install: { + packages: ['sharp@0.32.6'], + arch: 'arm64', + nodeVersion: '18', + libc: 'glibc', + }, + }, + // Initialization function is a special server that will run at build time to initialize the cache. + // By default, it only initializes the tag cache. Besides the common options, you can use the following options: + initializationFunction: { + tagCache: 'dynamodb-lite', // Can be overridden with a LazyLoadedOverride + }, + // Override the default revalidate function + // By default, works for lambda and on SQS event. + // Supports only node runtime + revalidate: { + override: { + wrapper: 'aws-lambda', // Can be overridden with a LazyLoadedOverride + converter: 'aws-apigw-v2', // Can be overridden with a LazyLoadedOverride + }, + }, + // Override the default warmer + // By default, works for lambda only. + // If you override this, you'll need to handle the warmer event in the wrapper + warmer: { + invokeFunction: 'aws-lambda', // Can be overridden with a LazyLoadedOverride + override: { + wrapper: 'aws-lambda', // Can be overridden with a LazyLoadedOverride + converter: 'aws-apigw-v2', // Can be overridden with a LazyLoadedOverride + }, + }, // If you want to override the default build command, you can do it here // By default it uses `npm run build` - buildCommand: "echo 'hello world'", + buildCommand: "echo 'skipping build'", dangerous: { // This will disable the tag cache @@ -87,19 +140,38 @@ const config = { // This will disable the incremental cache // This is generally not recommended, as this is necessary for ISR AND SSG routes as well as the fetch cache disableIncrementalCache: true, - } - - //The path to the target folder of build output from the `buildCommand` option (the path which will contain the `.next` and `.open-next` folders). This path is relative from the current process.cwd() - Optional default to "." - buildOutputPath: "build", - - //The path to the root of the Next.js app's source code. This path is relative from the current process.cwd(). - Optional default to "." - appPath: "app", - - //The path to the package.json file of the Next.js app. This path is relative from the current process.cwd(). - Optional - packageJsonPath: "package.json", - -} satisfies OpenNextConfig + // Enable the cache interception. Every request will go through the cache interceptor, if it is found in the cache, + // it will be returned without going through NextServer. Not every feature is covered by the cache interceptor and + // it should fallback to the NextServer if the cache is not found. + enableCacheInterception: true, + // Function to determine which headers or cookies takes precedence. + // By default, the middleware headers and cookies will override the handler headers and cookies. + // This is executed for every request and after next config headers and middleware has executed. + // Here is a very simple example of how you can use it: + headersAndCookiesPriority: (event) => { + if (event.rawPath.startsWith('/api')) { + return 'middleware'; + } + return 'handler'; + }, + }, + // The path to the target folder of build output from the `buildCommand` option + // (the path which will contain the `.next` and `.open-next` folders). + // This path is relative from the current process.cwd() - Optional defaults to "." + buildOutputPath: 'build', + // The path to the root of the Next.js app's source code. + // This path is relative from the current process.cwd(). - Optional defaults to "." + appPath: 'app', + // The path to the package.json file of the Next.js app. + // This path is relative from the current process.cwd(). - Optional + packageJsonPath: 'package.json', + // Advanced usage + // If you use the edge runtime somewhere (either with an external middleware or in the functions), we compile 2 versions of the open-next.config.ts file. + // One for the node runtime and one for the edge runtime. + // This option allows you to specify the externals for the edge runtime used in esbuild for the compilation of open-next.config.ts + // It is especially useful if you use some custom overrides only in node + edgeExternals: [], +} satisfies OpenNextConfig; export default config; -export type Config = typeof config ``` \ No newline at end of file diff --git a/pages/aws/config/nx.mdx b/pages/aws/config/nx.mdx index 0493b2a..e9334a8 100644 --- a/pages/aws/config/nx.mdx +++ b/pages/aws/config/nx.mdx @@ -1,7 +1,7 @@ # Configuring OpenNext for use in an Nx Monorepo. -Here's a detailed exampled of how to add open-next + SST to an existing Nx workspace, with an existing NextJS application sitting at `apps/next-site` +Here's a detailed exampled of how to add OpenNext + SST to an existing Nx workspace, with an existing NextJS application sitting at `apps/next-site` -1. install `open-next`: `pnpm add —save-dev open-next` +1. install `open-next`: `pnpm add —save-dev @opennextjs/aws` 2. Update your `apps/next-site/next.config.js` add `output: ‘standalone’`, and you want to add `experimental.outputFileTracingRoot`, it should look a little like this: ```javascript @@ -35,9 +35,9 @@ const plugins = [ module.exports = composePlugins(...plugins)(nextConfig); ``` -3. Create `open-next.config.js` inside your apps root directory, it should look a little something like this: +3. Create `open-next.config.ts` inside your apps root directory, it should look a little something like this: ```javascript -import type { OpenNextConfig } from '@opennextjs/aws/types/open-next.js'; +import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; const config = { default: {}, @@ -122,7 +122,7 @@ now, when you run `nx open-next-build next-site`, nx will automatically build th Now, we have a built app, ready to deploy, so how do we get it onto SST/AWS ? Good question! -We are using `sst ion` in this example. i will assume you have already have the cli installed, (if not, check here on how!)[https://ion.sst.dev/], +We are using `sst ion` in this example. i will assume you have already have the cli installed, [if not, check here on how](https://sst.dev), but we will not use the SST cli to init this project, because it wants to add a package.json to your next app, and it will look like it's working, but you will end up with a big far server error (all because the package.json overrides whatever nx _thinks_ there should be, and it will miss a bunch of dependencies). we will instead manually set this up: - let's add the sst package with `pnpm add sst@ion`, and the required packages for SST to work with AWS `pnpm add --save-dev aws-cdk-lib constructs @types/aws-lambda` diff --git a/pages/aws/config/reference.mdx b/pages/aws/config/reference.mdx index ce2cc89..99e20da 100644 --- a/pages/aws/config/reference.mdx +++ b/pages/aws/config/reference.mdx @@ -1,6 +1,8 @@ Every option that you can use in `open-next.config.ts` will be listed here. This is the configuration file that you can use to customize the build. You can look at the [full example](full_example) to see how you can use these options. +
+ import { Tabs } from 'nextra/components' @@ -24,7 +26,7 @@ import { Tabs } from 'nextra/components' ### `minify` - This will try to minify the output of the server including node_modules. It is a boolean and by default, it is set to `false`. + This will try to minify the output of the server including `node_modules`. It is a boolean and by default, it is set to `false`. It could lead to some issues with some packages, so it is recommended to test your app with this option before deploying it. We will likely not fix issues related to this option, as it is usually library specific. @@ -32,18 +34,14 @@ import { Tabs } from 'nextra/components' ### `override` This is where you will be able to override some part of the server. For all of them you can provide what we call a `LazyLoadedOverride` which is a function that will return the override. For some example look at some [Custom overrides](custom_overrides). - All servers have some default override that you can override - - TODO: Add all the types for the custom LazyLoadedOverride here. In the meantime, just look at the [source file](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/types/open-next.ts) - - --- + All servers have some default override that you can override. You can look at the types [here](https://github.com/opennextjs/opennextjs-aws/blob/5b314b13b2907a4510e7f0cca6959f8da4eab310/packages/open-next/src/types/overrides.ts). #### [`wrapper`](overrides/wrapper) This is the entrypoint of the server. Be aware that it might not be enough to change this to make it work on said platform. This is only the entrypoint, you might need to change other parts of the server to make it work on the platform. - Possible values are: `aws-lambda`, `aws-lambda-streaming`, `node`, `cloudflare`, `dummy` or a `LazyLoadedOverride` that will return the wrapper. + Possible values are: `aws-lambda`, `aws-lambda-streaming`, `cloudflare-edge`, `cloudflare-node`, `node`, `express-dev`, `dummy` or a `LazyLoadedOverride` that will return the wrapper. #### [`converter`](overrides/converter) @@ -53,7 +51,7 @@ import { Tabs } from 'nextra/components' #### `install` - Install options for the server. This is used to install additional packages to this server + Install options for the server. This is used to install additional packages. It is an object with the options below. For image optimization, it will install sharp by default @@ -68,7 +66,35 @@ import { Tabs } from 'nextra/components' Possible values are: `x64`, `arm64` - TODO: Add the other options and explain how to install packages on the default or splitted server functions + ##### `nodeVersion` + + This option will be passed to the postinstall script of sharp. It is used by `node-gyp`. + + ##### `libc` + + Override libc of native modules to install. + + Possible values are: `glibc`, `musl` + + ##### `additionalArgs` + + Additional arguments to pass to the install command (npm install). It is a string that will get appended to the `npm install` command. + + Here is an example of how to install sharp on your default server function with ARM64 architecture: + ```ts + import type { OpenNextConfig } from '@opennextjs/aws/types/open-next'; + const config = { + default: { + install: { + packages: ['sharp@0.33.5'], + arch: 'arm64', + }, + }, + } satisfies OpenNextConfig; + + export default config; + ``` +
@@ -103,13 +129,13 @@ import { Tabs } from 'nextra/components' Add possibility to override the default s3 cache. Used for fetch cache and html/rsc/json cache. - Possible values are: `s3`, `s3-lite`, `dummy` or a `LazyLoadedOverride` that will return the incremental cache. + Possible values are: `s3`, `s3-lite`, `multi-tier-ddb-s3`, `fs-dev`, `dummy` or a `LazyLoadedOverride` that will return the incremental cache. #### [`tagCache`](overrides/tag_cache) Add possibility to override the default tag cache. Used for revalidateTags and revalidatePath. - Possible values are: `dynamodb`, `dynamodb-lite`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. + Possible values are: `dynamodb`, `dynamodb-lite`, `fs-dev`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. #### [`queue`](overrides/queue) @@ -122,6 +148,12 @@ import { Tabs } from 'nextra/components' Add possibility to override the default proxy for external request (i.e. next config external rewrites or middleware rewrites). Used in the external middleware or one of the server function. Possible values are: `node`, `fetch`, `dummy` or a `LazyLoadedOverride` that will return the proxy. Default is `node` + + #### [`cdnInvalidation`](overrides/automatic_cdn_invalidation) + + Add possibility to override the CDN invalidation override. Used for on-demand invalidation with `revalidatePath()`, `revalidateTag()` and `res.revalidate()`. + + Possible values are: `cloudfront`, `dummy` or a `LazyLoadedOverride` that will return the invalidatePaths. This override is disabled by default. Every splitted server will have the same options as the default server. In addition to that, you can use the following options: @@ -173,7 +205,7 @@ import { Tabs } from 'nextra/components' ### [`loader`](overrides/image_loader) The image loader is used to load the image from the source. - Possible values are: `s3`, `host`, `dummy` or a `LazyLoadedOverride` that will return the loader. + Possible values are: `s3`, `s3-lite`, `host`, `fs-dev`, `dummy` or a `LazyLoadedOverride` that will return the loader. Revalidate doesn't have any specific options. It only uses the common options. @@ -195,7 +227,7 @@ import { Tabs } from 'nextra/components' Add possibility to override the default tag cache used for the initialization function. - Possible values are: `dynamodb`, `dynamodb-lite`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. + Possible values are: `dynamodb`, `dynamodb-lite`, `fs-dev`, `dummy` or a `LazyLoadedOverride` that will return the tag cache. @@ -239,14 +271,12 @@ It is also the place where you could find some experimental features. --- - #### `disableTagCache` This will disable the tag cache. You can disable it safely if you only use page router. It is used for `revalidateTag` and `revalidatePath`. It's a boolean and by default, it is set to `false`. - #### `disableIncrementalCache` This will disable the incremental cache. It is generally not recommended, as this is necessary for ISR **AND** SSG routes as well as the fetch cache. @@ -254,7 +284,7 @@ It's a boolean and by default, it is set to `false`. #### `enableCacheInterception` - Experimental -This will enable cache interception. It will allow you to intercept the cache system directly inside OpenNext routing layer and serve the page directly from the cache without going through `NextServer`. +This will enable cache interception. It will allow you to intercept the cache system directly inside OpenNext routing layer and serve the page directly from the cache without going through `NextServer`. If the cache interception fail, the request will be forwarded to the `NextServer` as usual. From 75c3b3c76aaa679723af8aabfc1342ef00896580 Mon Sep 17 00:00:00 2001 From: sommeeeR <91796856+sommeeeer@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:18:44 +0100 Subject: [PATCH 058/150] refactor: overrides (#79) Co-authored-by: conico974 --- .../overrides/automatic_cdn_invalidation.mdx | 2 +- pages/aws/config/overrides/converter.mdx | 32 ++++++++++++++++++- pages/aws/config/overrides/image_loader.mdx | 9 ++++++ .../overrides/proxy_external_request.mdx | 16 +++++++++- pages/aws/config/overrides/queue.mdx | 6 ++-- pages/aws/config/overrides/tag_cache.mdx | 8 +++-- pages/aws/config/overrides/wrapper.mdx | 2 +- 7 files changed, 66 insertions(+), 9 deletions(-) diff --git a/pages/aws/config/overrides/automatic_cdn_invalidation.mdx b/pages/aws/config/overrides/automatic_cdn_invalidation.mdx index 268c8dc..dc08370 100644 --- a/pages/aws/config/overrides/automatic_cdn_invalidation.mdx +++ b/pages/aws/config/overrides/automatic_cdn_invalidation.mdx @@ -2,7 +2,7 @@ import {Callout} from 'nextra/components' Available since `@opennextjs/aws` 3.4.0 -This override is used by OpenNext when routes have been On-Demand revalidated and the CDN needs to be updated. It is not called for ISR revalidation. +Not enabled by default. This override is used by OpenNext when routes have been On-Demand revalidated and the CDN needs to be updated. It is not called for ISR revalidation. It will be called for `revalidatePath`, `revalidateTag` and `res.revalidate()`. If you want to better understand how to implement your own Automatic CDN Invalidation, the easiest way would be to take a look at the existing [included Automatic CDN Invalidation](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/cdnInvalidation) diff --git a/pages/aws/config/overrides/converter.mdx b/pages/aws/config/overrides/converter.mdx index 8f1785f..b8e5d77 100644 --- a/pages/aws/config/overrides/converter.mdx +++ b/pages/aws/config/overrides/converter.mdx @@ -6,4 +6,34 @@ Couple of things to note : - If you use a `StreamCreator` in your wrapper, you probably don't need to do anything in the `convertTo` function. - If used for the default, the image optimization, or one of the splitted server the internal types will be `InternalEvent` and `InternalResult` respectively. - If used for the external middleware, the internal types will be `InternalEvent` and `InternalResult | MiddlewareResult` respectively. -- For the other servers, look up their respective types in the codebase. \ No newline at end of file +- For the other servers, look up their respective types in the codebase. + +## Included Converters + +### aws-apigw-v2 + +The `aws-apigw-v2` Converter is the default convert for AWS. It is used by default if you don't provide any Converter in your configuration. + +### aws-apigw-v1 + +The `aws-apigw-v1` Converter is a converter that allows you to convert request and response from Amazon API Gateway v1. + +### aws-cloudfront + +The `aws-cloudfront` Converter is a converter for Cloudfront (i.e. lambda@edge) + +### edge + +The `edge` Converter is the converter for everything that uses `Request` and `Response`. At the moment with the builtin one that's only Cloudflare. + +### converter + +The `node` Converter is a converter for classic Node.js server. + +### sqs-revalidate + +The `sqs-revalidate` Converter is a converter for the Revalidation server. It uses SQS Queue to handle the revalidation. + +### dummy + +The `dummy` Converter is a dummy implementation that will just forward the request and response as is. \ No newline at end of file diff --git a/pages/aws/config/overrides/image_loader.mdx b/pages/aws/config/overrides/image_loader.mdx index 2520cdf..06256a1 100644 --- a/pages/aws/config/overrides/image_loader.mdx +++ b/pages/aws/config/overrides/image_loader.mdx @@ -15,6 +15,15 @@ It uses the `@aws-sdk/client-s3` to interact with S3. - You need to provide the `BUCKET_KEY_PREFIX`, `BUCKET_NAME` environment variables to your server. +### s3-lite + +The `s3-lite` ImageLoader will load images from an S3 bucket. It uses the `aws4fetch` to interact with S3. + +##### Requirements + +- You need to provide the `BUCKET_KEY_PREFIX`, `BUCKET_NAME` environment variables to your server. +- Can also provide `BUCKET_REGION`. It fallbacks to `AWS_REGION` ?? `AWS_DEFAULT_REGION`. This should be set by AWS automatically. You can read more about how this works on AWS Lambdas [here](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime). + ### host The Host ImageLoader will load images from the host. diff --git a/pages/aws/config/overrides/proxy_external_request.mdx b/pages/aws/config/overrides/proxy_external_request.mdx index f9e3a16..641cb38 100644 --- a/pages/aws/config/overrides/proxy_external_request.mdx +++ b/pages/aws/config/overrides/proxy_external_request.mdx @@ -1,3 +1,17 @@ This override is used by OpenNext to proxy rewritten requests to external services. It is used either in the `external` middleware (if set) or in the default/splitted server if the middleware is bundled. -If you want to better understand how to implement your own ProxyExternalRequest, the easiest way would be to take a look at the existing [included ProxyExternalRequest](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/proxyExternalRequest). \ No newline at end of file +If you want to better understand how to implement your own ProxyExternalRequest, the easiest way would be to take a look at the existing [included ProxyExternalRequest](https://github.com/opennextjs/opennextjs-aws/tree/main/packages/open-next/src/overrides/proxyExternalRequest). + +## Included Proxy External Request + +### node + +This uses node-proxy to proxy the request to the external service. + +### fetch + +This uses fetch to proxy the request to the external service. It doesn't work in Node.js + +### dummy + +This is a dummy implementation that throws a FatalError. \ No newline at end of file diff --git a/pages/aws/config/overrides/queue.mdx b/pages/aws/config/overrides/queue.mdx index c081ca3..de99266 100644 --- a/pages/aws/config/overrides/queue.mdx +++ b/pages/aws/config/overrides/queue.mdx @@ -7,7 +7,7 @@ If you want to better understand how to implement your own Queue, the easiest wa Couple of things to note : - The default implementation use an SQS queue. This has the main advantage of being able to control the concurrency of the revalidations as well as avoiding trigerring the revalidation multiple times for the same route. -- You don't have to use a queue at all. You could trigger the revalidation directly in the Queue override itself. You can see a very simple implementation of this [in the `queue` override](/aws/contribute/local_run#devqueuets). +- You don't have to use a queue at all. You could trigger the revalidation directly in the Queue override itself. You can see a very simple implementation of this [in the `direct` override](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/queue/direct.ts). ## Included Queue @@ -18,7 +18,7 @@ It uses the `@aws-sdk/client-sqs` to interact with SQS. #### Requirements -- You need to provide the `QUEUE_URL` environment variable to your server. +- You need to provide the `REVALIDATION_QUEUE_URL` environment variable to your server. ### sqs-lite @@ -27,7 +27,7 @@ This implementation is a lighter version of the `sqs` Queue as it uses `aws4fetc #### Requirements -- You need to provide the `QUEUE_URL`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment variables to your server. +- You need to provide the `REVALIDATION_QUEUE_URL`, `REVALIDATION_QUEUE_REGION`(will fallback to `us-east-1`), `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment variables to your server. ### direct diff --git a/pages/aws/config/overrides/tag_cache.mdx b/pages/aws/config/overrides/tag_cache.mdx index 47575dd..a5f78e9 100644 --- a/pages/aws/config/overrides/tag_cache.mdx +++ b/pages/aws/config/overrides/tag_cache.mdx @@ -1,7 +1,7 @@ This override is used by the [`cache` adapter](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/adapters/cache.ts) that is provided by OpenNext to the NextServer. It is also used by OpenNext if `enableCacheInterception` is set to `true` in the configuration and by the `initializationFunction` for prepopulating the cache. It is used for the cache tags (i.e. `revalidateTag` and `revalidatePath`). It does not handle anything related to the ISR/SSG cache or the fetch cache used by Next.js. -It's main role is to detremine if a path is stale based on the tags and also to update the tag cache when `revalidateTag` is called. +It's main role is to determine if a path is stale based on the tags and also to update the tag cache when `revalidateTag` is called. The current implementation differs from the way Next.js standalone handle cache tags. In the standalone version, the cache tags are stored in a file, and every time a cache entry is accessed, it has to check for every tags if the entry is stale. This approach is very read heavy and doesn't work well with DB like DynamoDB. We choose to go another way. We store tags for every path that exists in the cache. This way, we can easily know if a path is stale by just checking the path instead of every tags used. This approach is more write heavy but it's a tradeoff we are willing to make. @@ -33,10 +33,14 @@ This implementation is a lighter version of the `dynamodb` TagCache as it uses ` - You need to provide the `CACHE_DYNAMO_TABLE`, `CACHE_BUCKET_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` environment variables to your server. - DynamoDB table should have a primary key `path` of type `String` and a sort key `tag` of type `String`. (It can reuse the same table as the one used by the default `tagCache`) +### dynamodb-nextMode + +TBA + ### dummy The Dummy TagCache is a dummy implementation that will throw an exception. It should not be used unless you want to disable cache tags. ### fs-dev -The FsDev TagCache is a simple implementation that stores the cache tags in a file in the `.open-next/cache` folder and interact with it using the filesystem. It is useful for development purposes only. \ No newline at end of file +The FsDev TagCache is a simple implementation that stores the cache tags in a file in the `.open-next/cache` folder and interact with it using the filesystem. It is useful for development purposes only. diff --git a/pages/aws/config/overrides/wrapper.mdx b/pages/aws/config/overrides/wrapper.mdx index 3d81b00..6fbd086 100644 --- a/pages/aws/config/overrides/wrapper.mdx +++ b/pages/aws/config/overrides/wrapper.mdx @@ -6,7 +6,7 @@ Couple of things to note : - If you want to use streaming (for the `node` runtime of next), you'll need to create a `StreamCreator` and pass it to the `handler`. You can find some example in the [node](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/wrappers/node.ts) or [aws-lambda-streaming](https://github.com/opennextjs/opennextjs-aws/blob/main/packages/open-next/src/overrides/wrappers/aws-lambda-streaming.ts) wrapper. - If you don't use streaming (like in the default `aws-lambda` wrapper), you may still need to provide a fake `StreamCreator` to the `handler` to avoid a weird issue with Node itself (see [here](https://github.com/opennextjs/opennextjs-aws/blob/f685ddea8f8a5c82591dc02713aff7138f2d9896/packages/open-next/src/overrides/wrappers/aws-lambda.ts#L49-L65) for an example and a more thorough explanation). - If you use the `edge` runtime of Next (either for the external middleware or for an `edge` route or page), you don't need the `StreamCreator` at all. -- If you are in a serverless environment and it supports `waitUntil`, you should define it here(see [here](https://github.com/opennextjs/opennextjs-aws/blob/f685ddea8f8a5c82591dc02713aff7138f2d9896/packages/open-next/src/overrides/wrappers/cloudflare.ts#L29)). This might not be necessary depending on where you run it (for example the `aws-lambda-streaming` or the `node` wrapper doesn't need it.) +- If you are in a serverless environment and it supports `waitUntil`, you should define it here(see [here](https://github.com/opennextjs/opennextjs-aws/blob/b0b1f7776b41612d2638a33e3c9ced8c42afab0a/packages/open-next/src/overrides/wrappers/cloudflare-node.ts#L80). This might not be necessary depending on where you run it (for example the `aws-lambda-streaming` or the `node` wrapper doesn't need it.) ## Included Wrappers From 5284312da00fb22f54f364b12bcb18f57a5a57bf Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Mon, 24 Feb 2025 13:46:15 +0000 Subject: [PATCH 059/150] add callout about `getCloudflareContext` in "async mode" (#75) --- pages/cloudflare/bindings.mdx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pages/cloudflare/bindings.mdx b/pages/cloudflare/bindings.mdx index 48dbbfe..b13fbcf 100644 --- a/pages/cloudflare/bindings.mdx +++ b/pages/cloudflare/bindings.mdx @@ -27,6 +27,17 @@ export async function GET(request) { } ``` + + `getCloudflareContext` can only be used in SSG routes in "async mode" (making it return a promise), to run the function in such a way simply provide an options argument with `async` set to `true`: + ```js + const context = await getCloudflareContext({ async: true }); + ``` + + **WARNING**: During SSG caution is advised since secrets (stored in `.dev.vars` files) and local development + values from bindings (like values saved in a local KV) will be used for the pages static generation. + + + #### How to add bindings to your Worker Add bindings to your Worker by adding them to your [wrangler configuration file](https://developers.cloudflare.com/workers/wrangler/configuration/). From 656a332e3230577fdeb377b57b4739fda13384d8 Mon Sep 17 00:00:00 2001 From: James Anderson Date: Tue, 25 Feb 2025 20:40:13 +0000 Subject: [PATCH 060/150] cloudflare: update ISR support (#66) --- pages/cloudflare/caching.mdx | 89 ++++++++++++++++++++++++++++++++++-- pages/cloudflare/index.mdx | 4 +- 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/pages/cloudflare/caching.mdx b/pages/cloudflare/caching.mdx index 356af4f..759cc3b 100644 --- a/pages/cloudflare/caching.mdx +++ b/pages/cloudflare/caching.mdx @@ -40,9 +40,9 @@ The binding name used in your app's worker is `NEXT_CACHE_WORKERS_KV`. "kv_namespaces": [ { "binding": "NEXT_CACHE_WORKERS_KV", - "id": "" - } - ] + "id": "", + }, + ], } ``` @@ -70,3 +70,86 @@ const config: OpenNextConfig = { export default config; ``` + + + + The `direct` mode for the queue is intended for debugging purposes and is not recommended for use in production. We are actively working on a solution that will be suitable for production. + + +#### On-Demand Revalidation + +The tag revalidation mechanism uses a [Cloudflare D1](https://developers.cloudflare.com/d1/) database as its backing store for information about tags, paths, and revalidation times. + +To use on-demand revalidation, you should also follow the [ISR setup steps](#incremental-static-regeneration-isr). + + + If your app **only** uses the pages router, it does not need to have a tag cache and should skip this step. + + +##### 1. Create a D1 database + +The binding name used in your app's worker is `NEXT_CACHE_D1`. + +```jsonc +// wrangler.json +{ + // ... + "d1_databases": [ + { + "binding": "NEXT_CACHE_D1", + "database_id": "", + "database_name": "", + }, + ], +} +``` + +##### 2. Create tables for tag revalidations + +The D1 tag cache requires two tables; one that keeps a record of the tag/path mappings, and another that tracks revalidation times. + +For the tag mappings, the default table name is `tags`, and can be configured by setting the `NEXT_CACHE_D1_TAGS_TABLE` environment variable to a string. + +For the revalidation times, the default table name is `revalidations` and can be configured by setting the `NEXT_CACHE_D1_REVALIDATIONS_TABLE` environment variable to a string. + +Wrangler can be used to create a table with it's [execute](https://developers.cloudflare.com/d1/wrangler-commands/#d1-execute) option. Ensure that you create a table for both your local dev database and your remote database. + +```sh +wrangler d1 execute NEXT_CACHE_D1 --command "CREATE TABLE IF NOT EXISTS tags (tag TEXT NOT NULL, path TEXT NOT NULL, UNIQUE(tag, path) ON CONFLICT REPLACE)" +wrangler d1 execute NEXT_CACHE_D1 --command "CREATE TABLE IF NOT EXISTS revalidations (tag TEXT NOT NULL, revalidatedAt INTEGER NOT NULL, UNIQUE(tag) ON CONFLICT REPLACE)" +``` + +##### 3. Configure the cache + +In your project's OpenNext config, enable the KV cache and set up a queue. The queue will send a revalidation request to a page when needed, but it will not dedupe requests. + +```ts +// open-next.config.ts +import tagCache from "@opennextjs/cloudflare/d1-tag-cache"; +import incrementalCache from "@opennextjs/cloudflare/kv-cache"; +import memoryQueue from "@opennextjs/cloudflare/memory-queue"; + +const config: OpenNextConfig = { + default: { + override: { + // ... + incrementalCache: () => incrementalCache, + queue: () => memoryQueue, + tagCache: () => tagCache, + }, + }, + // ... +}; +``` + +##### 4. Initialise the cache during deployments + +In order for the cache to be properly initialised with the build-time revalidation data, you need to setup a command that runs as part of your deploy step. + +OpenNext will generate an SQL file during the build that can be used to setup your D1 database. + +```sh +wrangler d1 execute NEXT_CACHE_D1 --file .open-next/cloudflare/cache-assets-manifest.sql +``` + +This should be run as part of each deployment to ensure that the cache is being populated with each build's initial revalidation data. diff --git a/pages/cloudflare/index.mdx b/pages/cloudflare/index.mdx index 8cdbca7..85993f7 100644 --- a/pages/cloudflare/index.mdx +++ b/pages/cloudflare/index.mdx @@ -53,10 +53,12 @@ We will update the list as we progress towards releasing 1.0. - [x] [Image optimization](https://nextjs.org/docs/app/building-your-application/optimizing/images) (you can integrate Cloudflare Images with Next.js by following [this guide](https://developers.cloudflare.com/images/transform-images/integrate-with-frameworks/)) - [x] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering) - [x] [Pages Router](https://nextjs.org/docs/pages) -- [x] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) +- [x] [Incremental Static Regeneration (ISR)](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration) 1 - [ ] [Support for after](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental) - [ ] [Composable Caching](https://nextjs.org/blog/composable-caching) (`'use cache'`) is a Next.js 15 feature and not supported yet. +1 Only the `direct` mode is supported at the moment, and is not suitable for production. + We welcome both contributions and feedback! ### Windows support From 814f261f4754203d99d3129498e2583a0d6c936a Mon Sep 17 00:00:00 2001 From: Philippe Serhal Date: Wed, 26 Feb 2025 02:54:28 -0500 Subject: [PATCH 061/150] chore: add team ownership via CODEOWNERS (#81) --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..2d74fd8 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +/pages/aws/* @opennextjs/aws +/pages/cloudflare/* @opennextjs/cloudflare @james-elicx +/pages/netlify/* @opennextjs/netlify-frameworks-and-build From 241f3326baa6a83fa634e776dcc7f25cd01ae73c Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Wed, 26 Feb 2025 10:33:08 +0000 Subject: [PATCH 062/150] update Cloudflare docs to include 0.5 (#80) --- pages/cloudflare/_meta.json | 3 ++- pages/cloudflare/migrate-from-0.3-to-0.4.mdx | 4 ++-- pages/cloudflare/migrate-from-0.4-to-0.5.mdx | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 pages/cloudflare/migrate-from-0.4-to-0.5.mdx diff --git a/pages/cloudflare/_meta.json b/pages/cloudflare/_meta.json index aff2153..e0d3688 100644 --- a/pages/cloudflare/_meta.json +++ b/pages/cloudflare/_meta.json @@ -7,7 +7,8 @@ "examples": "", "community": "Community projects", "troubleshooting": "", - "migrate-from-0.3-to-0.4": "Migrate from 0.3", + "migrate-from-0.4-to-0.5": "Migrate from 0.4", + "migrate-from-0.3-to-0.4": "", "0.3": "Release 0.3", "migrate-from-0.2-to-0.3": "", "0.2": "Release 0.2" diff --git a/pages/cloudflare/migrate-from-0.3-to-0.4.mdx b/pages/cloudflare/migrate-from-0.3-to-0.4.mdx index 81c9df5..00c78f8 100644 --- a/pages/cloudflare/migrate-from-0.3-to-0.4.mdx +++ b/pages/cloudflare/migrate-from-0.3-to-0.4.mdx @@ -1,9 +1,9 @@ import { SITE } from '../../config'; import { Callout } from 'nextra/components'; -### Migrate from 0.3 (to 0.4) +### Migrate from 0.3 to 0.4 -The `@opennextjs/cloudflare@0.4.0` introduced a new `initOpenNextCloudflareForDev` utility and made `getCloudflareContext` synchronous, +`@opennextjs/cloudflare@0.4.0` introduced a new `initOpenNextCloudflareForDev` utility and made `getCloudflareContext` synchronous, we'll explore those two differences below, and how they effect applications built using `0.3.x` versions of the adapter. ##### `initOpenNextCloudflareForDev` diff --git a/pages/cloudflare/migrate-from-0.4-to-0.5.mdx b/pages/cloudflare/migrate-from-0.4-to-0.5.mdx new file mode 100644 index 0000000..26d371d --- /dev/null +++ b/pages/cloudflare/migrate-from-0.4-to-0.5.mdx @@ -0,0 +1,3 @@ +### Migrate from 0.4 (to 0.5) + +`@opennextjs/cloudflare@0.5.0` did not introduce any breaking change, meaning that there are no migration steps from `0.4` to `0.5`. From 9cd75ea6a76d7cd54fe08ce1e9095ec1ffd8c39c Mon Sep 17 00:00:00 2001 From: James Anderson Date: Wed, 26 Feb 2025 15:27:16 +0000 Subject: [PATCH 063/150] chore: add formatter (#83) --- .github/actions/build-docs/action.yml | 22 +- .github/actions/format/action.yml | 13 + .github/workflows/check.yml | 21 +- .github/workflows/nextjs.yml | 2 +- .prettierrc | 8 + bun.lockb | Bin 156549 -> 156965 bytes components/Footer.tsx | 4 +- components/Logo.svg.tsx | 13 +- package.json | 8 +- pages/_app.mdx | 4 +- pages/aws/common_issues.mdx | 15 +- pages/aws/config.mdx | 6 +- pages/aws/config/_meta.json | 2 +- pages/aws/config/custom_overrides.mdx | 208 +++-- pages/aws/config/full_example.mdx | 86 +-- pages/aws/config/nx.mdx | 21 +- pages/aws/config/overrides/_meta.json | 2 +- .../overrides/automatic_cdn_invalidation.mdx | 5 +- pages/aws/config/overrides/converter.mdx | 3 +- pages/aws/config/overrides/image_loader.mdx | 4 +- .../config/overrides/incremental_cache.mdx | 9 +- .../aws/config/overrides/origin_resolver.mdx | 2 +- .../overrides/proxy_external_request.mdx | 2 +- pages/aws/config/overrides/queue.mdx | 9 +- pages/aws/config/overrides/wrapper.mdx | 11 +- pages/aws/config/reference.mdx | 111 +-- pages/aws/config/simple_example.mdx | 70 +- pages/aws/contribute/_meta.json | 2 +- pages/aws/contribute/local_run.mdx | 22 +- pages/aws/contribute/plugin.mdx | 26 +- pages/aws/faq.mdx | 2 +- pages/aws/index.mdx | 10 +- pages/aws/inner_workings.mdx | 2 +- pages/aws/inner_workings/architecture.mdx | 3 +- .../aws/inner_workings/cache_interception.mdx | 9 +- pages/aws/inner_workings/caching.mdx | 22 +- .../aws/inner_workings/components/_meta.json | 2 +- .../components/image_optimization.mdx | 17 +- .../inner_workings/components/initializer.mdx | 5 +- .../inner_workings/components/middleware.mdx | 18 +- .../inner_workings/components/overview.mdx | 7 +- .../components/revalidation.mdx | 7 +- .../inner_workings/components/server/edge.mdx | 2 +- .../inner_workings/components/server/node.mdx | 22 +- .../aws/inner_workings/components/warmer.mdx | 7 +- pages/aws/inner_workings/routing.mdx | 7 +- pages/aws/migration.mdx | 4 +- pages/aws/reference-implementation.mdx | 710 +++++++++--------- pages/aws/v2.mdx | 9 +- pages/aws/v2/_meta.json | 2 +- pages/aws/v2/advanced/_meta.json | 2 +- pages/aws/v2/advanced/architecture.mdx | 35 +- pages/aws/v2/advanced/debugging.mdx | 2 +- pages/aws/v2/advanced/options.mdx | 6 +- pages/aws/v2/common_issues.mdx | 2 +- pages/aws/v2/common_issues/bundle_size.mdx | 10 +- pages/aws/v2/common_issues/isr.mdx | 17 +- pages/aws/v2/inner_workings/isr.mdx | 18 +- pages/aws/v2/inner_workings/plugin.mdx | 5 +- pages/aws/v2/inner_workings/streaming.mdx | 9 +- pages/aws/v2/inner_workings/warming.mdx | 2 +- pages/cloudflare/0.2/_meta.json | 2 +- pages/cloudflare/0.2/bindings.mdx | 19 +- pages/cloudflare/0.2/caching.mdx | 7 +- pages/cloudflare/0.2/examples.mdx | 8 +- pages/cloudflare/0.2/get-started.mdx | 11 +- pages/cloudflare/0.2/index.mdx | 4 +- pages/cloudflare/0.3/bindings.mdx | 19 +- pages/cloudflare/0.3/caching.mdx | 13 +- pages/cloudflare/0.3/examples.mdx | 12 +- pages/cloudflare/0.3/get-started.mdx | 40 +- pages/cloudflare/0.3/index.mdx | 6 +- pages/cloudflare/bindings.mdx | 23 +- pages/cloudflare/caching.mdx | 11 +- pages/cloudflare/community.mdx | 4 +- pages/cloudflare/examples.mdx | 12 +- pages/cloudflare/get-started.mdx | 41 +- pages/cloudflare/howtos/NextAuth.mdx | 1 - pages/cloudflare/howtos/stripeAPI.mdx | 4 +- pages/cloudflare/index.mdx | 6 +- pages/cloudflare/migrate-from-0.2-to-0.3.mdx | 4 +- pages/cloudflare/migrate-from-0.3-to-0.4.mdx | 5 +- pages/cloudflare/troubleshooting.mdx | 4 +- shared/WindowsSupport.mdx | 18 +- theme.config.jsx | 3 +- tsconfig.json | 18 +- 86 files changed, 1002 insertions(+), 979 deletions(-) create mode 100644 .github/actions/format/action.yml create mode 100644 .prettierrc diff --git a/.github/actions/build-docs/action.yml b/.github/actions/build-docs/action.yml index 44d6d04..799eff8 100644 --- a/.github/actions/build-docs/action.yml +++ b/.github/actions/build-docs/action.yml @@ -2,16 +2,16 @@ name: Build Docs description: Build docs pages inside /docs directory runs: - using: 'composite' - steps: - - name: Install dependencies - run: bun install - shell: bash + using: "composite" + steps: + - name: Install dependencies + run: bun install + shell: bash - - name: Build with Next.js - run: bun next build - shell: bash + - name: Build with Next.js + run: bun next build + shell: bash - - name: Export static HTML with Next.js - run: bun next export - shell: bash + - name: Export static HTML with Next.js + run: bun next export + shell: bash diff --git a/.github/actions/format/action.yml b/.github/actions/format/action.yml new file mode 100644 index 0000000..3257b85 --- /dev/null +++ b/.github/actions/format/action.yml @@ -0,0 +1,13 @@ +name: Format codebase +description: Run prettier to check codebase formatting + +runs: + using: "composite" + steps: + - name: Install dependencies + run: bun install + shell: bash + + - name: Run prettier + run: bun run prettier:check + shell: bash diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 2a2fc68..ea4c643 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -1,15 +1,16 @@ name: Validate merge requests on: - pull_request: - branches: - - main + pull_request: + branches: + - main jobs: - validate: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - uses: oven-sh/setup-bun@v2 - - uses: ./.github/actions/build-docs + validate: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v2 + - uses: ./.github/actions/format + - uses: ./.github/actions/build-docs diff --git a/.github/workflows/nextjs.yml b/.github/workflows/nextjs.yml index f0fe1d8..46ce460 100644 --- a/.github/workflows/nextjs.yml +++ b/.github/workflows/nextjs.yml @@ -23,7 +23,7 @@ permissions: # Allow one concurrent deployment concurrency: - group: 'pages' + group: "pages" cancel-in-progress: true jobs: diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..0adf136 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "printWidth": 110, + "singleQuote": false, + "semi": true, + "useTabs": false, + "tabWidth": 2, + "trailingComma": "es5" +} diff --git a/bun.lockb b/bun.lockb index d373d48687d5f409a4e2f3f087a0effe3a3f72c1..126f2470931ea69c4e7d92d417f540a1aef0e537 100755 GIT binary patch delta 9024 zcmeI2d32Q38HZ;AXjr0Hki;soh=3wt6BR@OMMXtGB?1-=A`#HC3MgS2mWm+Y(t(b8 zv;tN{6a`ZV9H|>_wN)0^>cT?`#xC3NQQp&i&u=yU-u06=6mGlo%#!YtmcPEE(aKhL*UpSxGCU_? zN?kLsNluNaYcKt{Ztl1VB@-u(Dw$9=uHN>#xm(X|f5zQyHZCd~S}?OXy|f@V@5bqg z#8HXF%o^0ImEKX%E>#ChOsXY$kc7QL_eM>s{`#;FG=s))EHr`vVEP|4^_>;$uqYc< zpOtXGHCu!pj5>-#b$*BDq#IAmPxqSE zw2Q&*qQB?1`q$e1kfG4CT4#O{fD{9`UN?&5>6vPp!bPqm`%? z*Pyl0jgfyK$~U9@B_8r4RP*8RKZ5$2*n-;5Godd>`75YN^&Wq{qCAy&Hwsh-vOV&u zfghl*kVy(HuMt|y45_NxabEbVs;<4m|5fGt*I`EuQKuvybqoce`=KV)7hUV{9}@m= zQ`myNJT|$pWZLk~acikiW$A$m+&|XpAJIYT%ZT~dX zqm-!y^!lsEi^Z@cEqdt>qK5PzFy>2%kv_yYSxcD zn#wvF;4rXZ6jUm%>>~E#?R(>X8(>eQAEFNY2k(3B-;4hGh8Jh}?V##@SHF3ux)`iK zEb_xq<4eF)RgD`74WV+syKkkTx~$KGn(66NT2*g$nThJn?rt}~)tg;zjs8Aop_zu7I@c-6o;Majg@y?62+nGvrQ zmyw!Fp1gI%&VEfc6s=nLz)2g2*ZlL`bBf1ys@XU3$(ZZ53@`4}VDzS^?)jke+`bdq zJwAEGi}}l*T7P}7&&xk+z4?MR1K;nmDm}Cyzr00*lyDE}{Igiq0W_)R~K~I-7f7h9Y=|NvKPCO#BmS$3iM9~FN zFyj1)Fe`i)g|9BY+2Q+n_}t^psqm$;$3xowbo>Q|*Dxm31Gmd60u$p=O^+MAUXw>j znjXU*!Kl2}i^J#1(aG3e>%{Q=1p5I;Px5rh-#&>3WFExnWL_G9&inKToD#l$@wLY` zm4?rQ{Epbpnlt3!^Wm+i>y5-;q5ztO&*KGs`$2Pm>zZbU^QYJ?!{<~QxIg?xgXC0d z9sr(u`87C|`WnL$4U#iyGaeHARhZ_YnoVGw4pQp!2y9Bm@7wA1pv}N$a6$~`3LKiv z;V2BJ+ygk{4uVG_Zc+GJ;QKv3r~JyOdocDB;k&vbE|qAB(+2$-u8GR6u;Nss`y-Xyr3;Ew(ds9cuAmaHD6Prt9(8U)!(^yaAt; z3*l`rd4ye9qd*1l}2e zUGeS0b}H`*-_h7xBW_Ljy5aLmoyxVS9UlV@(5ozqIRDA(e0*NyZ^PFeo0Fkb_A1wf zvj@(53G|BAhp#90ec>w)-*Ncf!}cmSgztFl9O4|j2ep`qUa$$5 z$c_Vh^gDHh_GWSPPQN2=4&E$Ir8glrM=Ieh?>zd2dB-^|-tvAg-j#l#-W=WxK1SXg z&asb(3yF`EE0imei-;?j&!elG3y4c@9T)&ZU@)8wKZ7FIv_U#E`^`$WOF2Qazy-(! z$7T5>I2Mk9qv1s81>K;6AfR50~ z`=m2QZwgNV*Kn8T8Q= zD21_b35PO)*cpRRDTVW;K2CLw9a0Q+Pvmw)GcCuk=9@cmm17l${i~)i19hPu)PPOCw4R~T-=R4TH-*nBa0lsxj&;O^*T;vPgh zqWhxBLys*RO9`|25DzXB!v^1Bo33U7;BM1itiaU*8+V_|mcs`4Cbc^Wh6h$5L1ZRY&eW zIk$zwz(#D$7tnL?JZuI1zH9CS-zAk-U5k7U_`az0RkraW{-csC&hsh6_%h%@Y=i1M zZ=|7%eUCKHnUO62+uUT|dUdXL%R;*LwM=0;*|MPWS3u?eI>}9*+o`Z~VaM{b(#h@p z>b&_{MfkkeGyPvp_Hb)TD!=;G3ai0raL1a(1Kb{A2U8$19N1ysP`tqCYzAj%O`6c1omW|3o2P?4b+ ziBW`z8ZT5x)>8366k}qHWuk%?@ruT%YobwOg8BVszOC9)JYuC%smgZkZ~k9@{dK>7 z{oZu<^saoOaL$Ipg+2ECU|r9}OP9UYW91{4c0ci%KkV3{$EIcrPwe)CS10Z@=XN!8y9 zwuf>kg#oY=90#U;RQuYN(E34K#)MU^@%Iv=!xYnQP~C&ir~#^R!hKfmJeKQq3<0 zyS4;;1UG^4w}R!jfn8e#CRP8PV7M4{Chhi0_w+f3m71 z_s!`~&Tr*Vz5iWJ=U$KDT-fd&6&?6CYUt5?czef1JyrAg$Tw8uM&S24qfqmwB>9;G zBmeGC~f2r|)e1+Q3B+4Dvvr!v7H}w3d_jT$QZ%#TY%tLMHGSs^B`Pdd+WacZ> z4lJR(IeHyx2bM>?s<|Tas^u$DuX7V>z4R&!XY6~z@lXV;L-|WR;zy|F`tU!B7Lk7n zwV~%iUy1U~s7dvWek01?4Zli9(y8~up&Ixh>a=I6JuL`rYKGKMy>M~(8>+6B;oq8i zoi>y=NeyMq!LSb{p>3n0>KfHK{Ck9dtD4!ax+LuYcZ;Zos=sIWRUhoWsIGpY`=Rz? zf7AziQ1}Ohe{kr*Q9d-v4?}JL@B+rtgpnJ^V^AAB7Ij)28Tk`Xlj``5Ms=Oehw)?0 zgxZnu5e0XfA*q^c`0x&DQ7hgT`k;j*)$(HLDy@s_Di zBH&X4GHb6W@g+$8Bf`InIv$@#eKpB+pH-4uoeC@>eXVAWnAJH`b!GE*Hqne4c7NN@ z=C+Wz{mT5dsYSG>8dV&5RkKy(Rn69X7}qBJn7OC)9k!wA|I|LzK78%I)ee7o8#+8! zFSj3coVK?AG(x{O`{n(orFnnjHk5%_4-V9Z#%*ZhHuPI=m0lg-+3Fly4}JNvocfK?y#gZXI_$J`c^h6@=B=sYF zcBh4LRv>v!W1I&JGxNT5YBGklzxgi7J97s)njVYI!my$9LOm3i9rgvN4SEXdxOlG@ zh0g;X$Hg=a)ocyJFuZ>|n)s`|4Vj*nk}7k~{E2XHY=7}qp>|+Lcs%adJK`^QV%|4= z)!{3_@2_H$cWGQ(xHWv;$>FP++*%sW^PQ5H3@Gu(jT5G~CIruM*IhR+fDarpMc zZiUa$xF&qQ|8>}o#!tf675i0e)3vDYNjJEq{seM)1a`-HTLi8MUk`kC!eRR<>S*-@ zJE8B!i0g&z1x+6Cc_V)Dyr6MEi?}}6Z-eQU`WI<0GXAiyKyQt}y|KH5&rb1|+6O!d z>4@GQzJ0OR;&aIF2%lf;2g0{1eEsmfhwWpyGkod(WIiQhx+|RfVQ;~9*zOMB{@Bk) z-0JWhfbWIytwFh7?*B-SV>`URh`0l>Yq1?&mA}+MaDBqhb%)L4Pb&|E1j7#88@@r< zPh;DG`%(TE9gw+#IyrA@$3XnEPf;W1~?}aLm`ZUk#GW>2qVB_j^n(Q?%ers zI2?|EBf*m{=lHkbPvA+|gYXbM49@iz!whhOIzQX)lB8#PCRLrhJcFE~8!mt|;7sTR zy`c~64Wo%Yg?^k0Be93VVbCA;gZ<$E7yt*tK`;;o!C*KT4uL~qNRk?po27e^8B2pF zK_OqoB4`30gt>%x%=S-k`}Aj650AoQumPOGe+f^(lkgjG26x83FG@pAnb4W52UFmDxBxDMi(nc|2RB+x zVHv?vz+Yh$oCK$W^Z)O`L+y*HKLgTG4Kv{q@R-;6e-$|A zUxzM%EL;tp;Z^)MWv^n)E3UzG^7MGxBkUTQm|__N~{G>yx6>-pG639aFpL&1Ch( K+3ib{tN#U9C??DR diff --git a/components/Footer.tsx b/components/Footer.tsx index f7a3cad..c690535 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -4,9 +4,7 @@ import styles from "../styles/Layout.module.css"; export default function Footer() { return (