diff --git a/.changeset/funny-items-deny.md b/.changeset/funny-items-deny.md new file mode 100644 index 000000000000..fe263bd9f0ef --- /dev/null +++ b/.changeset/funny-items-deny.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: prevent duplicate module preload diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index bd5bb27f61db..01625bdfe5bf 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -545,7 +545,8 @@ function kit({ svelte_config }) { // E.g. Vite generates `new URL('/asset.png', import.meta).href` for a relative path vs just '/asset.png'. // That's larger and takes longer to run and also causes an HTML diff between SSR and client // causing us to do a more expensive hydration check. - const client_base = kit.paths.relative || kit.paths.assets ? './' : kit.paths.base || '/'; + const client_base = + kit.paths.relative !== false || kit.paths.assets ? './' : kit.paths.base || '/'; new_config = { base: ssr ? assets_base(kit) : client_base, diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js index ce3be3bf6b27..74e90d760616 100644 --- a/packages/kit/test/apps/basics/test/client.test.js +++ b/packages/kit/test/apps/basics/test/client.test.js @@ -802,3 +802,27 @@ test.describe('Actions', () => { await expect(pre).toHaveText('prop: 1, store: 1'); }); }); + +test.describe('Assets', () => { + test('only one link per stylesheet', async ({ page }) => { + if (process.env.DEV) return; + + await page.goto('/'); + + expect( + await page.evaluate(() => { + const links = Array.from(document.head.querySelectorAll('link[rel=stylesheet]')); + + for (let i = 0; i < links.length; ) { + const link = links.shift(); + const asset_name = link.href.split('/').at(-1); + if (links.some((link) => link.href.includes(asset_name))) { + return false; + } + } + + return true; + }) + ).toBe(true); + }); +});