Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
4 changes: 3 additions & 1 deletion pages/cloudflare/howtos/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
"image": "Image Optimization",
"custom-worker": "Custom Worker",
"keep_names": "__name issues",
"workerd": "workerd specific packages"
"workerd": "workerd specific packages",
"skew": "Skew Protection",
"assets": "Static assets"
}
56 changes: 56 additions & 0 deletions pages/cloudflare/howtos/assets.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
## Static assets (public folder)

The [static assets of Next located in the public folder](https://nextjs.org/docs/app/api-reference/file-conventions/public-folder) are served using [Workers Static Assets](https://developers.cloudflare.com/workers/static-assets/).

Workers Static Assets can intercept requests to the application ([`run_worker_first=false`](https://developers.cloudflare.com/workers/static-assets/) which is the default). This is the most cost efficient option as asset requests will not be billed in that case.

Another option is to run the Worker first (`run_worker_first=true`) to offer more flexibility at the expense of a higher cost.

Note that `run_worker_first` could also be set to a list of patterns - this is a great option if you need more flexibility for only a subset of the statids assets.

### run_worker_first=false

When `run_worker_first` is set to `false`, requests are intercepted before reaching the worker and are not billed:

```jsonc
// wrangler.jsonc
{
"name": "my-app",
// ...
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS",
// Optional as false is the default value
"run_worker_first": false,
},
// ...
}
```

This is the most cost efficient option to use when you do not need to serve assets behind the middleware or Next rewrites and headers from [the Next config](https://nextjs.org/docs/app/api-reference/config/next-config-js).

When `run_worker_first=false` you can still configure [headers](https://developers.cloudflare.com/workers/static-assets/headers/) and [redirects](https://developers.cloudflare.com/workers/static-assets/redirects/) via Worker Static Assets.

### run_worker_first=true

When `run_worker_first` is set to `true`, all the requests will reach the Worker and be billed:

```jsonc
// wrangler.jsonc
{
"name": "my-app",
// ...
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS",
"run_worker_first": true,
},
// ...
}
```

The Open Next asset resolver will be used to retrieve the assets from the Worker.

When `run_worker_first=true`, assets are served behind the middleware and Next rewrites and headers from [the Next config](https://nextjs.org/docs/app/api-reference/config/next-config-js). The [headers](https://developers.cloudflare.com/workers/static-assets/headers/) and [redirects](https://developers.cloudflare.com/workers/static-assets/redirects/) configured for the Worker Static Assets do not apply in this case.

`run_worker_first=true` should be used if you plan to use skew protection.
88 changes: 88 additions & 0 deletions pages/cloudflare/howtos/skew.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Callout } from "nextra/components";

## Skew protection

The Cloudflare adapter has _experimental support_ for skew protection based on [the preview URLs](https://developers.cloudflare.com/workers/configuration/previews/).

<Callout type="info">
Preview URLs are disabled for [Workers that implement a Durable
Object](https://developers.cloudflare.com/workers/configuration/previews/#limitations). If your app uses
Durable Objects, they will need to be implemented in a separate Worker.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably add an example for this at one point.

</Callout>

### How to enable the skew protection

**OpenNext config**

Set `cloudflare.skewProtection.enabled` to `true` to enable skew protection:

```ts
// open-next.config.ts
export default {
// ...
cloudflare: {
skewProtection: {
enabled: true,
// Maximum number of previous versions to use.
// Optional, default to 20.
maxNumberOfVersions: 20,
// Age of the oldest version to use (from the last deplyment date)
// Optional, default to 7 days.
maxVersionAgeDays: 7,
},
},
} satisfies OpenNextConfig;
```

**Wrangler configuration**

The Worker needs to serve the correct version of the app assets. For that it need be be executed before incoming requests are matched against the assets. Set [`run_worker_first`](https://developers.cloudflare.com/workers/static-assets/binding/#run_worker_first) to `tue` in your wrangler configuration to enable this behavior:

```jsonc
// wrangler.jsonc
{
"name": "my-app",
// ...
"assets": {
"directory": ".open-next/assets",
"binding": "ASSETS",
"run_worker_first": true,
},
// ...
}
```

**Environment variables**

The following environment variables should be set when the skew protection is used:

- `CF_WORKER_NAME` should be set to the name of the worker, i.e. `my-app` given the config above. If you're using environment, the name of the app should contain your env, i.e. `my-app-<env>`
- `CF_PREVIEW_DOMAIN` is the the subdomain of `workers.dev` where the previews are deployed, i.e. `<version-name>.<domain>.workers.dev`
- `CF_WORKERS_SCRIPTS_API_TOKEN` is an API token with the `Workers Scripts:Read` permission
- `CF_ACCOUNT_ID` is the Cloudflare account id where the app is deployed.

Those variables are used to retrieve the past deployments of your application.

**Next config**

You must set a different `deploymentId` in your next config each time your app is deployed. You will get an error if the `deployementId` has already been used by a previous deployment.

The cloudflare adapter exports a `getDeploymentId()` function that can be used to generate a unique deployment id.

```ts
// next.config.ts
import { getDeploymentId } from "@opennextjs/cloudflare";

const nextConfig = {
// ...
deploymentId: getDeploymentId(),
};
```

### What you should know

- Because the Worker is configured to run in front of the assets Worker (`run_worker_first`), requesting an asset will count as a request to your Worker
- Requesting an older deployment will generate 2 requests: the request to the latest version and the request to the older version
- It is not currently possible to delete a deployment
- Requests to an older deployment will be a few milli-seconds slower than requests to the latest version of the app
- Request to a deployment older than the `maxNumberOfVersions` or older than `maxVersionAgeDays` will fallback to the current deployment