cloudflare-pages

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Cloudflare Pages

Cloudflare Pages

Deploy frontend projects with preview builds, edge functions, and global CDN delivery on Cloudflare's network.
在Cloudflare网络上部署前端项目,支持预览构建、边缘函数和全球CDN分发。

When to Use

使用场景

  • Deploying static sites (React, Vue, Astro, Hugo, Next.js static export).
  • Full-stack applications using Pages Functions for server-side logic.
  • Projects that need automatic preview deployments per pull request.
  • Teams that want zero-config CDN with custom domain and TLS.
  • Migrating from Vercel, Netlify, or GitHub Pages to Cloudflare's ecosystem.
  • 部署静态站点(React、Vue、Astro、Hugo、Next.js静态导出)。
  • 使用Pages Functions实现服务端逻辑的全栈应用。
  • 需要为每个拉取请求自动部署预览版本的项目。
  • 想要零配置CDN、自定义域名及TLS支持的团队。
  • 从Vercel、Netlify或GitHub Pages迁移至Cloudflare生态系统的场景。

Prerequisites

前置条件

  • Node.js 18+ and npm installed locally.
  • A Cloudflare account (free tier works for most projects).
  • Wrangler CLI installed:
    npm install -g wrangler
    .
  • Authenticated via
    wrangler login
    or
    CLOUDFLARE_API_TOKEN
    environment variable.
  • Source code in a Git repository (GitHub or GitLab for dashboard integration).
  • 本地安装Node.js 18+及npm。
  • 拥有Cloudflare账户(免费套餐适用于大多数项目)。
  • 安装Wrangler CLI:
    npm install -g wrangler
  • 通过
    wrangler login
    CLOUDFLARE_API_TOKEN
    环境变量完成身份验证。
  • 源代码存储在Git仓库中(如需控制台集成,需使用GitHub或GitLab)。

Project Setup via Wrangler

通过Wrangler配置项目

Create a New Project

创建新项目

bash
undefined
bash
undefined

Create a new Pages project

创建新的Pages项目

npx wrangler pages project create my-site
npx wrangler pages project create my-site

List existing projects

列出已有项目

npx wrangler pages project list
npx wrangler pages project list

Delete a project (removes all deployments)

删除项目(会移除所有部署)

npx wrangler pages project delete my-site
undefined
npx wrangler pages project delete my-site
undefined

Deploy from Local Build Output

从本地构建产物部署

bash
undefined
bash
undefined

Build your framework first

先构建你的框架项目

npm run build
npm run build

Deploy the output directory

部署输出目录

npx wrangler pages deploy dist --project-name=my-site
npx wrangler pages deploy dist --project-name=my-site

Deploy with a custom branch name (triggers preview URL)

使用自定义分支名称部署(触发预览URL)

npx wrangler pages deploy dist --project-name=my-site --branch=feature-auth
npx wrangler pages deploy dist --project-name=my-site --branch=feature-auth

Deploy and get the deployment URL in JSON

部署并以JSON格式获取部署URL

npx wrangler pages deploy dist --project-name=my-site --branch=main 2>&1 | tail -1
undefined
npx wrangler pages deploy dist --project-name=my-site --branch=main 2>&1 | tail -1
undefined

List and Manage Deployments

列出并管理部署

bash
undefined
bash
undefined

List recent deployments

列出近期部署

npx wrangler pages deployment list --project-name=my-site
npx wrangler pages deployment list --project-name=my-site

Tail live logs from a deployment

实时查看部署日志

npx wrangler pages deployment tail --project-name=my-site --environment=production
undefined
npx wrangler pages deployment tail --project-name=my-site --environment=production
undefined

Dashboard Git Integration

