Skip to content

Commit f866865

Browse files
authored
Merge pull request #3 from opennextjs/bib/cloudflare
WIP: Add docs for Cloudflare adapter
2 parents e7e6b32 + bbb57a5 commit f866865

File tree

8 files changed

+331
-5
lines changed

8 files changed

+331
-5
lines changed

pages/aws/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ If you're migrating from V2 to V3, you can find the migration guide [here](/aws/
1313
---
1414

1515
OpenNext takes the Next.js build output and converts it into packages that can be deployed across a variety of environments.
16-
Natively OpenNext has support for AWS Lambda and classic Node Server. It also offer partial support for the `edge` runtime in Cloudflare Workers.
16+
Natively OpenNext has support for AWS Lambda, [Cloudflare](/cloudflare), and classic Node.js Server.
1717

1818
One notable feature of OpenNext is its ability to split the Next.js output, enabling selective deployment to different targets such as AWS Lambda, Cloudflare Workers, or Amazon ECS. This facilitates a tailored deployment strategy that aligns with the specific needs of your application.
1919

pages/cloudflare/bindings.mdx

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { SITE } from '../../config';
2+
import { Callout } from 'nextra/components';
3+
4+
### Bindings
5+
6+
[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.
7+
8+
#### How to configure your Next.js app so it can access bindings
9+
10+
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), y
11+
12+
#### How to access bindings in your Next.js app
13+
14+
You can access [bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/) from any route of your Next.js app via `getCloudlfareContext`:
15+
16+
```js
17+
import { getCloudflareContext } from "@cloudflare/next-on-pages";
18+
19+
export async function GET(request) {
20+
let responseText = "Hello World";
21+
22+
const myKv = (await getCloudflareContext()).env.MY_KV_NAMESPACE;
23+
await myKv.put("foo", "bar");
24+
const foo = await myKv.get("foo");
25+
26+
return new Response(foo);
27+
}
28+
```
29+
30+
#### How to add bindings to your Worker
31+
32+
Add bindings to your Worker by [adding them to your `wrangler.toml` configuration file](/pages/functions/wrangler-configuration/).
33+
34+
## TypeScript type declarations for bindings
35+
36+
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):
37+
38+
```
39+
npx wrangler types --experimental-include-runtime
40+
```
41+
42+
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.
43+
44+
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:
45+
46+
```bash
47+
npx wrangler types --experimental-include-runtime="./runtime.d.ts"
48+
```
49+
50+
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.
51+
52+
## Other Cloudflare APIs (`cf`, `ctx`)
53+
54+
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):
55+
56+
```js
57+
import { getCloudflareContext } from "@opennextjs/cloudflare";
58+
59+
60+
export async function GET(request) {
61+
const { env, cf, ctx } = await getCloudflareContext();
62+
63+
// ...
64+
}
65+
```

pages/cloudflare/caching.mdx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { SITE } from '../../config';
2+
import { Callout } from 'nextra/components';
3+
4+
## Caching
5+
6+
`@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/).
7+
8+
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.
9+
10+
[The cache persists across deployments](https://nextjs.org/docs/app/building-your-application/caching#data-cache). You are responsible for revalidating/purging this cache.
11+
12+
:::note
13+
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.
14+
:::
15+
16+
### How to enable caching
17+
18+
`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.
19+
20+
To enable caching, you must:
21+
22+
#### 1. Create a KV namespace
23+
24+
```
25+
npx wrangler@latest kv namespace create NEXT_CACHE_WORKERS_KV
26+
```
27+
28+
#### 2. Add the KV namespace to your Worker
29+
30+
```
31+
[[kv_namespaces]]
32+
binding = "NEXT_CACHE_WORKERS_KV"
33+
id = "<YOUR_NAMESPACE_ID>"
34+
```
35+
36+
### 3. Set the name of the binding to `NEXT_CACHE_WORKERS_KV`
37+
38+
As shown above, the name of the binding that you configure for the KV namespace must be set to `NEXT_CACHE_WORKERS_KV`.

