跳转到内容

@astrojs/ cloudflare

此适配器允许 Astro 将你的hybrid 或者 server 渲染站点部署到Cloudflare.

如果你使用 Astro 作为静态站点构建器,则不需要适配器。

在我们的 Cloudflare Pages部署指南 中了解如何部署Astro站点。

为什么选择 Astro Cloudflare

段落标题 为什么选择 Astro Cloudflare

Cloudflare提供 CDN、网络安全和其他服务。该适配器增强了 Astro 构建过程,为你的项目通过 Cloudflare 进行部署做好准备。

Astro 包含了一个 astro add 命令,用于自动设置官方集成。如果你愿意,可以改为手动安装集成

在你的 Astro 项目中使用 astro add 命令添加 Cloudflare 适配器,以启用SSR。这将安装@astrojs/cloudflare 并一步到位地对你的 astro.config.mjs 文件进行相应的更改。

Terminal window
npx astro add cloudflare

首先,使用合适的包管理器将 @astrojs/cloudflare 适配器添加到项目的依赖项中。

Terminal window
npm install @astrojs/cloudflare

然后,将适配器和所需的按需渲染模式添加到 astro.config.mjs 文件中:

astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare(),
});

类型: 'advanced' | 'directory'
默认值: 'advanced'

这个配置选项定义了你的 Astro 项目如何部署到 Cloudflare Pages。

  • advanced 模式会获取 dist 文件夹中的 _worker.js 文件。
  • directory 模式会获取 functions 文件夹中的文件,默认只会生成一个 [[path]].js 文件。

切换到 directory 模式允许你手动添加额外的文件例如 Cloudflare Pages 插件Cloudflare Pages 中间件 甚至使用了 Cloudflare Pages 函数路由 的自定义函数。

astro.config.mjs
export default defineConfig({
adapter: cloudflare({ mode: 'directory' }),
});

要为每个页面编译单独的包,请在你的 Cloudflare 适配器配置中设置 functionPerRoute 选项。该选项需要手动维护 functions 文件夹。Astro 生成的文件将覆盖 functions 文件夹中具有相同名称的现有文件,因此你必须为手动添加的每个文件选择唯一的文件名。此外,适配器永远不会清空 functions 文件夹中过时的文件,因此当你删除页面时,你必须手动清理文件夹。

astro.config.mjs
import {defineConfig} from "astro/config";
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
adapter: cloudflare({
mode: 'directory',
functionPerRoute: true
})
})

该适配器不支持 edgeMiddleware 选项。

类型: 'auto' | 'include' | 'exclude'
默认值: 'auto'

在没有提供自定义 _routes.json 的情况下决定 routes.json 该如何被生成。

这有三个选项可供选择:

  • "auto"(默认):自动选择生成最少条目的策略。这通常应该够用了,除非你有某些理由要选择其他选项。

  • include:不会被预渲染的页面和端点将会被列为 include 条目,并告诉 Cloudflare 将这些路由作为函数调用。而 exclude 条目仅用于解决冲突。通常情况下,如果你的网站大多数是静态页面,只有少数动态页面或端点时,这将是最好的策略。

    示例:对于 src/pages/index.astro(静态),src/pages/company.astro(静态),src/pages/users/faq.astro(静态),以及 /src/pages/users/[id].astro (SSR),将产生以下 _routes.json:

    dist/_routes.json
    {
    "version": 1,
    "include": [
    "/_image", // Astro 的图片端点
    "/users/*" // 动态路由
    ],
    "exclude": [
    // 排除上述动态通配符路由中后的静态路由
    "/users/faq/",
    "/users/faq/index.html"
    ]
    }
  • exclude 预渲染的页面将被列为 exclude 条目(即告诉 Cloudflare 将这些路由作为静态资源处理)。通常情况下,如果你的网站大多数是动态页面或端点,只有少数静态页面时,这将是最好的策略。

    示例:对于前面示例中相同的页面,这将产生以下 _routes.json:

    dist/_routes.json
    {
    "version": 1,
    "include": [
    "/*" // 除了后面的路由外,所有路由都会被作为函数处理
    ],
    "exclude": [
    // 所有静态资源
    "/",
    "/company/",
    "/index.html",
    "/users/faq/",
    "/favicon.png",
    "/company/index.html",
    "/users/faq/index.html"
    ]
    }

类型: string[]
默认值: []

如果你想使用自动生成的 _routes.json,但又想要包含额外的路由(例如,当你在 functions 文件夹中有自定义函数时),那么你可以使用 routes.include 选项将额外的路由添加到 include 数组中。

类型: string[]
默认值: []

如果你想要使用自动生成的 _routes.json,但又想要排除其他的路由,那么你可以使用 routes.exclude 选项将额外的路由到添加 exclude 数组中。

以下示例自动生成了 _routes.json,同时包含和排除额外的路由。请注意,如果你在 functions 文件夹中有自定义函数,那么这些函数将不会被 Astro 处理。

