Edit

Cloudflare

You can use Cloudflare to deploy static websites as well as SSR.

If you pre-render partially, then your pre-rendered pages are statically deployed while your SSR pages are served dynamically.

In development, your server code runs inside workerd, the same runtime Cloudflare uses in production.

If you're using vike-photon, then migrate to +server.

Get started

New app

Use vike.dev/new to scaffold a new Vike app that uses Cloudflare.

Add to existing app

1. Install

npm install wrangler @cloudflare/vite-plugin
pnpm add wrangler @cloudflare/vite-plugin
bun add wrangler @cloudflare/vite-plugin
yarn add wrangler @cloudflare/vite-plugin
// vite.config.js
 
import vike from 'vike/plugin'
import { cloudflare } from '@cloudflare/vite-plugin'
 
export default {
  plugins: [
    cloudflare({
      viteEnvironment: { name: 'ssr' } 
    }), 
    vike()
  ]
}
// vite.config.ts
 
import type { UserConfig } from 'vite'
import vike from 'vike/plugin'
import { cloudflare } from '@cloudflare/vite-plugin'
 
export default {
  plugins: [
    cloudflare({ 
      viteEnvironment: { name: 'ssr' } 
    }), 
    vike()
  ]
} satisfies UserConfig

The entire docs of using Vike with @cloudflare/vite-plugin is documented on this page.

2. Scripts

// package.json
 
{
  "scripts": {
    "dev": "vike dev",
    "preview": "vike build && vike preview", 
    "deploy": "vike build && wrangler deploy", 
    // ...
  }
}

3. Wrangler config

// wrangler.jsonc
 
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "compatibility_date": "2026-03-09",
  "name": "my-vike-cloudflare-app",
  "main": "vike:server-entry",
  // Only required if your app (or one of your libraries) uses a Node.js API
  "compatibility_flags": ["nodejs_compat"]
}
# .gitignore
 
.wrangler/

4. Server

If you didn't already, create +server.js or set +server to true.

You can export Durable Objects inside +server.js, see section below Durable Objects.

Cloudflare APIs

To access Cloudflare APIs (such as D1 and KV), use Cloudflare's bindings which are available via the env object imported from cloudflare:workers.

// Environment: server
 
import { env } from 'cloudflare:workers'
// Key-value store
env.KV.get('my-key')
// Environment variable
env.LOG_LEVEL
// ...

Example of using Cloudflare D1:

npm create vike@latest -- --react --hono --drizzle --cloudflare
pnpm create vike --react --hono --drizzle --cloudflare
bunx create-vike --react --hono --drizzle --cloudflare
yarn create vike --react --hono --drizzle --cloudflare

Or go to vike.dev/new and select Cloudflare with an ORM.

To make environment variables available on the client-side, you can use +onCreateGlobalContext.server.js with a custom globalContext property and passToClient.

// pages/+onCreateGlobalContext.server.js
// Environment: server
 
export { onCreateGlobalContext }
 
import { env } from 'cloudflare:workers'
 
async function onCreateGlobalContext(globalContext) {
  // Making the environment variable LOG_LEVEL available on the client-side
  globalContext.logLevel = env.LOG_LEVEL || 'info'
}
// pages/+onCreateGlobalContext.server.ts
// Environment: server
 
export { onCreateGlobalContext }
 
import { env } from 'cloudflare:workers'
import type { GlobalContextServer } from 'vike/types'
 
async function onCreateGlobalContext(globalContext: GlobalContextServer) {
  // Making the environment variable LOG_LEVEL available on the client-side
  globalContext.logLevel = env.LOG_LEVEL || 'info'
}
 
declare global {
  namespace Vike {
    interface GlobalContext {
      logLevel: string
    }
  }
}
// pages/+config.js
 
export default {
  passToClient: ['logLevel']
}
// pages/+config.ts
 
import type { Config } from 'vike/types'
 
export default {
  passToClient: ['logLevel']
} satisfies Config
// anywhere.js
// Environment: server and/or client
 
import { getGlobalContext } from 'vike'
 
const globalContext = getGlobalContext()
// Available anywhere
console.log(globalContext.logLevel)
// anywhere.ts
// Environment: server and/or client
 
import { getGlobalContext } from 'vike'
 
const globalContext = getGlobalContext()
// Available anywhere
console.log(globalContext.logLevel)

Durable Objects

You can export Durable Objects inside your +server.js file:

// +server.js
 
// ...
 
export class MyDurableObject extends DurableObject {
  // ...
} 
// +server.ts
 
// ...
 
export class MyDurableObject extends DurableObject { 
  // ...
} 

If you use Vike's built-in server (+server: true), then define the following +server.js instead:

// +server.js
 
// 1. Use Vike's built-in server
import vike from 'vike/fetch'
export default vike
 
// 2. Export Durable Object
export class MyDurableObject extends DurableObject {
  // ...
}
// +server.ts
 
// 1. Use Vike's built-in server
import vike from 'vike/fetch'
export default vike
 
// 2. Export Durable Object
export class MyDurableObject extends DurableObject {
  // ...
}

TypeScript

If you use TypeScript, run wrangler types whenever you change your Cloudflare configuration to update the worker-configuration.d.ts file.

npx wrangler types
pnpm dlx wrangler types
bun x wrangler types
yarn dlx wrangler types

Then commit:

git commit -am "update cloudflare types"

Make sure TypeScript loads it:

// tsconfig.json
 
{
  "compilerOptions": {
    "types": ["./worker-configuration.d.ts"] 
 }
}

See also: Cloudflare Workers > TypeScript

Extend 3MB limit

By default the bundle size of your worker cannot exceed 3MB, but you can request sizes of up to 100MB and beyond.

Manual integration

Instead of using @cloudflare/vite-plugin, you can integrate Cloudflare Workers yourself.

Cloudflare Workers requires your entire worker code to be bundled into a single file — you can use Wrangler to achieve that (it uses esbuild under the hood).

Cloudflare uses the term "worker code" to denote server code that is run on its edge infrastructure.

Examples:

Development

For a significantly faster development experience we recommend, whenever possible, using Vite's development server (or a server such as Express.js or Hono) instead of Wrangler.

In other words:

  • Skip wrangler / Cloudflare Workers altogether while developing your app.
  • Use wrangler dev to preview your worker.
  • Use wrangler deploy to deploy your worker to Cloudflare Workers.

Examples:

Universal fetch()

When using Node.js(/Bun/Deno) for development and Cloudflare Workers for production, you may need a fetch() function that works in both environments.

You can define a fetch function at pageContext.fetch that works in all environments. The trick is to add a different fetch() implementation to pageContextInit at renderPage(pageContextInit).

Example: /examples/cloudflare-workers-react-full#universal-fetch.

Libraries such as node-fetch or cross-fetch typically don't work with Cloudflare Workers.

See also