From d10cb7de83b1399f932eab067827c033278bf00e Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 23 May 2022 21:56:01 -0400 Subject: [PATCH 01/13] put build inside _app/build directory --- packages/kit/src/core/build/build_client.js | 6 ++++-- packages/kit/src/core/build/build_server.js | 2 +- packages/kit/src/core/build/build_service_worker.js | 2 +- packages/kit/src/core/build/index.js | 6 +++--- packages/kit/src/core/preview/index.js | 8 ++++++-- packages/kit/test/apps/basics/test/test.js | 10 ++++++++++ 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/packages/kit/src/core/build/build_client.js b/packages/kit/src/core/build/build_client.js index 1e7f23bc8cd5..17e602dd7d02 100644 --- a/packages/kit/src/core/build/build_client.js +++ b/packages/kit/src/core/build/build_client.js @@ -59,7 +59,7 @@ export async function build_client({ build: { cssCodeSplit: true, manifest: true, - outDir: client_out_dir, + outDir: `${client_out_dir}/build`, polyfillDynamicImport: false, rollupOptions: { input, @@ -95,7 +95,9 @@ export async function build_client({ const { chunks, assets } = await create_build(merged_config); /** @type {import('vite').Manifest} */ - const vite_manifest = JSON.parse(fs.readFileSync(`${client_out_dir}/manifest.json`, 'utf-8')); + const vite_manifest = JSON.parse( + fs.readFileSync(`${client_out_dir}/build/manifest.json`, 'utf-8') + ); const entry = posixify(client_entry_file); const entry_js = new Set(); diff --git a/packages/kit/src/core/build/build_server.js b/packages/kit/src/core/build/build_server.js index 289abecf0cf2..97447465ac03 100644 --- a/packages/kit/src/core/build/build_server.js +++ b/packages/kit/src/core/build/build_server.js @@ -69,7 +69,7 @@ export class Server { manifest, method_override: ${s(config.kit.methodOverride)}, paths: { base, assets }, - prefix: assets + '/${config.kit.appDir}/', + prefix: assets + '/${config.kit.appDir}/build/', prerender: { default: ${config.kit.prerender.default}, enabled: ${config.kit.prerender.enabled} diff --git a/packages/kit/src/core/build/build_service_worker.js b/packages/kit/src/core/build/build_service_worker.js index e193242d665d..924ea08ae3e1 100644 --- a/packages/kit/src/core/build/build_service_worker.js +++ b/packages/kit/src/core/build/build_service_worker.js @@ -44,7 +44,7 @@ export async function build_service_worker( export const build = [ ${Array.from(build) - .map((file) => `${s(`${config.kit.paths.base}/${config.kit.appDir}/${file}`)}`) + .map((file) => `${s(`${config.kit.paths.base}/${config.kit.appDir}/build/${file}`)}`) .join(',\n\t\t\t\t')} ]; diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index 61def523cc7f..008cbd7a0475 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -34,7 +34,7 @@ export async function build(config, { log }) { // during `svelte-kit preview`, because we use a local asset path. If Vite // used relative paths, I _think_ this could get fixed. Issue here: // https://github.com/vitejs/vite/issues/2009 - assets_base: `${config.kit.paths.assets || config.kit.paths.base}/${config.kit.appDir}/`, + assets_base: `${config.kit.paths.assets || config.kit.paths.base}/${config.kit.appDir}/build/`, manifest_data, output_dir, client_entry_file: path.relative(cwd, `${get_runtime_path(config)}/client/start.js`), @@ -65,8 +65,8 @@ export async function build(config, { log }) { const files = new Set([ ...static_files, - ...client.chunks.map((chunk) => `${config.kit.appDir}/${chunk.fileName}`), - ...client.assets.map((chunk) => `${config.kit.appDir}/${chunk.fileName}`) + ...client.chunks.map((chunk) => `${config.kit.appDir}/build/${chunk.fileName}`), + ...client.assets.map((chunk) => `${config.kit.appDir}/build/${chunk.fileName}`) ]); // TODO is this right? diff --git a/packages/kit/src/core/preview/index.js b/packages/kit/src/core/preview/index.js index b931202f18df..f258942fc51a 100644 --- a/packages/kit/src/core/preview/index.js +++ b/packages/kit/src/core/preview/index.js @@ -66,8 +66,12 @@ export async function preview({ port, host, config, https: use_https = false }) scoped( assets, sirv(join(config.kit.outDir, 'output/client'), { - maxAge: 31536000, - immutable: true + setHeaders: (res, pathname) => { + // only apply to build directory, not e.g. version.json + if (pathname.startsWith(`/${config.kit.appDir}/build`)) { + res.setHeader('cache-control', 'public,max-age=31536000,immutable'); + } + } }) ), diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index ab76155f9833..b56b99cd7e83 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -2636,3 +2636,13 @@ test.describe.parallel('XSS', () => { ); }); }); + +test.describe.parallel('Version', () => { + test('does not serve version.json with an immutable cache header', async ({ request }) => { + // this isn't actually a great test, because caching behaviour is down to adapters. + // but it's better than nothing + const response = await request.get('/_app/version.json'); + const headers = response.headers(); + expect(headers['cache-control'] || '').not.toContain('immutable'); + }); +}); From 93ce1d37571be786383a6349cd59c47f3ce6633e Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 23 May 2022 22:02:32 -0400 Subject: [PATCH 02/13] use free variable for native fetch --- packages/kit/src/runtime/client/client.js | 10 +++++----- packages/kit/src/runtime/client/fetcher.js | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 9b8658f69492..c535ae42768c 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -11,7 +11,7 @@ import { notifiable_store, scroll_state } from './utils.js'; -import * as fetcher from './fetcher.js'; +import { increment, decrement, initial_fetch, native_fetch } from './fetcher.js'; import { parse } from './parse.js'; import Root from '__GENERATED__/root.svelte'; @@ -594,7 +594,7 @@ export function create_client({ target, session, base, trailing_slash }) { add_dependency(normalized); // prerendered pages may be served from any origin, so `initial_fetch` urls shouldn't be normalized - return started ? fetcher.native(normalized, init) : fetcher.initial(requested, init); + return started ? native_fetch(normalized, init) : initial_fetch(requested, init); }, status: status ?? null, error: error ?? null @@ -613,10 +613,10 @@ export function create_client({ target, session, base, trailing_slash }) { if (import.meta.env.DEV) { try { - fetcher.increment(); + increment(); loaded = await module.load.call(null, load_input); } finally { - fetcher.decrement(); + decrement(); } } else { loaded = await module.load.call(null, load_input); @@ -704,7 +704,7 @@ export function create_client({ target, session, base, trailing_slash }) { const is_shadow_page = has_shadow && i === a.length - 1; if (is_shadow_page) { - const res = await fetcher.native( + const res = await native_fetch( `${url.pathname}${url.pathname.endsWith('/') ? '' : '/'}__data.json${url.search}`, { headers: { diff --git a/packages/kit/src/runtime/client/fetcher.js b/packages/kit/src/runtime/client/fetcher.js index 05605964fb1d..9c5d2375a70a 100644 --- a/packages/kit/src/runtime/client/fetcher.js +++ b/packages/kit/src/runtime/client/fetcher.js @@ -2,7 +2,7 @@ import { hash } from '../hash.js'; let loading = 0; -export const native = window.fetch; +export const native_fetch = window.fetch; export function increment() { loading += 1; @@ -32,7 +32,8 @@ if (import.meta.env.DEV) { `Loading ${url} using \`window.fetch\`. For best results, use the \`fetch\` that is passed to your \`load\` function: https://kit.svelte.dev/docs/loading#input-fetch` ); } - return native(input, init); + + return native_fetch(input, init); }; } @@ -40,7 +41,7 @@ if (import.meta.env.DEV) { * @param {RequestInfo} resource * @param {RequestInit} [opts] */ -export function initial(resource, opts) { +export function initial_fetch(resource, opts) { const url = JSON.stringify(typeof resource === 'string' ? resource : resource.url); let selector = `script[sveltekit\\:data-type="data"][sveltekit\\:data-url=${url}]`; @@ -55,5 +56,5 @@ export function initial(resource, opts) { return Promise.resolve(new Response(body, init)); } - return native(resource, opts); + return native_fetch(resource, opts); } From 6a30552372dd401fb9b96467c79cae5b6c32637c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 23 May 2022 22:08:50 -0400 Subject: [PATCH 03/13] update test --- packages/kit/test/apps/basics/test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index b56b99cd7e83..6a25d2e767c3 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -347,7 +347,7 @@ test.describe.parallel('Imports', () => { ]); } else { expect(sources[0].startsWith('data:image/png;base64,')).toBeTruthy(); - expect(sources[1]).toBe(`${baseURL}/_app/assets/large-3183867c.jpg`); + expect(sources[1]).toBe(`${baseURL}/_app/build/assets/large-3183867c.jpg`); } }); }); From f28d823d5ebfb27c02438285500f4464fac90593 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 23 May 2022 22:18:56 -0400 Subject: [PATCH 04/13] only serve _app/build with immutable cache header, not _app/version.json - fixes #4837 --- .changeset/wise-berries-flash.md | 10 ++++++++ .../adapter-cloudflare-workers/files/entry.js | 2 +- packages/adapter-cloudflare/src/worker.js | 2 +- packages/adapter-netlify/src/edge.js | 3 ++- packages/adapter-node/src/handler.js | 23 +++++++++++-------- packages/adapter-vercel/index.js | 2 +- 6 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 .changeset/wise-berries-flash.md diff --git a/.changeset/wise-berries-flash.md b/.changeset/wise-berries-flash.md new file mode 100644 index 000000000000..0e72e7394437 --- /dev/null +++ b/.changeset/wise-berries-flash.md @@ -0,0 +1,10 @@ +--- +'@sveltejs/adapter-cloudflare': patch +'@sveltejs/adapter-cloudflare-workers': patch +'@sveltejs/adapter-netlify': patch +'@sveltejs/adapter-node': patch +'@sveltejs/adapter-vercel': patch +'@sveltejs/kit': patch +--- + +only serve \_app/build with immutable cache header, not \_app/version.json diff --git a/packages/adapter-cloudflare-workers/files/entry.js b/packages/adapter-cloudflare-workers/files/entry.js index 2d2a5d32c0cf..2efd905e45f3 100644 --- a/packages/adapter-cloudflare-workers/files/entry.js +++ b/packages/adapter-cloudflare-workers/files/entry.js @@ -6,7 +6,7 @@ const static_asset_manifest = JSON.parse(static_asset_manifest_json); const server = new Server(manifest); -const prefix = `/${manifest.appDir}/`; +const prefix = `/${manifest.appDir}/build/`; export default { /** diff --git a/packages/adapter-cloudflare/src/worker.js b/packages/adapter-cloudflare/src/worker.js index ad7c4643034d..5c385749e667 100644 --- a/packages/adapter-cloudflare/src/worker.js +++ b/packages/adapter-cloudflare/src/worker.js @@ -4,7 +4,7 @@ import * as Cache from 'worktop/cfw.cache'; const server = new Server(manifest); -const prefix = `/${manifest.appDir}/`; +const prefix = `/${manifest.appDir}/build/`; /** @type {import('worktop/cfw').Module.Worker<{ ASSETS: import('worktop/cfw.durable').Durable.Object }>} */ const worker = { diff --git a/packages/adapter-netlify/src/edge.js b/packages/adapter-netlify/src/edge.js index 89d2eb7e58ec..adf7dee8a9b7 100644 --- a/packages/adapter-netlify/src/edge.js +++ b/packages/adapter-netlify/src/edge.js @@ -2,7 +2,7 @@ import { Server } from '0SERVER'; import { manifest, prerendered } from 'MANIFEST'; const server = new Server(manifest); -const prefix = `/${manifest.appDir}/`; +const prefix = `/${manifest.appDir}/build/`; /** * @param { Request } request @@ -12,6 +12,7 @@ const prefix = `/${manifest.appDir}/`; export default function handler(request, context) { if (is_static_file(request)) { // Static files can skip the handler + // TODO can we serve _app/build files with an immutable cache header? return; } diff --git a/packages/adapter-node/src/handler.js b/packages/adapter-node/src/handler.js index d5c66d920b15..e68ed88b3b22 100644 --- a/packages/adapter-node/src/handler.js +++ b/packages/adapter-node/src/handler.js @@ -22,18 +22,23 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url)); /** * @param {string} path - * @param {number} max_age - * @param {boolean} immutable + * @param {boolean} client */ -function serve(path, max_age, immutable = false) { +function serve(path, client = false) { return ( fs.existsSync(path) && sirv(path, { etag: true, - maxAge: max_age, - immutable, gzip: true, - brotli: true + brotli: true, + setHeaders: + client && + ((res, pathname) => { + // only apply to build directory, not e.g. version.json + if (pathname.startsWith(`/${manifest.appDir}/build/`)) { + res.setHeader('cache-control', 'public,max-age=31536000,immutable'); + } + }) }) ); } @@ -126,9 +131,9 @@ function get_origin(headers) { export const handler = sequence( [ - serve(path.join(__dirname, '/client'), 31536000, true), - serve(path.join(__dirname, '/static'), 0), - serve(path.join(__dirname, '/prerendered'), 0), + serve(path.join(__dirname, '/client'), true), + serve(path.join(__dirname, '/static')), + serve(path.join(__dirname, '/prerendered')), ssr ].filter(Boolean) ); diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 041f492557fa..37d0d7dda9a8 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -180,7 +180,7 @@ async function v1(builder, external) { ...prerendered_pages, ...prerendered_redirects, { - src: `/${builder.config.kit.appDir}/.+`, + src: `/${builder.config.kit.appDir}/build/.+`, headers: { 'cache-control': 'public, immutable, max-age=31536000' } From 1cd467fd7d9dfaeb9d6490fde9d73c370dc34945 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 23 May 2022 22:23:05 -0400 Subject: [PATCH 05/13] Update .changeset/wise-berries-flash.md --- .changeset/wise-berries-flash.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/wise-berries-flash.md b/.changeset/wise-berries-flash.md index 0e72e7394437..fe4c7271283d 100644 --- a/.changeset/wise-berries-flash.md +++ b/.changeset/wise-berries-flash.md @@ -7,4 +7,4 @@ '@sveltejs/kit': patch --- -only serve \_app/build with immutable cache header, not \_app/version.json +only serve `_app/build` with immutable cache header, not `_app/version.json` From 3b88ffdd95069f7f8cdf0e5e19f8f783b8d9e8ca Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 24 May 2022 16:55:45 -0400 Subject: [PATCH 06/13] fix is_static_file --- packages/adapter-netlify/src/edge.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/adapter-netlify/src/edge.js b/packages/adapter-netlify/src/edge.js index adf7dee8a9b7..23e3784488e4 100644 --- a/packages/adapter-netlify/src/edge.js +++ b/packages/adapter-netlify/src/edge.js @@ -2,7 +2,7 @@ import { Server } from '0SERVER'; import { manifest, prerendered } from 'MANIFEST'; const server = new Server(manifest); -const prefix = `/${manifest.appDir}/build/`; +const prefix = `/${manifest.appDir}/`; /** * @param { Request } request @@ -34,6 +34,7 @@ function is_static_file(request) { if (url.pathname.startsWith(prefix)) { return true; } + // prerendered pages and index.html files const pathname = url.pathname.replace(/\/$/, ''); let file = pathname.substring(1); From f3e35ea89f512caf7e33f92d11a1ed259b9b23f8 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 24 May 2022 16:59:04 -0400 Subject: [PATCH 07/13] rename /build/ to /immutable/ --- .../adapter-cloudflare-workers/files/entry.js | 2 +- packages/adapter-cloudflare/src/worker.js | 2 +- packages/adapter-netlify/index.js | 2 +- packages/adapter-node/src/handler.js | 2 +- packages/adapter-vercel/index.js | 2 +- packages/kit/src/core/build/build_client.js | 2 +- packages/kit/src/core/build/build_server.js | 2 +- .../kit/src/core/build/build_service_worker.js | 2 +- packages/kit/src/core/build/index.js | 17 ++++++++++------- packages/kit/test/apps/basics/test/test.js | 2 +- 10 files changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/adapter-cloudflare-workers/files/entry.js b/packages/adapter-cloudflare-workers/files/entry.js index 2efd905e45f3..3450959bdcd8 100644 --- a/packages/adapter-cloudflare-workers/files/entry.js +++ b/packages/adapter-cloudflare-workers/files/entry.js @@ -6,7 +6,7 @@ const static_asset_manifest = JSON.parse(static_asset_manifest_json); const server = new Server(manifest); -const prefix = `/${manifest.appDir}/build/`; +const prefix = `/${manifest.appDir}/immutable/`; export default { /** diff --git a/packages/adapter-cloudflare/src/worker.js b/packages/adapter-cloudflare/src/worker.js index 5c385749e667..6a8c0376deb7 100644 --- a/packages/adapter-cloudflare/src/worker.js +++ b/packages/adapter-cloudflare/src/worker.js @@ -4,7 +4,7 @@ import * as Cache from 'worktop/cfw.cache'; const server = new Server(manifest); -const prefix = `/${manifest.appDir}/build/`; +const prefix = `/${manifest.appDir}/immutable/`; /** @type {import('worktop/cfw').Module.Worker<{ ASSETS: import('worktop/cfw.durable').Durable.Object }>} */ const worker = { diff --git a/packages/adapter-netlify/index.js b/packages/adapter-netlify/index.js index 89fa7305cc4e..774db538a5eb 100644 --- a/packages/adapter-netlify/index.js +++ b/packages/adapter-netlify/index.js @@ -64,7 +64,7 @@ export default function ({ split = false, edge = edge_set_in_env_var } = {}) { builder.copy('_headers', headers_file); appendFileSync( headers_file, - `\n\n/${builder.config.kit.appDir}/*\n cache-control: public\n cache-control: immutable\n cache-control: max-age=31536000\n` + `\n\n/${builder.config.kit.appDir}/immutable/*\n cache-control: public\n cache-control: immutable\n cache-control: max-age=31536000\n` ); // for esbuild, use ESM diff --git a/packages/adapter-node/src/handler.js b/packages/adapter-node/src/handler.js index e68ed88b3b22..4e3cfe1eeef3 100644 --- a/packages/adapter-node/src/handler.js +++ b/packages/adapter-node/src/handler.js @@ -35,7 +35,7 @@ function serve(path, client = false) { client && ((res, pathname) => { // only apply to build directory, not e.g. version.json - if (pathname.startsWith(`/${manifest.appDir}/build/`)) { + if (pathname.startsWith(`/${manifest.appDir}/immutable/`)) { res.setHeader('cache-control', 'public,max-age=31536000,immutable'); } }) diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index 37d0d7dda9a8..b731b91aaa38 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -180,7 +180,7 @@ async function v1(builder, external) { ...prerendered_pages, ...prerendered_redirects, { - src: `/${builder.config.kit.appDir}/build/.+`, + src: `/${builder.config.kit.appDir}/immutable/.+`, headers: { 'cache-control': 'public, immutable, max-age=31536000' } diff --git a/packages/kit/src/core/build/build_client.js b/packages/kit/src/core/build/build_client.js index 17e602dd7d02..0a1b24fcf76b 100644 --- a/packages/kit/src/core/build/build_client.js +++ b/packages/kit/src/core/build/build_client.js @@ -96,7 +96,7 @@ export async function build_client({ /** @type {import('vite').Manifest} */ const vite_manifest = JSON.parse( - fs.readFileSync(`${client_out_dir}/build/manifest.json`, 'utf-8') + fs.readFileSync(`${client_out_dir}/immutable/manifest.json`, 'utf-8') ); const entry = posixify(client_entry_file); diff --git a/packages/kit/src/core/build/build_server.js b/packages/kit/src/core/build/build_server.js index 97447465ac03..8cf13eb49bb0 100644 --- a/packages/kit/src/core/build/build_server.js +++ b/packages/kit/src/core/build/build_server.js @@ -69,7 +69,7 @@ export class Server { manifest, method_override: ${s(config.kit.methodOverride)}, paths: { base, assets }, - prefix: assets + '/${config.kit.appDir}/build/', + prefix: assets + '/${config.kit.appDir}/immutable/', prerender: { default: ${config.kit.prerender.default}, enabled: ${config.kit.prerender.enabled} diff --git a/packages/kit/src/core/build/build_service_worker.js b/packages/kit/src/core/build/build_service_worker.js index 924ea08ae3e1..6b43554bdd2d 100644 --- a/packages/kit/src/core/build/build_service_worker.js +++ b/packages/kit/src/core/build/build_service_worker.js @@ -44,7 +44,7 @@ export async function build_service_worker( export const build = [ ${Array.from(build) - .map((file) => `${s(`${config.kit.paths.base}/${config.kit.appDir}/build/${file}`)}`) + .map((file) => `${s(`${config.kit.paths.base}/${config.kit.appDir}/immutable/${file}`)}`) .join(',\n\t\t\t\t')} ]; diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index 008cbd7a0475..4bd182b64753 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -26,15 +26,18 @@ export async function build(config, { log }) { const { manifest_data } = sync.all(config); + // TODO this is so that Vite's preloading works. Unfortunately, it fails + // during `svelte-kit preview`, because we use a local asset path. If Vite + // used relative paths, I _think_ this could get fixed. Issue here: + // https://github.com/vitejs/vite/issues/2009 + const { base, assets } = config.kit.paths; + const assets_base = `${assets || base}/${config.kit.appDir}/immutable/`; + const options = { cwd, config, build_dir, - // TODO this is so that Vite's preloading works. Unfortunately, it fails - // during `svelte-kit preview`, because we use a local asset path. If Vite - // used relative paths, I _think_ this could get fixed. Issue here: - // https://github.com/vitejs/vite/issues/2009 - assets_base: `${config.kit.paths.assets || config.kit.paths.base}/${config.kit.appDir}/build/`, + assets_base, manifest_data, output_dir, client_entry_file: path.relative(cwd, `${get_runtime_path(config)}/client/start.js`), @@ -65,8 +68,8 @@ export async function build(config, { log }) { const files = new Set([ ...static_files, - ...client.chunks.map((chunk) => `${config.kit.appDir}/build/${chunk.fileName}`), - ...client.assets.map((chunk) => `${config.kit.appDir}/build/${chunk.fileName}`) + ...client.chunks.map((chunk) => `${config.kit.appDir}/immutable/${chunk.fileName}`), + ...client.assets.map((chunk) => `${config.kit.appDir}/immutable/${chunk.fileName}`) ]); // TODO is this right? diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index a2362222b0da..a8af8739de2e 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -347,7 +347,7 @@ test.describe.parallel('Imports', () => { ]); } else { expect(sources[0].startsWith('data:image/png;base64,')).toBeTruthy(); - expect(sources[1]).toBe(`${baseURL}/_app/build/assets/large-3183867c.jpg`); + expect(sources[1]).toBe(`${baseURL}/_app/immutable/assets/large-3183867c.jpg`); } }); }); From 271a83c7cf9b3699ee94ec508d999972f1eb54e7 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 24 May 2022 17:00:46 -0400 Subject: [PATCH 08/13] Update packages/kit/src/core/preview/index.js --- packages/kit/src/core/preview/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/core/preview/index.js b/packages/kit/src/core/preview/index.js index f258942fc51a..93dcfe98c562 100644 --- a/packages/kit/src/core/preview/index.js +++ b/packages/kit/src/core/preview/index.js @@ -68,7 +68,7 @@ export async function preview({ port, host, config, https: use_https = false }) sirv(join(config.kit.outDir, 'output/client'), { setHeaders: (res, pathname) => { // only apply to build directory, not e.g. version.json - if (pathname.startsWith(`/${config.kit.appDir}/build`)) { + if (pathname.startsWith(`/${config.kit.appDir}/immutable`)) { res.setHeader('cache-control', 'public,max-age=31536000,immutable'); } } From c1b6ee01a71be025179a3212c64a3e6f9e2bf0ca Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 24 May 2022 17:00:50 -0400 Subject: [PATCH 09/13] Update packages/kit/src/core/build/build_client.js --- packages/kit/src/core/build/build_client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/core/build/build_client.js b/packages/kit/src/core/build/build_client.js index 0a1b24fcf76b..8bea2daf31b1 100644 --- a/packages/kit/src/core/build/build_client.js +++ b/packages/kit/src/core/build/build_client.js @@ -59,7 +59,7 @@ export async function build_client({ build: { cssCodeSplit: true, manifest: true, - outDir: `${client_out_dir}/build`, + outDir: `${client_out_dir}/immutable`, polyfillDynamicImport: false, rollupOptions: { input, From e3f249337e34c5f9777d7725381de87b8ce85ce5 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 24 May 2022 17:00:55 -0400 Subject: [PATCH 10/13] Update packages/adapter-netlify/src/edge.js --- packages/adapter-netlify/src/edge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/adapter-netlify/src/edge.js b/packages/adapter-netlify/src/edge.js index 23e3784488e4..533d57eb2cc9 100644 --- a/packages/adapter-netlify/src/edge.js +++ b/packages/adapter-netlify/src/edge.js @@ -12,7 +12,7 @@ const prefix = `/${manifest.appDir}/`; export default function handler(request, context) { if (is_static_file(request)) { // Static files can skip the handler - // TODO can we serve _app/build files with an immutable cache header? + // TODO can we serve _app/immutable files with an immutable cache header? return; } From 369b37229fe795c74d4a946d1a392b3e47571e51 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 24 May 2022 17:00:59 -0400 Subject: [PATCH 11/13] Update .changeset/wise-berries-flash.md --- .changeset/wise-berries-flash.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/wise-berries-flash.md b/.changeset/wise-berries-flash.md index fe4c7271283d..8cb7218931d9 100644 --- a/.changeset/wise-berries-flash.md +++ b/.changeset/wise-berries-flash.md @@ -7,4 +7,4 @@ '@sveltejs/kit': patch --- -only serve `_app/build` with immutable cache header, not `_app/version.json` +only serve `_app/immutable` with immutable cache header, not `_app/version.json` From 26da5ad5ff5137bc7df9daaba8b4b5ed027050de Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 24 May 2022 17:36:30 -0400 Subject: [PATCH 12/13] update test --- packages/kit/test/apps/options-2/test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/test/apps/options-2/test/test.js b/packages/kit/test/apps/options-2/test/test.js index 0d8ba54090df..22b9e99d14a0 100644 --- a/packages/kit/test/apps/options-2/test/test.js +++ b/packages/kit/test/apps/options-2/test/test.js @@ -21,7 +21,7 @@ test.describe.parallel('Service worker', () => { const response = await request.get('/basepath/service-worker.js'); const content = await response.text(); - expect(content).toMatch(/\/_app\/start-[a-z0-9]+\.js/); + expect(content).toMatch(/\/_app\/immutable\/start-[a-z0-9]+\.js/); }); test('does not register /basepath/service-worker.js', async ({ page }) => { From 257d2fd78d8deb192ceae399123f1deeff6ed53f Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Tue, 24 May 2022 17:52:40 -0400 Subject: [PATCH 13/13] fix cloudflare adapters --- packages/adapter-cloudflare-workers/files/entry.js | 10 +++++++--- packages/adapter-cloudflare/src/worker.js | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/adapter-cloudflare-workers/files/entry.js b/packages/adapter-cloudflare-workers/files/entry.js index 3450959bdcd8..1064a1547763 100644 --- a/packages/adapter-cloudflare-workers/files/entry.js +++ b/packages/adapter-cloudflare-workers/files/entry.js @@ -6,7 +6,7 @@ const static_asset_manifest = JSON.parse(static_asset_manifest_json); const server = new Server(manifest); -const prefix = `/${manifest.appDir}/immutable/`; +const prefix = `/${manifest.appDir}/`; export default { /** @@ -23,11 +23,15 @@ export default { const res = await get_asset_from_kv(req, env, context); if (is_error(res.status)) return res; + const cache_control = url.pathname.startsWith(prefix + 'immutable/') + ? 'public, immutable, max-age=31536000' + : 'no-cache'; + return new Response(res.body, { headers: { - // include original cache headers, minus cache-control which + // include original headers, minus cache-control which // is overridden, and etag which is no longer useful - 'cache-control': 'public, immutable, max-age=31536000', + 'cache-control': cache_control, 'content-type': res.headers.get('content-type'), 'x-robots-tag': 'noindex' } diff --git a/packages/adapter-cloudflare/src/worker.js b/packages/adapter-cloudflare/src/worker.js index 6a8c0376deb7..4a53b71ea0ee 100644 --- a/packages/adapter-cloudflare/src/worker.js +++ b/packages/adapter-cloudflare/src/worker.js @@ -4,7 +4,7 @@ import * as Cache from 'worktop/cfw.cache'; const server = new Server(manifest); -const prefix = `/${manifest.appDir}/immutable/`; +const prefix = `/${manifest.appDir}/`; /** @type {import('worktop/cfw').Module.Worker<{ ASSETS: import('worktop/cfw.durable').Durable.Object }>} */ const worker = { @@ -20,11 +20,15 @@ const worker = { if (pathname.startsWith(prefix)) { res = await env.ASSETS.fetch(req); + const cache_control = pathname.startsWith(prefix + 'immutable/') + ? 'public, immutable, max-age=31536000' + : 'no-cache'; + res = new Response(res.body, { headers: { - // include original cache headers, minus cache-control which + // include original headers, minus cache-control which // is overridden, and etag which is no longer useful - 'cache-control': 'public, immutable, max-age=31536000', + 'cache-control': cache_control, 'content-type': res.headers.get('content-type'), 'x-robots-tag': 'noindex' }