pages/cloudflare/examples.mdx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { SITE } from '../../config';
2+
import { Callout } from 'nextra/components';
3+
4+
## Examples
5+
6+
To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run:
7+
8+
```
9+
npm create cloudflare@latest --no-auto-update --experimental --framework next
10+
```
11+
12+
### Basic starter projects
13+
14+
Two basic example apps are included in the repository for `@opennextjs/cloudflare` package:
15+
16+
- [*`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).
17+
- [*`api`*](https://github.com/opennextjs/opennextjs-cloudflare/tree/main/examples/api) — a minimal Next.js project with a single API route
18+
19+
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).
20+
21+
### Next.js Commerce Demo
22+
23+
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](TODO).
24+
25+
To run this using `@opennextjs/cloudflare`, TODO.

pages/cloudflare/get-started.mdx

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { SITE } from '../../config';
2+
import { Callout } from 'nextra/components';
3+
4+
### Get Started
5+
6+
#### New apps
7+
8+
To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run:
9+
10+
```
11+
npm create cloudflare@latest --no-auto-update --experimental --framework next
12+
```
13+
14+
#### Existing Next.js apps
15+
16+
##### 1. Install @opennextjs/cloudflare
17+
18+
First, install [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare):
19+
20+
```sh
21+
npm install --save-dev @opennextjs/cloudflare
22+
```
23+
24+
##### 2. Add a `wrangler.toml` file
25+
26+
Then, add a [`wrangler.toml`](https://developers.cloudflare.com/workers/wrangler/configuration/) file to the root directory of your Next.js app:
27+
28+
```toml
29+
main = ".worker-next/index.mjs"
30+
name = "my-app"
31+
compatibility_date = "2024-09-23"
32+
compatibility_flags = ["nodejs_compat"]
33+
experimental_assets = { directory = ".worker-next/assets", binding = "ASSETS" }
34+
```
35+
36+
<Callout>
37+
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.
38+
</Callout>
39+
40+
`wrangler.toml` is where you configure your Worker and define what resources it can access via [bindings](/workers/runtime-apis/bindings/).
41+
42+
##### 3. Update `package.json`
43+
44+
Add the following to the scripts field of your `package.json` file:
45+
46+
```json
47+
"build:worker": "cloudflare",
48+
"dev:worker": "wrangler dev --port 8771",
49+
"preview:worker": "npm run build:worker && npm run dev:worker",
50+
"deploy:worker": "npm run build:worker && wrangler deploy"
51+
```
52+
53+
- `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.
54+
- `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.
55+
- `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.
56+
- `npm run deploy`: Builds your app, and then deploys it to Cloudflare
57+
58+
### 4. Add caching with Workers KV
59+
60+
`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.
61+
62+
To enable caching, you must:
63+
64+
##### Create a KV namespace
65+
66+
```
67+
npx wrangler@latest kv namespace create NEXT_CACHE_WORKERS_KV
68+
```
69+
70+
##### Add the KV namespace to your Worker
71+
72+
```
73+
[[kv_namespaces]]
74+
binding = "NEXT_CACHE_WORKERS_KV"
75+
id = "<YOUR_NAMESPACE_ID>"
76+
```
77+
78+
#### Set the name of the binding to `NEXT_CACHE_WORKERS_KV`
79+
80+
As shown above, the name of the binding that you configure for the KV namespace must be set to `NEXT_CACHE_WORKERS_KV`.
81+
82+
##### 5. Develop locally
83+
84+
You can continue to run `next dev` when developing locally.
85+
86+
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.
87+
88+
##### 6. Deploy to Cloudflare Workers
89+
90+
Either deploy via the command line:
91+
92+
```sh
93+
npm run deploy
94+
```
95+
96+
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.

pages/cloudflare/index.mdx

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,64 @@
1-
### TODO
1+
import { SITE } from '../../config';
2+
import { Callout } from 'nextra/components';
23

4+
## Cloudflare
5+
6+
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).
7+
8+
<Callout>
9+
[`@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.
10+
11+
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](LINK).
12+
</Callout>
13+
14+
### Get Started
15+
16+
##### New apps
17+
18+
To create a new Next.js app, pre-configured to run on Cloudflare using @opennextjs/cloudflare, run:
19+
20+
```
21+
npm create cloudflare@latest --no-auto-update --experimental --framework next
22+
```
23+
24+
##### Existing Next.js apps
25+
26+
Follow the guide [here](/cloudflare/get-started) to use [@opennextjs/cloudflare](https://www.npmjs.com/package/@opennextjs/cloudflare) with an existing Next.js app.
27+
28+
### Supported Next.js runtimes
29+
30+
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.
31+
32+
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.
33+
34+
### Supported Next.js versions
35+
36+
`@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)
37+
38+
To help improve compatibility, we encourage you to [report bugs](https://github.com/opennextjs/opennextjs-cloudflare/issues) and contribute code!
39+
40+
### Supported Next.js features
41+
42+
- [x] [App Router](https://nextjs.org/docs/app) & [Pages Router](https://nextjs.org/docs/pages)
43+
- [x] [API routes](https://nextjs.org/docs/pages/building-your-application/routing/api-routes)
44+
- [x] [Dynamic routes](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes)
45+
- [x] [Static Site Generation (SSG)](https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation)
46+
- [x] [Server-Side Rendering (SSR)](https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering)
47+
- [x] [Incremental Static Regeneration<sup>1</sup> (ISR)](https://nextjs.org/docs/pages/building-your-application/data-fetching/incremental-static-regeneration)
48+
49+
<sup>1</sup> "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))
50+
51+
### Not Yet Supported Next.js features
52+
53+
- [ ] [Partial Prerendering (PPR)](https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering)
54+
- [ ] [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware)
55+
- [ ] [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/))
56+
- [ ] [Experimental streaming support](https://nextjs.org/blog/next-15-rc#executing-code-after-a-response-with-nextafter-experimental)
57+
58+
### How @opennextjs/cloudflare Works
59+
60+
The OpenNext Cloudflare adapter works by taking the Next.js build output and transforming it, so that it can run in Cloudflare Workers.
61+
62+
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.
63+
64+
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.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { SITE } from '../../config';
2+
import { Callout } from 'nextra/components';
3+
4+
## Troubleshooting
5+
6+
### Trying to deploy to Cloudflare Pages, instead of Cloudflare Workers?
7+
8+
`@opennextjs/cloudflare` is specifically built for deploying Next.js apps to [Cloudflare Workers](https://developers.cloudflare.com/workers/)
9+
10+
Cloudflare Workers now support the majority of functionality from Cloudflare Pages, and have features that are not yet supported by Cloudflare Pages. Refer to the [Compatibility Matrix](https://developers.cloudflare.com/workers/static-assets/compatibility-matrix/) in the Cloudflare Workers docs.
11+
12+
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/).
13+
14+
### "Your Worker exceeded the size limit of 1 MiB"
15+
16+
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.
17+
18+
### My app fails to build when I import a specific NPM package
19+
20+
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.
21+
22+
Some NPM packages define multiple exports. For example:
23+
24+
```
25+
"exports": {
26+
"other": "./src/other.js",
27+
"node": "./src/node.js",
28+
"browser": "./src/browser.js",
29+
"default": "./src/default.js"
30+
},
31+
```
32+
33+
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.
34+
35+
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:
36+
37+
```
38+
WRANGLER_BUILD_CONDITIONS=""
39+
WRANGLER_BUILD_PLATFORM="node"
40+
```

0 commit comments

Comments
 (0)