diff --git a/.changeset/chilled-humans-roll.md b/.changeset/chilled-humans-roll.md new file mode 100644 index 000000000000..14e779a03a54 --- /dev/null +++ b/.changeset/chilled-humans-roll.md @@ -0,0 +1,5 @@ +--- +"@sveltejs/kit": patch +--- + +fix: detect assets emitted by vite plugins in prerenderer `fetch`. diff --git a/packages/kit/src/core/generate_manifest/index.js b/packages/kit/src/core/generate_manifest/index.js index a2ef4cd4c619..2e63bc5c47a3 100644 --- a/packages/kit/src/core/generate_manifest/index.js +++ b/packages/kit/src/core/generate_manifest/index.js @@ -80,6 +80,15 @@ export function generate_manifest({ build_data, relative_path, routes }) { mime_types[ext] ??= mime.lookup(ext) || ''; } + const emitted_asset_dir = path.resolve(build_data.out_dir, 'server', build_data.asset_prefix); + if (fs.existsSync(emitted_asset_dir)) { + for (const file of fs.readdirSync(emitted_asset_dir)) { + assets.push(path.join(build_data.asset_prefix, file).replaceAll(path.sep, '/')); + const ext = path.extname(file); + mime_types[ext] ??= mime.lookup(ext) || ''; + } + } + // prettier-ignore // String representation of /** @template {import('@sveltejs/kit').SSRManifest} T */ diff --git a/packages/kit/src/core/postbuild/prerender.js b/packages/kit/src/core/postbuild/prerender.js index 05c995ab9771..76394585a941 100644 --- a/packages/kit/src/core/postbuild/prerender.js +++ b/packages/kit/src/core/postbuild/prerender.js @@ -211,6 +211,11 @@ async function prerender({ out, manifest_path, metadata, verbose, env }) { const filepath = saved.get(file); if (filepath) return readFileSync(filepath); + // Static assets emitted during build + if (file.startsWith(config.appDir)) { + return readFileSync(join(config.outDir, 'output', 'server', file)); + } + // stuff in `static` return readFileSync(join(config.files.assets, file)); }, diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index c91055ba9aa7..393171283d0b 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -754,6 +754,7 @@ async function kit({ svelte_config }) { app_path: `${kit.paths.base.slice(1)}${kit.paths.base ? '/' : ''}${kit.appDir}`, manifest_data, out_dir: out, + asset_prefix: `${kit.appDir}/immutable/assets`, service_worker: service_worker_entry_file ? 'service-worker.js' : null, // TODO make file configurable? client: null, server_manifest diff --git a/packages/kit/src/types/internal.d.ts b/packages/kit/src/types/internal.d.ts index af50cbe74c7d..38c6350c12c3 100644 --- a/packages/kit/src/types/internal.d.ts +++ b/packages/kit/src/types/internal.d.ts @@ -63,6 +63,7 @@ export interface BuildData { app_path: string; manifest_data: ManifestData; out_dir: string; + asset_prefix: string; service_worker: string | null; client: { start: string; diff --git a/packages/kit/test/prerendering/paths-base/custom_asset_plugin.js b/packages/kit/test/prerendering/paths-base/custom_asset_plugin.js new file mode 100644 index 000000000000..3a28d6c3cabe --- /dev/null +++ b/packages/kit/test/prerendering/paths-base/custom_asset_plugin.js @@ -0,0 +1,41 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +export default function () { + let config; + const ext = '.csv'; + return { + name: 'vite-plugin-sveltekit-custom-asset', + resolveId(id) { + if (id.endsWith(ext)) { + return id; + } + }, + configResolved(resolvedConfig) { + config = resolvedConfig; + }, + load(id) { + if (!id.endsWith(ext)) return; + if (config.command === 'serve') + return `export default "${path.relative(process.cwd(), id).replaceAll(path.sep, '/')}";`; + + const outName = config.build.rollupOptions.output.assetFileNames + .replace('[name]', path.basename(id, ext)) + .replace('[hash]', '000000') + .replace('[extname]', ext); + + if (config.build?.ssr) { + const ref = this.emitFile({ + type: 'asset', + fileName: outName + }); + fs.readFile(id, (err, data) => { + if (err) this.error(err); + this.setAssetSource(ref, data); + }); + } + + return `export default "${config.base}${outName}";`; + } + }; +} diff --git a/packages/kit/test/prerendering/paths-base/src/routes/assets/emitted/+page.js b/packages/kit/test/prerendering/paths-base/src/routes/assets/emitted/+page.js new file mode 100644 index 000000000000..ecd0785e6b06 --- /dev/null +++ b/packages/kit/test/prerendering/paths-base/src/routes/assets/emitted/+page.js @@ -0,0 +1,8 @@ +// @ts-ignore +import url from './message.csv'; + +export async function load({ fetch }) { + const response = await fetch(url); + const asset = await response.text(); + return { asset }; +} diff --git a/packages/kit/test/prerendering/paths-base/src/routes/assets/emitted/+page.svelte b/packages/kit/test/prerendering/paths-base/src/routes/assets/emitted/+page.svelte new file mode 100644 index 000000000000..33b39b7e03cd --- /dev/null +++ b/packages/kit/test/prerendering/paths-base/src/routes/assets/emitted/+page.svelte @@ -0,0 +1,5 @@ + + +
{data.asset}
diff --git a/packages/kit/test/prerendering/paths-base/src/routes/assets/emitted/message.csv b/packages/kit/test/prerendering/paths-base/src/routes/assets/emitted/message.csv new file mode 100644 index 000000000000..07beee08078d --- /dev/null +++ b/packages/kit/test/prerendering/paths-base/src/routes/assets/emitted/message.csv @@ -0,0 +1 @@ +A custom asset emitted by a vite plugin during build. \ No newline at end of file diff --git a/packages/kit/test/prerendering/paths-base/test/tests.spec.js b/packages/kit/test/prerendering/paths-base/test/tests.spec.js index 77674df89c93..1ea39a737327 100644 --- a/packages/kit/test/prerendering/paths-base/test/tests.spec.js +++ b/packages/kit/test/prerendering/paths-base/test/tests.spec.js @@ -29,3 +29,8 @@ test('prerenders /path-base/assets', () => { const content = read('assets.html'); assert.match(content, /]+src="\/path-base\//u); }); + +test('prerenders /path-base/assets/emitted', () => { + const content = read('assets/emitted.html'); + assert.ok(content.includes('A custom asset emitted by a vite plugin during build.
')); +}); diff --git a/packages/kit/test/prerendering/paths-base/vite.config.js b/packages/kit/test/prerendering/paths-base/vite.config.js index 2857b2592d11..cd49ec622d63 100644 --- a/packages/kit/test/prerendering/paths-base/vite.config.js +++ b/packages/kit/test/prerendering/paths-base/vite.config.js @@ -1,5 +1,6 @@ import * as path from 'node:path'; import { sveltekit } from '@sveltejs/kit/vite'; +import csvasset from './custom_asset_plugin.js'; /** @type {import('vite').UserConfig} */ const config = { @@ -13,7 +14,7 @@ const config = { logLevel: 'silent', - plugins: [sveltekit()], + plugins: [csvasset(), sveltekit()], server: { fs: { diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 1219176d5665..bb2a23166a95 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -1587,6 +1587,7 @@ declare module '@sveltejs/kit' { app_path: string; manifest_data: ManifestData; out_dir: string; + asset_prefix: string; service_worker: string | null; client: { start: string;