如果你同时配置了静态资源和 Worker 脚本,Cloudflare 会首先尝试提供与传入请求匹配的静态资源。有关资源匹配的更多信息,请参阅 HTML 处理文档。
如果未找到合适的静态资源,Cloudflare 会调用 Worker 脚本。
这样你可以轻松组合这两种功能,构建强大的应用(例如全栈应用、带 API 的单页应用(SPA)或静态站点生成(SSG)应用)。
你可以配置 assets.run_worker_first 设置,控制 Worker 脚本相对于静态资源服务的执行时机。这让你更精确地控制静态资源的提供方式,也可用于实现请求的「中间件」。
如果你需要在提供静态资源之前始终运行 Worker 脚本(例如记录请求、执行身份验证检查、使用 HTMLRewriter 或在提供前转换资源),将 run_worker_first 设置为 true:
{
"name": "my-worker",
// Set this to today's date
"compatibility_date": "2026-08-17",
"main": "./worker/index.ts",
"assets": {
"directory": "./dist/",
"binding": "ASSETS",
"run_worker_first": true
}
}name = "my-worker"
# Set this to today's date
compatibility_date = "2026-08-17"
main = "./worker/index.ts"
[assets]
directory = "./dist/"
binding = "ASSETS"
run_worker_first = trueimport { WorkerEntrypoint } from "cloudflare:workers";
export default class extends WorkerEntrypoint {
async fetch(request) {
// You can perform checks before fetching assets
const user = await checkIfRequestIsAuthenticated(request);
if (!user) {
return new Response("Unauthorized", { status: 401 });
}
// You can then just fetch the assets as normal, or you could pass in a custom Request object here if you wanted to fetch some other specific asset
const assetResponse = await this.env.ASSETS.fetch(request);
// You can return static asset response as-is, or you can transform them with something like HTMLRewriter
return new HTMLRewriter()
.on("#user", {
element(element) {
element.setInnerContent(JSON.stringify({ name: user.name }));
},
})
.transform(assetResponse);
}
}import { WorkerEntrypoint } from "cloudflare:workers";
export default class extends WorkerEntrypoint<Env> {
async fetch(request: Request) {
// You can perform checks before fetching assets
const user = await checkIfRequestIsAuthenticated(request);
if (!user) {
return new Response("Unauthorized", { status: 401 });
}
// You can then just fetch the assets as normal, or you could pass in a custom Request object here if you wanted to fetch some other specific asset
const assetResponse = await this.env.ASSETS.fetch(request);
// You can return static asset response as-is, or you can transform them with something like HTMLRewriter
return new HTMLRewriter()
.on("#user", {
element(element) {
element.setInnerContent(JSON.stringify({ name: user.name }));
},
})
.transform(assetResponse);
}
}你也可以使用路由模式数组配置选择性 Worker 优先路由,通常与 single-page-application 设置 配合使用。这样你可以仅对特定路由优先运行 Worker,其他请求则遵循默认的静态资源优先行为:
{
"name": "my-worker",
// Set this to today's date
"compatibility_date": "2026-08-17",
"main": "./worker/index.ts",
"assets": {
"directory": "./dist/",
"not_found_handling": "single-page-application",
"binding": "ASSETS",
"run_worker_first": ["/oauth/callback"]
}
}name = "my-worker"
# Set this to today's date
compatibility_date = "2026-08-17"
main = "./worker/index.ts"
[assets]
directory = "./dist/"
not_found_handling = "single-page-application"
binding = "ASSETS"
run_worker_first = [ "/oauth/callback" ]import { WorkerEntrypoint } from "cloudflare:workers";
export default class extends WorkerEntrypoint {
async fetch(request) {
// The only thing this Worker script does is handle an OAuth callback.
// All other requests either serve an asset that matches or serve the index.html fallback, without ever hitting this code.
const url = new URL(request.url);
const code = url.searchParams.get("code");
const state = url.searchParams.get("state");
const accessToken = await exchangeCodeForToken(code, state);
const sessionIdentifier = await storeTokenAndGenerateSession(accessToken);
// Redirect back to the index, but set a cookie that the front-end will use.
return new Response(null, {
headers: {
Location: "/",
"Set-Cookie": `session_token=${sessionIdentifier}; HttpOnly; Secure; SameSite=Lax; Path=/`,
},
});
}
}import { WorkerEntrypoint } from "cloudflare:workers";
export default class extends WorkerEntrypoint<Env> {
async fetch(request: Request) {
// The only thing this Worker script does is handle an OAuth callback.
// All other requests either serve an asset that matches or serve the index.html fallback, without ever hitting this code.
const url = new URL(request.url);
const code = url.searchParams.get("code");
const state = url.searchParams.get("state");
const accessToken = await exchangeCodeForToken(code, state);
const sessionIdentifier = await storeTokenAndGenerateSession(accessToken);
// Redirect back to the index, but set a cookie that the front-end will use.
return new Response(null, {
headers: {
Location: "/",
"Set-Cookie": `session_token=${sessionIdentifier}; HttpOnly; Secure; SameSite=Lax; Path=/`,
},
});
}
}