控制台Git集成

  1. Navigate to Workers & Pages > Create application > Pages.
  2. Connect your GitHub or GitLab account.
  3. Select the repository and configure:
    • Production branch:
      main
    • Build command:
      npm run build
    • Build output directory:
      dist
      (or
      build
      ,
      .next
      ,
      public
      depending on framework)
  4. Set environment variables per environment (Production vs Preview).
  1. 前往Workers & Pages > 创建应用 > Pages
  2. 连接你的GitHub或GitLab账户。
  3. 选择仓库并配置:
    • 生产分支
      main
    • 构建命令
      npm run build
    • 构建输出目录
      dist
      (根据框架不同,也可设置为
      build
      .next
      public
  4. 为不同环境(生产/预览)设置环境变量。

Framework Presets

框架预设

Cloudflare auto-detects frameworks. Override if needed:
FrameworkBuild CommandOutput Directory
React CRA
npm run build
build
Vite
npm run build
dist
Next.js
npx @cloudflare/next-on-pages
.vercel/output/static
Astro
npm run build
dist
Hugo
hugo
public
SvelteKit
npm run build
.svelte-kit/cloudflare
Cloudflare会自动检测框架,如有需要可手动覆盖:
FrameworkBuild CommandOutput Directory
React CRA
npm run build
build
Vite
npm run build
dist
Next.js
npx @cloudflare/next-on-pages
.vercel/output/static
Astro
npm run build
dist
Hugo
hugo
public
SvelteKit
npm run build
.svelte-kit/cloudflare

Preview Deployments

预览部署

Every non-production branch gets a unique preview URL automatically.
undefined
每个非生产分支都会自动生成一个唯一的预览URL。
undefined

URL format for preview deployments

预览部署的URL格式

https://<commit-hash>.<project-name>.pages.dev https://<branch-name>.<project-name>.pages.dev
undefined
https://<commit-hash>.<project-name>.pages.dev https://<branch-name>.<project-name>.pages.dev
undefined

Branch-Based Access Control

基于分支的访问控制

bash
undefined
bash
undefined

Set preview branch patterns in wrangler.toml (Pages-specific)

在wrangler.toml中设置预览分支规则(Pages专属)

Or configure via dashboard: Settings > Builds & deployments

或通过控制台配置:设置 > 构建与部署

Include branches: feature/*, staging

包含分支:feature/*、staging

Exclude branches: dependabot/*

排除分支:dependabot/*

undefined
undefined

Preview Comment on Pull Requests

拉取请求的预览评论

Enable the Cloudflare Pages GitHub App to post deployment URLs as PR comments. Configure under Settings > Builds & deployments > Preview comment.
启用Cloudflare Pages GitHub应用,即可将部署URL作为PR评论发布。可在设置 > 构建与部署 > 预览评论中配置。

Pages Functions

Pages Functions

Pages Functions provide server-side logic deployed alongside your static site. Place files in a
functions/
directory at the project root.
Pages Functions可提供与静态站点一同部署的服务端逻辑。需将文件放置在项目根目录的
functions/
文件夹中。

Basic API Route

基础API路由

typescript
// functions/api/hello.ts
export const onRequestGet: PagesFunction = async (context) => {
  return new Response(JSON.stringify({ message: "Hello from the edge" }), {
    headers: { "Content-Type": "application/json" },
  });
};

// functions/api/users/[id].ts — dynamic route parameter
export const onRequestGet: PagesFunction = async (context) => {
  const userId = context.params.id;
  return new Response(JSON.stringify({ userId }), {
    headers: { "Content-Type": "application/json" },
  });
};
typescript
// functions/api/hello.ts
export const onRequestGet: PagesFunction = async (context) => {
  return new Response(JSON.stringify({ message: "Hello from the edge" }), {
    headers: { "Content-Type": "application/json" },
  });
};

// functions/api/users/[id].ts — 动态路由参数
export const onRequestGet: PagesFunction = async (context) => {
  const userId = context.params.id;
  return new Response(JSON.stringify({ userId }), {
    headers: { "Content-Type": "application/json" },
  });
};

Middleware

中间件

typescript
// functions/_middleware.ts — runs before all routes
export const onRequest: PagesFunction = async (context) => {
  const authHeader = context.request.headers.get("Authorization");
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return new Response("Unauthorized", { status: 401 });
  }
  return context.next();
};
typescript
// functions/_middleware.ts — 在所有路由前执行
export const onRequest: PagesFunction = async (context) => {
  const authHeader = context.request.headers.get("Authorization");
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return new Response("Unauthorized", { status: 401 });
  }
  return context.next();
};

Functions with Bindings

绑定资源的Functions

typescript
// functions/api/data.ts — using KV and D1 bindings
interface Env {
  MY_KV: KVNamespace;
  MY_DB: D1Database;
  MY_BUCKET: R2Bucket;
}

export const onRequestGet: PagesFunction<Env> = async (context) => {
  // Read from KV
  const cached = await context.env.MY_KV.get("key");
  if (cached) return new Response(cached);

  // Query D1
  const result = await context.env.MY_DB.prepare(
    "SELECT * FROM items LIMIT 10"
  ).all();

  // Cache in KV
  await context.env.MY_KV.put("key", JSON.stringify(result.results), {
    expirationTtl: 300,
  });

  return Response.json(result.results);
};
typescript
// functions/api/data.ts — 使用KV和D1绑定
interface Env {
  MY_KV: KVNamespace;
  MY_DB: D1Database;
  MY_BUCKET: R2Bucket;
}

export const onRequestGet: PagesFunction<Env> = async (context) => {
  // 从KV读取数据
  const cached = await context.env.MY_KV.get("key");
  if (cached) return new Response(cached);

  // 查询D1数据库
  const result = await context.env.MY_DB.prepare(
    "SELECT * FROM items LIMIT 10"
  ).all();

  // 在KV中缓存数据
  await context.env.MY_KV.put("key", JSON.stringify(result.results), {
    expirationTtl: 300,
  });

  return Response.json(result.results);
};

Wrangler Configuration

Wrangler配置

toml
undefined
toml
undefined

wrangler.toml — Pages project configuration

wrangler.toml — Pages项目配置

name = "my-site" compatibility_date = "2024-09-01" pages_build_output_dir = "dist"
name = "my-site" compatibility_date = "2024-09-01" pages_build_output_dir = "dist"

KV namespace binding

KV命名空间绑定

[[kv_namespaces]] binding = "MY_KV" id = "abc123def456"
[[kv_namespaces]] binding = "MY_KV" id = "abc123def456"

D1 database binding

D1数据库绑定

[[d1_databases]] binding = "MY_DB" database_name = "my-app-db" database_id = "xxxx-yyyy-zzzz"
[[d1_databases]] binding = "MY_DB" database_name = "my-app-db" database_id = "xxxx-yyyy-zzzz"

R2 bucket binding

R2存储桶绑定

[[r2_buckets]] binding = "MY_BUCKET" bucket_name = "app-assets"
[[r2_buckets]] binding = "MY_BUCKET" bucket_name = "app-assets"

Environment variables

环境变量

[vars] API_BASE_URL = "https://api.example.com"
undefined
[vars] API_BASE_URL = "https://api.example.com"
undefined

Headers and Redirects

自定义头部与重定向

Custom Headers

自定义头部

undefined
undefined

public/_headers

public/_headers

/assets/* Cache-Control: public, max-age=31536000, immutable
/* X-Frame-Options: DENY X-Content-Type-Options: nosniff Referrer-Policy: strict-origin-when-cross-origin Permissions-Policy: camera=(), microphone=(), geolocation=() Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'
/api/* Access-Control-Allow-Origin: https://example.com Access-Control-Allow-Methods: GET, POST, OPTIONS
undefined
/assets/* Cache-Control: public, max-age=31536000, immutable
/* X-Frame-Options: DENY X-Content-Type-Options: nosniff Referrer-Policy: strict-origin-when-cross-origin Permissions-Policy: camera=(), microphone=(), geolocation=() Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'
/api/* Access-Control-Allow-Origin: https://example.com Access-Control-Allow-Methods: GET, POST, OPTIONS
undefined

Redirects

重定向

undefined
undefined

public/_redirects

public/_redirects

/old-page /new-page 301 /blog/:slug /posts/:slug 301 /docs/* https://docs.example.com/:splat 302 /home / 302
undefined
/old-page /new-page 301 /blog/:slug /posts/:slug 301 /docs/* https://docs.example.com/:splat 302 /home / 302
undefined

Custom Domains

自定义域名

bash
undefined
bash
undefined

Add a custom domain via Cloudflare dashboard:

通过Cloudflare控制台添加自定义域名:

Pages project > Custom domains > Set up a custom domain

Pages项目 > 自定义域名 > 设置自定义域名

Or via API

或通过API添加

curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/my-site/domains"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{"name":"www.example.com"}'
undefined
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/my-site/domains"
-H "Authorization: Bearer $CF_API_TOKEN"
-H "Content-Type: application/json"
-d '{"name":"www.example.com"}'
undefined

CI/CD Integration

CI/CD集成

GitHub Actions

GitHub Actions

yaml
undefined
yaml
undefined

.github/workflows/deploy.yml

.github/workflows/deploy.yml

name: Deploy to Cloudflare Pages on: push: branches: [main] pull_request:
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm - run: npm ci - run: npm run build - uses: cloudflare/wrangler-action@v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: pages deploy dist --project-name=my-site
undefined
name: Deploy to Cloudflare Pages on: push: branches: [main] pull_request:
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm - run: npm ci - run: npm run build - uses: cloudflare/wrangler-action@v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: pages deploy dist --project-name=my-site
undefined

Troubleshooting

故障排查

SymptomCauseFix
Build fails with out-of-memoryBuild exceeds 1 GB RAM limitReduce dependencies; use
NODE_OPTIONS=--max_old_space_size=768
Functions return 404
functions/
directory not at project root
Move
functions/
to repo root, not inside
src/
Preview URL shows old contentBrowser cache or stale deploymentHard refresh; check deployment list for latest commit hash
Custom domain shows SSL errorDNS not proxied through CloudflareEnable orange cloud (proxy) on the CNAME record
_headers
file ignored
File not in build output directoryPlace in
public/
so it copies to
dist/
during build
Bindings undefined in FunctionsMissing
wrangler.toml
or dashboard config
Add bindings in
wrangler.toml
and redeploy
1 MB function size limit exceededToo many dependencies bundledTree-shake; move large deps to KV or R2
症状原因解决方法
构建因内存不足失败构建超出1GB内存限制减少依赖;使用
NODE_OPTIONS=--max_old_space_size=768
Functions返回404
functions/
目录不在项目根目录
functions/
移至仓库根目录,而非
src/
预览URL显示旧内容浏览器缓存或部署版本过期强制刷新;查看部署列表确认最新提交哈希
自定义域名显示SSL错误DNS未通过Cloudflare代理在CNAME记录上启用橙色云(代理)
_headers
文件未生效
文件不在构建输出目录中将其放置在
public/
目录,以便构建时复制到
dist/
Functions中绑定资源未定义
wrangler.toml
或控制台配置缺失
wrangler.toml
中添加绑定并重新部署
超出1MB函数大小限制打包了过多依赖摇树优化;将大型依赖移至KV或R2

Related Skills

相关技能

  • cloudflare-workers - Edge backend logic and API routes
  • cloudflare-r2 - Object storage for assets and uploads
  • cloudflare-zero-trust - Protect preview deployments with Access policies
  • cdn-setup - General CDN configuration patterns
  • cloudflare-workers - 边缘后端逻辑与API路由
  • cloudflare-r2 - 用于资源与上传的对象存储
  • cloudflare-zero-trust - 使用访问策略保护预览部署
  • cdn-setup - 通用CDN配置模式