diff --git a/.changeset/ten-planes-relax.md b/.changeset/ten-planes-relax.md new file mode 100644 index 000000000000..48f46a0ff7bb --- /dev/null +++ b/.changeset/ten-planes-relax.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: correctly find shared entry-point CSS files during inlining diff --git a/packages/kit/src/exports/vite/build/build_server.js b/packages/kit/src/exports/vite/build/build_server.js index 96ce9a7ed5fa..ca68244cc553 100644 --- a/packages/kit/src/exports/vite/build/build_server.js +++ b/packages/kit/src/exports/vite/build/build_server.js @@ -25,45 +25,52 @@ export function build_server_nodes(out, kit, manifest_data, server_manifest, cli /** @type {Set} */ const client_stylesheets = new Set(); for (const key in client_manifest) { - const file = client_manifest[key]; - if (file.css?.[0]) { - client_stylesheets.add(file.css[0]); - } + client_manifest[key].css?.forEach((filename) => { + client_stylesheets.add(filename); + }); } - /** @type {Map} */ + /** @type {Map} */ const server_stylesheets = new Map(); + manifest_data.nodes.forEach((node, i) => { + if (!node.component || !server_manifest[node.component]) return; - const component_stylesheet_map = new Map(Object.values(server_manifest).map((file) => [file.src, file.css?.[0]])); + const { stylesheets } = find_deps(server_manifest, node.component, false); - manifest_data.nodes.forEach((node, i) => { - const server_stylesheet = component_stylesheet_map.get(node.component); - if (node.component && server_stylesheet) { - server_stylesheets.set(i, server_stylesheet); + if (stylesheets.length) { + server_stylesheets.set(i, stylesheets); } }); - // ignore dynamically imported stylesheets since we can't inline those - css.filter(asset => client_stylesheets.has(asset.fileName)) - .forEach((asset) => { - if (asset.source.length < kit.inlineStyleThreshold) { - // We know that the names for entry points are numbers. - const [index] = basename(asset.fileName).split('.'); - // There can also be other CSS files from shared components - // for example, which we need to ignore here. - if (isNaN(+index)) return; - - const server_stylesheet = server_stylesheets.get(+index); - const file = `${out}/server/stylesheets/${index}.js`; - - // we need to inline the server stylesheet instead of the client one - // so that asset paths are correct on document load - const source = fs.readFileSync(`${out}/server/${server_stylesheet}`, 'utf-8'); - - fs.writeFileSync(file, `// ${server_stylesheet}\nexport default ${s(source)};`); - stylesheet_lookup.set(asset.fileName, index); - } + for (const asset of css) { + // ignore dynamically imported stylesheets since we don't need to inline those + if (!client_stylesheets.has(asset.fileName) || asset.source.length >= kit.inlineStyleThreshold) { + continue; + } + + // We know that the names for entry points are numbers. + const [index] = basename(asset.fileName).split('.'); + // There can also be other CSS files from shared components + // for example, which we need to ignore here. + if (isNaN(+index)) continue; + + const file = `${out}/server/stylesheets/${index}.js`; + + // we need to inline the server stylesheet instead of the client one + // so that asset paths are correct on document load + const filenames = server_stylesheets.get(+index); + + if (!filenames) { + throw new Error('This should never happen, but if it does, it means we failed to find the server stylesheet for a node.'); + } + + const sources = filenames.map((filename) => { + return fs.readFileSync(`${out}/server/${filename}`, 'utf-8'); }); + fs.writeFileSync(file, `// ${filenames.join(', ')}\nexport default ${s(sources.join('\n'))};`); + + stylesheet_lookup.set(asset.fileName, index); + } } manifest_data.nodes.forEach((node, i) => { diff --git a/packages/kit/test/apps/options/source/pages/inline-assets/+page.server.js b/packages/kit/test/apps/options/source/pages/inline-assets/+page.server.js new file mode 100644 index 000000000000..661546f24436 --- /dev/null +++ b/packages/kit/test/apps/options/source/pages/inline-assets/+page.server.js @@ -0,0 +1,4 @@ +// test that the server-client stylesheet map is constructed correctly when +// a page is imported. Importing a page causes Vite to associate the css with +// a separate chunk instead of the page component itself +import.meta.glob('./import-meta/+page.svelte', { eager: true }); diff --git a/packages/kit/test/apps/options/source/pages/inline-assets/import-meta/+page.svelte b/packages/kit/test/apps/options/source/pages/inline-assets/import-meta/+page.svelte new file mode 100644 index 000000000000..fb14331c1393 --- /dev/null +++ b/packages/kit/test/apps/options/source/pages/inline-assets/import-meta/+page.svelte @@ -0,0 +1,7 @@ +
this page is being imported so its css is associated with a separate chunk
+ +