astro.config.mjs
export default defineConfig({
adapter: cloudflare({
mode: 'directory',
routes: {
strategy: 'include',
include: ['/users/*'], // 由自定义函数处理: functions/users/[id].js
exclude: ['/users/faq'], // 由静态页面处理: pages/users/faq.astro
},
}),
});

类型: 'passthrough' | 'cloudflare'
默认值: 'passthrough'

控制适配器使用哪个图像服务。当配置了不兼容的图像服务时,适配器将默认到 passthrough 模式。否则,它将使用全局配置的图像服务:

类型: true | false
默认值: false

是否将 .wasm 文件直接作为 ES 模块导入。

wasmModuleImports: true 添加到 astro.config.mjs 以在 Cloudflare 构建和 Astro 开发服务器中启用该功能。

astro.config.mjs
// astro.config.mjs
import {defineConfig} from "astro/config";
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
adapter: cloudflare({
wasmModuleImports: true
}),
output: 'server'
})

类型:

{ mode: 'off' }
| { mode: 'local'; type: 'pages'; persistTo?: string; bindings?: Record<string, CF_BINDING> }
| { mode: 'local'; type: 'workers'; persistTo?: string; };

(CF_BINDING 类型参考)
默认值: { mode: 'off', persistTo: '' }

决定是否以及如何将 Cloudflare Runtime 添加到 astro dev。请阅读更多有关 Cloudflare Runtime 的信息。

type 属性定义了你的 Astro 项目将部署到哪:

mode 属性则定义了你希望运行时在 astro dev 中支持什么:

  • off:使用 astro dev 时无法访问运行时。当你需要访问运行时来模拟本地的生产环境时,可以选择使用 Wrangler 预览
  • local:使用由 miniflare 和 workerd 驱动的本地运行时,它支持 Cloudflare 绑定。只有当你想使用不支持的功能,如 eval,或没有本地支持的绑定时,才选择使用 Wrangler 预览

mode: local 中,你可以访问 persistTo 属性,它定义了本地绑定状态保存的位置。这避免了每次重启开发服务器时都刷新绑定。这个值是相对于你执行 astro dev 的路径的一个目录。默认情况下它被设置为 .wrangler/state/v3,以允许使用 wrangler 命令行工具(例如用于迁移)。将这个路径会添加到你的 .gitignore 中。

Cloudflare 运行时让你能够访问环境变量和 Cloudflare 绑定。你可以在 Cloudflare 的 WorkersPages 文档中找到更多信息。根据你的部署类型(pagesworkers),你需要以不同的方式配置绑定。

目前支持的绑定有:

Cloudflare Pages 不支持配置文件。

要将你的 pages 项目部署到生产环境,你需要使用 Cloudflare 的仪表盘来配置绑定。要在本地访问绑定,你需要使用适配器的 runtime 选项来配置它们。

astro.config.mjs
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare({
runtime: {
mode: 'local',
type: 'pages',
bindings: {
// 一个变量绑定的例子(环境变量)
"URL": {
type: "var",
value: "https://example.com",
},
// 一个 KV 绑定的例子
"KV": {
type: "kv",
},
// 一个 D1 绑定的例子
"D1": {
type: "d1",
},
// 一个 R2 绑定的例子
"R2": {
type: "r2",
},
// 一个 Durable Object 绑定的例子
"DO": {
type: "durable-object",
className: "DO",
},
},
},
}),
});

如果你还需要定义 secrets 以外的环境变量,你需要在 Astro 项目的根目录下添加一个 .dev.vars 文件:

.dev.vars
DB_PASSWORD=myPassword

如果你想使用 wrangler 进行命令行操作,比如 D1 迁移,你还需要在 Astro 项目的根目录下添加一个包含正确内容的 wrangler.toml 文件。请查阅Cloudflare 的文档以获取更多详细信息。

wrangler.toml
name = "example"
compatibility_date = "2023-06-14"
# example for D1 Binding
[[d1_databases]]
binding = "D1"
database_name = "D1"
database_id = "D1"
preview_database_id = "D1"

要将你的 workers 项目部署到生产环境,你需要在你的 Astro 项目的根目录中使用 wrangler.toml 配置文件来配置绑定。为了能够在本地访问绑定,@astrojs/cloudflare 适配器也会 wrangler.toml 从文件读取配置。

wrangler.toml
name = "example"
# 一个 KV 绑定的例子
kv_namespaces = [
{ binding = "KV", id = "KV", preview_id = "KV" },
]
# 一个变量绑定的例子(环境变量)
[vars]
URL = "example.com"
# 一个 D1 绑定的例子
[[d1_databases]]
binding = "D1"
database_name = "D1"
database_id = "D1"
preview_database_id = "D1"
# 一个 R2 绑定的例子
[[r2_buckets]]
binding = 'R2'
bucket_name = 'R2'
# 一个 Durable Object 绑定的例子
[[durable_objects.bindings]]
name = "DO"
class_name = "DO"

如果你还需要定义 secrets 以外的环境变量,你需要在 Astro 项目的根目录下添加一个 .dev.vars 文件:

