Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions pages/cloudflare/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
"examples": "",
"community": "Community projects",
"troubleshooting": "",
"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"
"migrate-from-0.5-to-0.6": "Migrate from 0.5 to 0.6",
"former-releases": "Former releases"
}
1 change: 0 additions & 1 deletion pages/cloudflare/bindings.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../config";
import { Callout } from "nextra/components";

### Bindings
Expand Down
347 changes: 303 additions & 44 deletions pages/cloudflare/caching.mdx

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion pages/cloudflare/community.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../config";
import { Callout } from "nextra/components";

## Projects from the community
Expand Down
1 change: 0 additions & 1 deletion pages/cloudflare/examples.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../config";
import { Callout } from "nextra/components";

## Examples
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";

### Bindings
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";

## Caching
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";

## Examples
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";

### Get Started
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";

## Cloudflare
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";

### Bindings
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";

## Caching
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";

## Examples
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";

### Get Started
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { SITE } from "../../../config";
import { Callout } from "nextra/components";
import WindowsSupport from "../../../shared/WindowsSupport.mdx";
import WindowsSupport from "../../../../shared/WindowsSupport.mdx";

## Cloudflare

Expand Down
7 changes: 7 additions & 0 deletions pages/cloudflare/former-releases/0.5/_meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"index": "Overview",
"get-started": "",
"bindings": "",
"caching": "",
"examples": ""
}
74 changes: 74 additions & 0 deletions pages/cloudflare/former-releases/0.5/bindings.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
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 = getCloudflareContext().env.MY_KV_NAMESPACE;
await myKv.put("foo", "bar");
const foo = await myKv.get("foo");

return new Response(foo);
}
```

<Callout type='info'>
`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.

</Callout>

#### 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 `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 } = getCloudflareContext();

// ...
}
```
156 changes: 156 additions & 0 deletions pages/cloudflare/former-releases/0.5/caching.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
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).

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/).

<Callout>
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.
</Callout>

### How to enable caching

`@opennextjs/cloudflare` supports multiple caching mechanisms through a project's OpenNext configuration.

#### Incremental Static Regeneration (ISR)

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

```
npx wrangler@latest kv namespace create <YOUR_NAMESPACE_NAME>
```

##### 2. Add the KV namespace and Service Binding to your Worker

The binding name used in your app's worker is `NEXT_CACHE_WORKERS_KV`. The service binding should be a self reference to your worker where `<WORKER_NAME>` is the name in your wrangler configuration file.

```jsonc
// wrangler.jsonc
{
// ...
"kv_namespaces": [
{
"binding": "NEXT_CACHE_WORKERS_KV",
"id": "<BINDING_ID>",
},
],
"services": [
{
"binding": "NEXT_CACHE_REVALIDATION_WORKER",
"service": "<WORKER_NAME>",
},
],
}
```

#### 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.

<Callout type="warning">
The memory queue provided by `@opennextjs/cloudflare` is not fully suitable for production deployments, you
can use it at your own risk!
</Callout>

```ts
// open-next.config.ts
import { defineCloudflareConfig } from "@opennextjs/cloudflare";
import kvIncrementalCache from "@opennextjs/cloudflare/kv-cache";
import memoryQueue from "@opennextjs/cloudflare/memory-queue";

export default defineCloudflareConfig({
incrementalCache: kvIncrementalCache,
queue: memoryQueue,
});
```

<Callout>
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.
</Callout>

#### 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).

<Callout>
If your app **only** uses the pages router, it does not need to have a tag cache and should skip this step.
</Callout>

##### 1. Create a D1 database and Service Binding

The binding name used in your app's worker is `NEXT_CACHE_D1`. The service binding should be a self reference to your worker where `<WORKER_NAME>` is the name in your wrangler configuration file.

```jsonc
// wrangler.jsonc
{
// ...
"d1_databases": [
{
"binding": "NEXT_CACHE_D1",
"database_id": "<DATABASE_ID>",
"database_name": "<DATABASE_NAME>",
},
],
"services": [
{
"binding": "NEXT_CACHE_REVALIDATION_WORKER",
"service": "<WORKER_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 { defineCloudflareConfig } from "@opennextjs/cloudflare";
import kvIncrementalCache from "@opennextjs/cloudflare/kv-cache";
import d1TagCache from "@opennextjs/cloudflare/d1-tag-cache";
import memoryQueue from "@opennextjs/cloudflare/memory-queue";

export default defineCloudflareConfig({
incrementalCache: kvIncrementalCache,
tagCache: d1TagCache,
queue: memoryQueue,
});
```

##### 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.
24 changes: 24 additions & 0 deletions pages/cloudflare/former-releases/0.5/examples.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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/).
Loading