diff --git a/.changeset/clear-deer-doubt.md b/.changeset/clear-deer-doubt.md new file mode 100644 index 000000000000..572d9fd9b265 --- /dev/null +++ b/.changeset/clear-deer-doubt.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: ensure CSS URL references are absolute when `paths.relative` is `false` diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 5f2c1e629371..bd3af895b4e0 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -981,7 +981,7 @@ async function kit({ svelte_config }) { if (is_build) { const ssr = /** @type {boolean} */ (config.build?.ssr); - const prefix = `${kit.appDir}/immutable`; + const app_immutable = `${kit.appDir}/immutable`; /** @type {Record} */ const input = {}; @@ -1071,9 +1071,9 @@ async function kit({ svelte_config }) { /** @type {string} */ const base = (kit.paths.assets || kit.paths.base) + '/'; - const root_to_assets = prefix + '/assets/'; + const root_to_assets = app_immutable + '/assets/'; const assets_to_root = - prefix + app_immutable .split('/') .map(() => '..') .join('/') + '/../'; @@ -1099,9 +1099,11 @@ async function kit({ svelte_config }) { output: { format: inline ? 'iife' : 'esm', name: `__sveltekit_${version_hash}.app`, - entryFileNames: ssr ? '[name].js' : `${prefix}/[name].[hash].${ext}`, - chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[hash].${ext}`, - assetFileNames: `${prefix}/assets/[name].[hash][extname]`, + entryFileNames: ssr ? '[name].js' : `${app_immutable}/[name].[hash].${ext}`, + chunkFileNames: ssr + ? 'chunks/[name].js' + : `${app_immutable}/chunks/[hash].${ext}`, + assetFileNames: `${app_immutable}/assets/[name].[hash][extname]`, hoistTransitiveImports: false, sourcemapIgnoreList, inlineDynamicImports: is_rolldown ? undefined : !split @@ -1129,9 +1131,9 @@ async function kit({ svelte_config }) { worker: { rollupOptions: { output: { - entryFileNames: `${prefix}/workers/[name]-[hash].js`, - chunkFileNames: `${prefix}/workers/chunks/[hash].js`, - assetFileNames: `${prefix}/workers/assets/[name]-[hash][extname]`, + entryFileNames: `${app_immutable}/workers/[name]-[hash].js`, + chunkFileNames: `${app_immutable}/workers/chunks/[hash].js`, + assetFileNames: `${app_immutable}/workers/assets/[name]-[hash][extname]`, hoistTransitiveImports: false } } @@ -1151,6 +1153,11 @@ async function kit({ svelte_config }) { return { relative }; } + if (!relative) return; + + // ensure assets loaded by CSS files are loaded relative to the + // CSS file rather than the default of relative to the root + // _app/immutable/assets files if (filename.startsWith(root_to_assets)) { return `./${filename.slice(root_to_assets.length)}`; diff --git a/packages/kit/test/apps/options/package.json b/packages/kit/test/apps/options/package.json index 3e7c004eea33..85c9ed6c8d31 100644 --- a/packages/kit/test/apps/options/package.json +++ b/packages/kit/test/apps/options/package.json @@ -10,7 +10,10 @@ "check": "svelte-kit sync && tsc && svelte-check", "test": "pnpm test:dev && pnpm test:build", "test:dev": "DEV=true playwright test && DEV=true PATHS_ASSETS=https://cdn.example.com/stuff playwright test", - "test:build": "playwright test && PATHS_ASSETS=https://cdn.example.com/stuff playwright test", + "test:paths-relative:build": "playwright test", + "test:paths-absolute:build": "PATHS_RELATIVE=false playwright test", + "test:paths-assets:build": "PATHS_ASSETS=https://cdn.example.com/stuff playwright test", + "test:build": "pnpm test:paths-relative:build && pnpm test:paths-absolute:build && pnpm test:paths-assets:build", "test:unit": "vitest run --config vite.custom.config.js", "test:server-side-route-resolution:dev": "rm -rf test/errors.json && DEV=true ROUTER_RESOLUTION=server playwright test", "test:server-side-route-resolution:build": "rm -rf test/errors.json && ROUTER_RESOLUTION=server playwright test" diff --git a/packages/kit/test/apps/options/playwright.config.js b/packages/kit/test/apps/options/playwright.config.js index cdb691f211a8..975bba3b3305 100644 --- a/packages/kit/test/apps/options/playwright.config.js +++ b/packages/kit/test/apps/options/playwright.config.js @@ -9,7 +9,8 @@ export default defineConfig({ command: process.env.DEV ? `pnpm dev` : `pnpm build && pnpm preview`, env: { ROUTER_RESOLUTION: process.env.ROUTER_RESOLUTION ?? 'client', - PATHS_ASSETS: process.env.PATHS_ASSETS ?? '' + PATHS_ASSETS: process.env.PATHS_ASSETS ?? '', + PATHS_RELATIVE: process.env.PATHS_RELATIVE ?? 'true' } } }); diff --git a/packages/kit/test/apps/options/svelte.config.js b/packages/kit/test/apps/options/svelte.config.js index da8cebe35818..271373259438 100644 --- a/packages/kit/test/apps/options/svelte.config.js +++ b/packages/kit/test/apps/options/svelte.config.js @@ -33,7 +33,8 @@ const config = { paths: { base: '/path-base', // @ts-expect-error our env var string can't match the https template literal - assets: process.env.PATHS_ASSETS || '' + assets: process.env.PATHS_ASSETS || '', + relative: process.env.PATHS_RELATIVE !== 'false' }, env: { dir: './env-dir', diff --git a/packages/kit/test/apps/options/test/paths-assets.test.js b/packages/kit/test/apps/options/test/paths.test.js similarity index 100% rename from packages/kit/test/apps/options/test/paths-assets.test.js rename to packages/kit/test/apps/options/test/paths.test.js diff --git a/packages/kit/test/apps/options/test/test.js b/packages/kit/test/apps/options/test/test.js index ceefb0383b18..a7356b5fec04 100644 --- a/packages/kit/test/apps/options/test/test.js +++ b/packages/kit/test/apps/options/test/test.js @@ -5,7 +5,7 @@ import { test } from '../../../utils.js'; test.describe.configure({ mode: 'parallel' }); -test.skip(!!process.env.PATHS_ASSETS); +test.skip(!!process.env.PATHS_ASSETS || process.env.PATHS_RELATIVE === 'false'); test.describe('CSP', () => { test('blocks script from external site', async ({ page, start_server }) => {