Skip to content

Commit ae8225d

Browse files
jrf0110Rich-Harris
andauthored
feat: Cloudflare Pages _routes.json specification (#6441) (#6530)
* feat: Cloudflare Pages _routes.json specification (#6441) When a SvelteKit project is deployed to Cloudflare Pages, the server-side code is supported through Pages Functions (currently in beta). Unfortunately, by using Functions, each request must go through the server-side Functions code even if it doesn't need to. For instance, an immutable asset request to https://kit.svelte.dev/_app/immutable/assets/_layout-ab34ca4f.css would first have to route through Functions. This is problematic since the request would "count" as a request to Functions even though only a static asset was served. Further, there is a slight amount of added latency. This change exposes a set of includes and excludes based on static files generated. * use writeFileSync over writeFile, for consistency with rest of codebase * code style stuff * tweak changeset Co-authored-by: Rich Harris <[email protected]>
1 parent afba48c commit ae8225d

File tree

3 files changed

+64
-4
lines changed

3 files changed

+64
-4
lines changed

.changeset/afraid-gifts-act.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@sveltejs/adapter-cloudflare': patch
3+
'@sveltejs/kit': patch
4+
---
5+
6+
Support Cloudflare Pages `_routes.json` specification

packages/adapter-cloudflare/index.d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,10 @@ import { Adapter } from '@sveltejs/kit';
22
import './ambient.js';
33

44
export default function plugin(): Adapter;
5+
6+
export interface RoutesJSONSpec {
7+
version: 1;
8+
description: string;
9+
include: string[];
10+
exclude: string[];
11+
}

packages/adapter-cloudflare/index.js

+51-4
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,28 @@ export default function () {
2323
builder.rimraf(tmp);
2424
builder.mkdirp(tmp);
2525

26-
builder.writeClient(dest);
26+
const written_files = builder.writeClient(dest);
2727
builder.writePrerendered(dest);
2828

2929
const relativePath = posix.relative(tmp, builder.getServerDirectory());
3030

31+
builder.log.info(
32+
`adapter-cloudfare is writing its own _headers file. If you have your own, you should duplicate the headers contained in: ${dest}/_headers`
33+
);
34+
3135
writeFileSync(
3236
`${tmp}/manifest.js`,
33-
`export const manifest = ${builder.generateManifest({
34-
relativePath
35-
})};\n\nexport const prerendered = new Set(${JSON.stringify(builder.prerendered.paths)});\n`
37+
`export const manifest = ${builder.generateManifest({ relativePath })};\n\n` +
38+
`export const prerendered = new Set(${JSON.stringify(builder.prerendered.paths)});\n`
39+
);
40+
41+
writeFileSync(
42+
`${dest}/_routes.json`,
43+
JSON.stringify(get_routes_json(builder.config.kit.appDir, written_files))
3644
);
3745

46+
writeFileSync(`${dest}/_headers`, generate_headers(builder.config.kit.appDir));
47+
3848
builder.copy(`${files}/worker.js`, `${tmp}/_worker.js`, {
3949
replace: {
4050
SERVER: `${relativePath}/index.js`,
@@ -55,3 +65,40 @@ export default function () {
5565
}
5666
};
5767
}
68+
69+
/**
70+
* @param {string} app_dir
71+
* @param {string[]} assets
72+
* @returns {import('.').RoutesJSONSpec}
73+
*/
74+
function get_routes_json(app_dir, assets) {
75+
return {
76+
version: 1,
77+
description: 'Generated by @sveltejs/adapter-cloudflare',
78+
include: ['/*'],
79+
exclude: [
80+
`/${app_dir}/immutable/*`,
81+
...assets
82+
// We're being conservative by not excluding all assets in
83+
// /static just yet. If there are any upstream auth rules to
84+
// protect certain things (e.g. a PDF that requires auth),
85+
// then we wouldn't want to prevent those requests from going
86+
// to the user functions worker.
87+
// We do want to show an example of a _routes.json that
88+
// excludes more than just /_app/immutable/*, and favicons
89+
// are a reasonable choice
90+
.filter((filePath) => filePath.includes('favicon'))
91+
]
92+
};
93+
}
94+
95+
/** @param {string} app_dir */
96+
function generate_headers(app_dir) {
97+
return `
98+
# === START AUTOGENERATED SVELTE IMMUTABLE HEADERS ===
99+
/${app_dir}/immutable/*
100+
Cache-Control: public, immutable, max-age=31536000
101+
X-Robots-Tag: noindex
102+
# === END AUTOGENERATED SVELTE IMMUTABLE HEADERS ===
103+
`.trim();
104+
}

0 commit comments

Comments
 (0)