Cloudflare
We recommend using vike-cloudflare
to deploy your app to Cloudflare.
Go to vike.dev/new if you want to scaffold a new Vike app that uses
vike-cloudflare
.
vike-cloudflare
Version history: CHANGELOG.md
Examples: vike.dev/new and examples/
Source code: GitHub > vikejs/vike-cloudflare
npm package: vike-cloudflare
You can use Vike with the vike-cloudflare
extension for a zero-config Cloudflare deployment of your SSR or pre-rendered (aka SSG) app.
See:
- With server if you use SSR (it requires a server).
- Without server if you pre-render all your pages (you don't need a server then).
With server
- npm
- pnpm
- yarn
npm i vike-cloudflare wrangler cross-env
// pages/+config.ts
import type { Config } from 'vike/types'
import vikeCloudflare from 'vike-cloudflare/config'
export default {
extends: [vikeCloudflare],
server: 'server/index.ts'
} satisfies Config
If you have
vike-server
installed then remove it (replace it withvike-cloudflare
).
- Hono
- Hattip
// server/index.ts
import { Hono } from 'hono'
import { apply } from 'vike-cloudflare/hono'
import { serve } from 'vike-cloudflare/hono/serve'
function startServer() {
const app = new Hono()
apply(app)
return serve(app, { port: 3000 })
}
export default startServer()
If you haven't already, set up a Hono server and install the
hono
package.
vike-cloudflare
currently only supports Hono and Hattip — more servers are coming soon.
// package.json
{
"scripts": {
"dev": "vike dev",
"preview": "vike build && wrangler pages dev",
"deploy": "vike build && wrangler pages deploy"
}
}
// wrangler.jsonc
{
"$schema": "node_modules/wrangler/config-schema.json",
"compatibility_date": "2025-08-06",
"name": "my-vike-cloudflare-app",
"pages_build_output_dir": "./dist/cloudflare",
// Only needed if your app (or one of your libraries) uses Node.js APIs
"compatibility_flags": ["nodejs_compat"]
}
# .gitignore
.wrangler/
Without server
- npm
- pnpm
- yarn
npm i vike-cloudflare wrangler cross-env
// pages/+config.ts
import type { Config } from 'vike/types'
import vikeCloudflare from 'vike-cloudflare/config'
export default {
prerender: true,
extends: [vikeCloudflare]
} satisfies Config
// package.json
{
"scripts": {
"dev": "vike dev",
"preview": "vike build && wrangler pages dev",
"deploy": "vike build && wrangler pages deploy"
}
}
// wangler.jsonc
{
"$schema": "node_modules/wrangler/config-schema.json",
"compatibility_date": "2025-08-06",
"name": "my-vike-cloudflare-app",
"pages_build_output_dir": "./dist/cloudflare",
"assets": {
"directory": "./dist/cloudflare"
}
}
# .gitignore
.wrangler/
Cloudflare APIs
You can access Cloudflare's APIs (such as D1 and KV):
- In development, by using
getPlatformProxy()
- In production, by using
import('cloudflare:workers')
Using +onCreateGlobalContext.server
, you can make Cloudflare's bindings (the env
object) available anywhere via globalContext.cloudflare.env
.
// pages/+onCreateGlobalContext.server.ts
export { onCreateGlobalContext }
import type { GlobalContextServer } from 'vike/types'
async function onCreateGlobalContext(globalContext: GlobalContextServer) {
let cloudflare: { env: Cloudflare.Env }
if (import.meta.env.DEV) {
const { getPlatformProxy } = await import('wrangler')
cloudflare = (await getPlatformProxy()) as any
} else {
cloudflare = await import('cloudflare:workers')
}
globalContext.cloudflare = cloudflare
}
declare global {
namespace Vike {
interface GlobalContextServer {
cloudflare: { env: Cloudflare.Env }
}
}
}
// vite.config.ts
import { defineConfig } from 'vite'
export default defineConfig({
build: {
rollupOptions: {
external: ['cloudflare:workers']
}
}
})
For an example of how to access Cloudflare D1 during development, see:
- npm
- pnpm
- yarn
npm create vike@latest --- --react --hono --drizzle --cloudflare
Or go to vike.dev/new and select
Cloudflare
with an ORM.
TypeScript
If you use TypeScript, (re-)run wrangler types
after changing your Cloudflare configuration to generate/update the worker-configuration.d.ts
file.
- npm
- pnpm
- yarn
npx wrangler types
Then commit it:
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 vike-cloudflare
, you can manually integrate your app with Cloudflare yourself.
Cloudflare Pages
For a manual integration, we generally recommend using:
- Cloudflare Pages for static assets and pre-rendered pages, and
- Pages Functions for SSR'd pages.
Examples:
- 2024.01 GitHub >
travis-r6s/vike-cf-pages
- Advanced demo showcasing a lot of integrations such as REST, tRPC, GraphQL, Sentry, and Thumbprint. -
2022.04 GitHub >
Immortalin/vite-plugin-ssr-cloudflare-pages-demo
vite-plugin-ssr was the previous name of Vike.
Wrangler
You can also directly use Cloudflare Workers instead of using Cloudflare Pages.
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:
- React: /examples/cloudflare-workers-react/
- React + SSR Streaming: /examples/cloudflare-workers-react-full/
- Vue: /examples/cloudflare-workers-vue/
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 publish
to deploy your worker to Cloudflare Workers.
Examples:
- React: /examples/cloudflare-workers-react/
- React + SSR Streaming: /examples/cloudflare-workers-react-full/
- Vue: /examples/cloudflare-workers-vue/
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
orcross-fetch
typically don't work with Cloudflare Workers.