react-server675fbba4
react-servertreemaindocssrcpagesen(pages)deploycloudflare.mdx
docs/src/pages/en/(pages)/deploy/cloudflare.mdxmdx6.3 KiB2c9a2c54

title: Cloudflare category: Deploy order: 2

import Link from "../../../../components/Link.jsx";

Cloudflare

To deploy to Cloudflare Workers or Pages, use the built-in cloudflare adapter. This adapter is specifically designed to work with Cloudflare's edge runtime.

<Link name="installation"> ## Installation </Link>

First you need to have a Cloudflare account with Workers enabled and the wrangler CLI installed:

npm install -g wrangler
wrangler login

No additional packages are needed - the adapter is built into @lazarv/react-server.

Then you need to add the adapter to your react-server.config.mjs file:

export default {
  adapter: "cloudflare",
};
<Link name="configuration"> ## Configuration </Link>

You can customize the adapter by passing options:

export default {
  adapter: [
    "cloudflare",
    {
      name: "my-app", // Cloudflare Worker name
      compatibilityDate: "2024-01-01", // Cloudflare compatibility date
      compatibilityFlags: ["nodejs_compat_v2"], // Additional compatibility flags
      pages: true, // Generate _routes.json for Cloudflare Pages
      excludeRoutes: ["/api/*"], // Additional routes to exclude from worker handling
      serverlessFunctions: true, // Enable worker deployment (default: true)
      wrangler: {
        vars: {
          MY_VAR: "value",
        },
      },
    },
  ],
};

Configuration Options

  • name: Cloudflare Worker name. Falls back to package.json name (without scope) or "react-server-app".
  • compatibilityDate: Cloudflare compatibility date (default: current date).
  • compatibilityFlags: Additional Cloudflare compatibility flags (appended to required nodejs_compat).
  • pages: Generate _routes.json for Cloudflare Pages (default: true).
  • excludeRoutes: Additional routes to exclude from worker handling in _routes.json.
  • serverlessFunctions: Enable/disable worker deployment (default: true). Set to false for static-only deployment.
  • wrangler: Additional wrangler.toml configuration as an object (merged with adapter defaults).
<Link name="response-headers"> ## Response headers </Link>

To attach response headers to pre-rendered (ASSETS-served) pages — RFC 8288 Link headers for agent discovery, security headers, custom cache directives — drop a _headers file into your public/ directory. The runtime copies it to the static asset bundle at build time and Cloudflare applies it natively:

/*
  Link: </.well-known/api-catalog>; rel="api-catalog"; type="application/linkset+json"

/secure/*
  X-Frame-Options: DENY
  Referrer-Policy: no-referrer

This works even when run_worker_first is enabled, as long as the worker proxies the request via env.ASSETS.fetch() (which the built-in adapter does) — the response is generated by the static-assets binding, not by the worker, so _headers rules are preserved end-to-end.

For headers that should also appear on worker-generated responses (SSR pages, content-negotiation responses, server functions, …) set them inside your middleware with setHeader from @lazarv/react-server. The _headers file does not apply to worker-generated responses.

<Link name="run-worker-first"> ## Worker-first request handling </Link>

By default Cloudflare serves static assets directly and only invokes your worker when no asset matches. If you need the worker to run before static assets — for example to do content negotiation between an HTML page and its .md sibling, set custom redirects, or apply auth in front of pre-rendered pages — enable run_worker_first in react-server.wrangler.toml:

[assets]
run_worker_first = true

The setting accepts either a boolean or an array of glob patterns (with ! for exclusion) to scope worker-first handling to specific routes:

[assets]
run_worker_first = ["/*", "!/assets/*", "!/client/*"]

The built-in worker proxies non-deferred requests through env.ASSETS.fetch(), so _headers continues to apply to those responses even with run_worker_first enabled. Worker-generated responses (SSR / content-negotiated alternatives) need to set their own headers from middleware.

<Link name="extending-wrangler"> ## Extending Wrangler configuration </Link>

To extend the generated wrangler.toml, create a react-server.wrangler.toml file in your project root. The adapter will merge it with its configuration:

  • Primitive values: Adapter config takes precedence
  • Objects: Deep merged recursively
  • Arrays: Unique items from your config are preserved and prepended to adapter defaults

This allows you to add custom bindings, environment variables, or other Cloudflare-specific configuration while the adapter manages the required settings.

[vars]
MY_API_KEY = "secret"

[[kv_namespaces]]
binding = "MY_KV"
id = "abc123"
<Link name="deploy"> ## Deploy </Link>

When using @lazarv/react-server with the Cloudflare adapter, you can deploy your application using the following command:

pnpm react-server build [root] # [root] is the entry point of your application
wrangler deploy

You can also deploy with the react-server CLI by using the --deploy argument:

pnpm react-server build [root] --deploy

This will build your application and deploy it to Cloudflare Workers.

<Link name="cloudflare-pages"> ## Cloudflare Pages </Link>

The adapter automatically generates a _routes.json file for Cloudflare Pages compatibility. This file specifies which routes should be handled by the Worker and which should be served as static assets.

By default, static assets like images, CSS, JavaScript, and fonts are excluded from Worker handling. You can add additional routes to exclude using the excludeRoutes option.

To deploy to Cloudflare Pages, you can use the Cloudflare dashboard or the wrangler pages commands.

Note: Some advanced Cloudflare features like Durable Objects, D1, and R2 bindings can be configured through the react-server.wrangler.toml file. Please refer to the Cloudflare Workers documentation for more information about available features and configuration options.