
Vike 官方示例实战在 Cloudflare Workers 上运行 React SSR 应用【免费下载链接】vike(Replaces Next.js/Nuxt) Build mission-critical applications with stability and development freedom.项目地址: https://gitcode.com/GitHub_Trending/vi/vike本篇指南基于 Vike 仓库中的官方示例 examples/cloudflare-workers-react讲解如何用 Vite Vike React 搭建一个可直接部署到 Cloudflare Workers 的服务端渲染SSR应用。读完本文后你能掌握完整的 Worker 入口与 SSR 处理链路、静态资源的 KV 分发方式、wrangler.jsonc的关键配置项以及在 Vike 钩子中同时兼容开发与生产两种环境的 Cloudflare 平台变量env读取技巧。示例定位与适用场景该示例演示了三个组件的组合Vite构建与开发服务器Vike页面框架负责路由、配置钩子config hooks与 SSR 入口renderPageReactUI 框架通过自定义集成而非vike-react扩展接入。注意来自官方 README如果要从零创建新的 Vike 应用官方推荐使用 Bati 与 new/core 文档。从package.json依赖可以看到本示例的技术基线vike0.4.262、vite^7、react^19、wrangler^4并通过cloudflare/kv-asset-handler处理静态资源。运行方式开发、本地预览与部署README 给出的完整流程如下在仓库内操作仓库为只读参考git clone gitgithub.com:vikejs/vike cd vike/examples/cloudflare-workers-react/ npm install开发模式npm run devnpm run dev对应脚本为dev: vike dev。官方特别指出为了提升开发速度开发阶段直接使用 Vite 的开发服务器而不是起一个 Worker。这避免了每次热更新都经过wrangler dev的冷启动开销。本地预览 Workernpm run previewnpm run preview对应脚本为preview: vike build wrangler dev即先用 Vike 构建出产物再由 Wrangler 在本地默认 3000 端口见wrangler.jsonc的dev.port启动真实的 Worker 运行时。运行前需要登录/创建 Cloudflare 账号。部署npm run deploynpm run deploy对应脚本为deploy: vike build wrangler publish构建后直接发布到 Cloudflare。此外package.json中还提供了cf-typegen: wrangler types用于根据 Wrangler 配置生成worker-configuration.d.ts类型声明文件该文件已存在于示例目录中供 TypeScript 校验Cloudflare.Env等类型。构建与 Wrangler 配置要点vite.config.jsimport react from vitejs/plugin-react import vike from vike/plugin export default { plugins: [react(), vike()], build: { rollupOptions: { external: [cloudflare:workers], }, }, }关键点是rollupOptions.external: [cloudflare:workers]cloudflare:workers是 Workers 运行时的内置模块只能在 Cloudflare 环境中解析构建时必须将其标记为外部依赖否则 Rollup 会尝试打包它并在构建期报错。wrangler.jsonc{ $schema: node_modules/wrangler/config-schema.json, compatibility_date: 2025-08-06, name: vike_examples_cloudflare-workers-react, vars: { SOME_ENV_VAR: some-value }, dev: { port: 3000 }, define: { // Workaround https://github.com/cloudflare/workers-sdk/issues/7886 process.env.NODE_ENV: production }, main: ./worker/index.js, assets: { directory: ./dist/client/ } }各字段的作用字段说明mainWorker 入口指向 worker/index.jsassets.directory静态资源目录指向 Vike 构建输出的./dist/client/由 Cloudflare 的 Assets 机制配合cloudflare/kv-asset-handler提供vars注入平台级环境变量示例中定义了SOME_ENV_VAR后续在 Vike 钩子中读取define将process.env.NODE_ENV静态替换为production这是针对 workers-sdk 已知问题的 workaround注释中引用了 workers-sdk issue #7886compatibility_date锁定的 Workers 兼容日期决定可用的运行时特性集dev.portwrangler dev本地预览端口Worker 端的两条请求处理路径SSR 路径worker/ssr.jsimport { renderPage } from vike/server export async function handleSsr(url) { const pageContextInit { urlOriginal: url.href, } const pageContext await renderPage(pageContextInit) const { httpResponse } pageContext return new Response(httpResponse.body, { headers: httpResponse.headers, status: httpResponse.statusCode, }) }这是 Vike 部署到任意 Web 环境的核心模式向renderPage传入仅含urlOriginal的最小pageContextInitVike 会自行解析路由、执行onBeforeRender/onRenderHtml等钩子最终把渲染结果以pageContext.httpResponse含body、headers、statusCode返回Worker 只需把它翻译成标准的Response对象。入口worker/index.jsimport { handleSsr } from ./ssr export default { async fetch(request) { const url new URL(request.url) return await handleSsr(url) }, }本示例的入口对所有请求统一走 SSR 处理renderPage内部会根据匹配到的页面配置决定渲染模式。静态资源路径worker/static-assets.js该文件提供了基于cloudflare/kv-asset-handler的handleStaticAssets实现代码注释标明由 Cloudflare Workers 官方提供。其要点getAssetFromKV(event, options)从 AssetsKV中取出对应资源DEBUG标志控制两件事跳过边缘缓存以便调试以及异常时返回错误信息而非默认 404 页统一为响应补充安全响应头X-XSS-Protection、X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Feature-Policy未命中资源时回退到404.html仍失败则返回 500。在本示例中wrangler.jsonc已配置了assets目录静态文件由 Cloudflare Assets 直接提供因此handleStaticAssets更多是作为手动接管静态资源分发的参考模板存在。在 Vike 钩子中读取 Cloudflare 平台变量Cloudflare 特有的一点是env包括vars、KV、D1 等绑定只能从 Workers 运行时获取且在wrangler dev本地模拟与真实 Workers 生产环境中获取方式不同。示例在 pages/onCreateGlobalContext.server.ts 中给出了标准解法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 globalContext.someEnvVar cloudflare.env[SOME_ENV_VAR] }要点解析开发环境vike dev通过wrangler包的getPlatformProxy()创建一个模拟env的平台代理从而在 Vite 开发服务器里也能读到vars中定义的变量生产环境运行在 Workers 内直接import(cloudflare:workers)拿到真实的env绑定——这也解释了为什么vite.config.js必须把cloudflare:workers设为 external全局只执行一次onCreateGlobalContext是 Vike 的服务端全局钩子在创建 Worker 全局上下文时运行一次适合做这类“一次读取、处处共享”的初始化文件末尾的declare global块通过 Vike 的Vike命名空间对GlobalContextServer/GlobalContext做类型增强使globalContext.cloudflare与someEnvVar在 TypeScript 中获得类型提示后者类型声明为传递到客户端的GlobalContext字段。首页 pages/index/Page.jsx 中直接打印了pageContext.globalContext.someEnvVar与process.env.NODE_ENV可用于验证上述两条链路是否生效。配置钩子passToClient序列化边界全局配置 pages/config.jsconst config { passToClient: [someEnvVar], }passToClient声明了哪些globalContext字段会被序列化并随页面下发到客户端使浏览器端的pageContext.globalContext也能访问someEnvVar。这与onCreateGlobalContext.server.ts中把someEnvVar声明到GlobalContext而非仅GlobalContextServer类型里是配套的服务端全局上下文默认只存在于服务端只有显式passToClient的字段才会跨到客户端。自定义 React 集成渲染钩子由于本示例不使用vike-reactReact 的 SSR 与 hydration 通过两个 Vike 钩子手动接线。服务端renderer/onRenderHtml.jsximport ReactDOMServer from react-dom/server import { escapeInject, dangerouslySkipEscape } from vike/server import { Layout } from ./Layout function onRenderHtml(pageContext) { const { Page } pageContext const pageHtml ReactDOMServer.renderToString( Layout Page pageContext{pageContext} / /Layout, ) return escapeInject!DOCTYPE html html body div idroot${dangerouslySkipEscape(pageHtml)}/div /body /html }说明pageContext.Page由 Vike 根据urlOriginal自动解析出当前路由对应的页面组件用ReactDOMServer.renderToString把LayoutPage//Layout序列化为 HTML 字符串用 Vike 的escapeInject模板构造最终 HTML${dangerouslySkipEscape(pageHtml)}明确标记这段 React 已序列化好的 HTML 无需再转义其余插值都会被自动 HTML 转义避免 XSS。客户端renderer/onRenderClient.jsximport { hydrateRoot } from react-dom/client async function onRenderClient(pageContext) { const { Page } pageContext hydrateRoot( document.getElementById(root), Layout Page pageContext{pageContext} / /Layout, ) }客户端用hydrateRoot对服务端输出的div idroot做 hydration使静态 HTML 变成交互式页面如首页的Counter组件。布局与页面结构示例采用 Vike 的文件约定路由pages/index/Page.jsx对应根路径pages/about/Page.jsx对应/aboutrenderer/Layout.jsx 提供侧边导航 内容区的公共布局并在React.StrictMode中渲染。首页还包含一个Counter组件用于演示 hydration 后的交互能力。小结本示例完整展示了 Vike 部署到 Cloudflare Workers 的关键环节wrangler.jsonc指定 Worker 入口与 Assets 目录worker/ssr.js用renderPage一行核心代码完成 SSRvite.config.js将cloudflare:workers标记为外部模块onCreateGlobalContext钩子用getPlatformProxy与cloudflare:workers双分支读取平台变量passToClient控制服务端到客户端的数据边界onRenderHtml/onRenderClient钩子则以escapeInjecthydrateRoot完成自定义 React 集成。对于新项目官方仍建议通过 Bati 脚手架并搭配vike-react起步本示例的价值在于演示底层接线方式便于在需要完全控制渲染逻辑或对接 Workers 特有绑定时做参照。【免费下载链接】vike(Replaces Next.js/Nuxt) Build mission-critical applications with stability and development freedom.项目地址: https://gitcode.com/GitHub_Trending/vi/vike创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考