.dev.vars
DB_PASSWORD=myPassword

在任意 .astro 文件中,你都可以直接通过 Astro.locals 从 Astro 组件中访问运行时:

src/pages/index.astro
---
const runtime = Astro.locals.runtime;
---
<pre>{JSON.stringify(runtime.env)}</pre>

你也可以通过 context.locals 从 API 端点访问运行时:

src/pages/api/someFile.js
export function GET(context) {
const runtime = context.locals.runtime;
return new Response('Some body');
}

如果你正在使用 advanced 运行时,那么你可以按以下方式声明 runtime 对象:

如果你已经配置了 mode:advanced,你可以使用 AdvancedRuntime 来为 runtime 对象添加类型:

src/env.d.ts
/// <reference types="astro/client" />
type KVNamespace = import('@cloudflare/workers-types/experimental').KVNamespace;
type ENV = {
SERVER_URL: string;
KV_BINDING: KVNamespace;
};
type Runtime = import('@astrojs/cloudflare').AdvancedRuntime<ENV>;
declare namespace App {
interface Locals extends Runtime {
user: {
name: string;
surname: string;
};
}
}

如果你已经配置了 mode: directory,你可以使用 DirectoryRuntime 来为 runtime 对象添加类型:

src/env.d.ts
/// <reference types="astro/client" />
type KVNamespace = import('@cloudflare/workers-types/experimental').KVNamespace;
type ENV = {
SERVER_URL: string;
KV_BINDING: KVNamespace;
};
type Runtime = import('@astrojs/cloudflare').DirectoryRuntime<ENV>;
declare namespace App {
interface Locals extends Runtime {
user: {
name: string;
surname: string;
};
}
}

你可以通过在 Astro 项目的 public/ 文件夹中添加一个 _headers 文件来附加 自定义头部 到你的响应中,该文件将被复制到构建输出目录中。

你可以使用 Cloudflare Pages 来声明 自定义重定向。这允许你将请求重定向到不同的 URL。你可以在 Astro 项目的 public/ 文件夹中添加一个 _redirects 文件,该文件将被复制到构建输出目录。

你可以使用 Cloudflare 路由 通过 _routes.json 文件来定义哪些路由会调用函数,哪些路由是静态资源。该文件由 Astro 自动生成。

默认情况下,@astrojs/cloudflare 会基于你应用的动态和静态路由生成一个 _routes.json 文件,当中包含了 includeexclude 规则。

这将使 Cloudflare 能够在没有函数调用的情况下提供文件和处理静态重定向。创建自定义的 _routes.json 将覆盖此自带的优化文件。参阅 Cloudflare 关于创建自定义 routes.json 的文档 了解更多细节。

以下是导入一个 Wasm 模块的示例,该模块通过将请求的数字参数相加来响应请求:

pages/add/[a]/[b].js
import mod from '../util/add.wasm?module';
// 预先初始化以共享同一个模块
const addModule: any = new WebAssembly.Instance(mod);
export async function GET(context) {
const a = Number.parseInt(context.params.a);
const b = Number.parseInt(context.params.b);
return new Response(`${addModule.exports.add(a, b)}`);
}

虽然这个例子很简单,但是 Wasm 可以用来加速在不涉及大量 I/O 的情况下的计算密集型操作,比如嵌入图像处理库。

Astro 的 Cloudflare 适配器允许你使用任何 Cloudflare 支持的 Node.js 运行时 API,例如:

  • assert
  • AsyncLocalStorage
  • Buffer
  • Crypto
  • Diagnostics Channel
  • EventEmitter
  • path
  • process
  • Streams
  • StringDecoder
  • util

如果要使用这些 API,你的页面或端点必须是服务器渲染的(而不是预渲染的),并使用 import {} from 'node:*' 导入语法。

pages/api/endpoint.js
export const prerender = false;
import { Buffer } from 'node:buffer';

另外,你需要在 Cloudflare 中启用兼容性标志。该标志的配置方法取决于你部署 Astro 站点的方式。更多详细指导,请参阅 启用 Node.js 兼容性的 Cloudflare 文档

所有 Cloudflare 的命名空间包(例如 cloudflare:sockets)都允许使用。但请注意,cloudflare:sockets 包在本地环境中需要使用 Wrangler 的开发模式才能正常工作。

为了使用 wrangler 在本地运行你的应用程序,请更新预览脚本:

package.json
"preview": "wrangler pages dev ./dist"

wrangler 能让你访问 Cloudflare 绑定环境变量cf 对象。要让热重载或 Astro 开发服务器与 Wrangler 工作,可能需要进行自定义设置。请参阅 社区示例

目前,在 Wrangler 中运行应用程序时由于代码被压缩,错误消息并不是很有用。为了更好地进行调试,你可以将 vite.build.minify = false 添加到你的 astro.config.js 文件中。

astro.config.mjs
export default defineConfig({
adapter: cloudflare(),
output: 'server',
vite: {
build: {
minify: false,
},
},
});

更多集成

UI 框架

SSR 适配器

其他集成