From e5edb602189f280cf0b4710f0ceb50c2df0adb4b Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:05:42 -0800 Subject: [PATCH 01/18] chore: faster builds with Vite 8 hook filters --- .changeset/cold-carrots-raise.md | 1 + .changeset/nine-coins-cheer.md | 1 + packages/enhanced-img/package.json | 4 +- packages/kit/src/exports/vite/index.js | 240 +++++++++++++------------ pnpm-lock.yaml | 15 +- 5 files changed, 141 insertions(+), 120 deletions(-) diff --git a/.changeset/cold-carrots-raise.md b/.changeset/cold-carrots-raise.md index b715e26dbc8e..5b77b8c63f25 100644 --- a/.changeset/cold-carrots-raise.md +++ b/.changeset/cold-carrots-raise.md @@ -1,6 +1,7 @@ --- '@sveltejs/package': major '@sveltejs/kit': major +'@sveltejs/enhanced-img': major --- breaking: require Node 22 or newer diff --git a/.changeset/nine-coins-cheer.md b/.changeset/nine-coins-cheer.md index 8f78036d0edd..efaf5ad2ecdc 100644 --- a/.changeset/nine-coins-cheer.md +++ b/.changeset/nine-coins-cheer.md @@ -1,4 +1,5 @@ --- +'@sveltejs/enhanced-img': major '@sveltejs/kit': major --- diff --git a/packages/enhanced-img/package.json b/packages/enhanced-img/package.json index 9d2ad76e82e3..6419c68bdb14 100644 --- a/packages/enhanced-img/package.json +++ b/packages/enhanced-img/package.json @@ -41,7 +41,7 @@ "magic-string": "^0.30.5", "sharp": "^0.34.1", "svelte-parse-markup": "^0.1.5", - "vite-imagetools": "^9.0.3", + "vite-imagetools": "^10.0.0", "zimmerframe": "^1.1.2" }, "devDependencies": { @@ -57,6 +57,6 @@ "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^6.0.0", "svelte": "^5.0.0", - "vite": "^6.3.0 || >=7.0.0" + "vite": ">=8.0.0" } } diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index dd742f0b0511..d5b180bd8100 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -423,7 +423,7 @@ async function kit({ svelte_config }) { // If importing from a service-worker, only allow $service-worker & $env/static/public, but none of the other virtual modules. // This check won't catch transitive imports, but it will warn when the import comes from a service-worker directly. // Transitive imports will be caught during the build. - // TODO move this logic to plugin_guard + // TODO move this logic to plugin_guard. add a filter to this resolveId when doing so if (importer) { const parsed_importer = path.parse(importer); @@ -456,45 +456,55 @@ async function kit({ svelte_config }) { return `\0virtual:${id}`; } }, + load: { + filter: { + id: [ + env_static_private, + env_static_public, + env_dynamic_private, + env_dynamic_public, + service_worker, + sveltekit_environment, + sveltekit_server + ] + }, + handler(id, options) { + switch (id) { + case env_static_private: + return create_static_module('$env/static/private', env.private); + + case env_static_public: + return create_static_module('$env/static/public', env.public); + + case env_dynamic_private: + return create_dynamic_module( + 'private', + vite_config_env.command === 'serve' ? env.private : undefined + ); - load(id, options) { - const browser = !options?.ssr; - - const global = is_build - ? `globalThis.__sveltekit_${version_hash}` - : 'globalThis.__sveltekit_dev'; - - switch (id) { - case env_static_private: - return create_static_module('$env/static/private', env.private); - - case env_static_public: - return create_static_module('$env/static/public', env.public); - - case env_dynamic_private: - return create_dynamic_module( - 'private', - vite_config_env.command === 'serve' ? env.private : undefined - ); + case env_dynamic_public: { + const browser = !options?.ssr; + // populate `$env/dynamic/public` from `window` + if (browser) { + const global = is_build + ? `globalThis.__sveltekit_${version_hash}` + : 'globalThis.__sveltekit_dev'; + return `export const env = ${global}.env;`; + } - case env_dynamic_public: - // populate `$env/dynamic/public` from `window` - if (browser) { - return `export const env = ${global}.env;`; + return create_dynamic_module( + 'public', + vite_config_env.command === 'serve' ? env.public : undefined + ); } - return create_dynamic_module( - 'public', - vite_config_env.command === 'serve' ? env.public : undefined - ); - - case service_worker: - return create_service_worker_module(svelte_config); + case service_worker: + return create_service_worker_module(svelte_config); - case sveltekit_environment: { - const { version } = svelte_config.kit; + case sveltekit_environment: { + const { version } = svelte_config.kit; - return dedent` + return dedent` export const version = ${s(version.name)}; export let building = false; export let prerendering = false; @@ -507,10 +517,10 @@ async function kit({ svelte_config }) { prerendering = true; } `; - } + } - case sveltekit_server: { - return dedent` + case sveltekit_server: { + return dedent` export let read_implementation = null; export let manifest = null; @@ -523,6 +533,7 @@ async function kit({ svelte_config }) { manifest = _; } `; + } } } } @@ -662,12 +673,15 @@ async function kit({ svelte_config }) { if (id.startsWith('\0sveltekit-remote:')) return id; }, - load(id) { - // On-the-fly generated entry point for remote file just forwards the original module - // We're not using manualChunks because it can cause problems with circular dependencies - // (e.g. https://github.com/sveltejs/kit/issues/14679) and module ordering in general - // (e.g. https://github.com/sveltejs/kit/issues/14590). - if (id.startsWith('\0sveltekit-remote:')) { + load: { + filter: { + id: /^\0sveltekit-remote:/ + }, + handler(id) { + // On-the-fly generated entry point for remote file just forwards the original module + // We're not using manualChunks because it can cause problems with circular dependencies + // (e.g. https://github.com/sveltejs/kit/issues/14679) and module ordering in general + // (e.g. https://github.com/sveltejs/kit/issues/14590). const hash_id = id.slice('\0sveltekit-remote:'.length); const original = remote_original_by_hash.get(hash_id); if (!original) throw new Error(`Expected to find metadata for remote file ${id}`); @@ -679,31 +693,32 @@ async function kit({ svelte_config }) { dev_server = _dev_server; }, - async transform(code, id, opts) { - const normalized = normalize_id(id, normalized_lib, normalized_cwd); - if (!svelte_config.kit.moduleExtensions.some((ext) => normalized.endsWith(`.remote${ext}`))) { - return; - } - - const file = posixify(path.relative(cwd, id)); - const remote = { - hash: hash(file), - file - }; + transform: { + filter: { + id: new RegExp( + `\\.remote(${svelte_config.kit.moduleExtensions.map((e) => e.replaceAll('.', '\\.')).join('|')})(\\?.*)?$` + ) + }, + async handler(code, id, opts) { + const file = posixify(path.relative(cwd, id)); + const remote = { + hash: hash(file), + file + }; - remotes.push(remote); + remotes.push(remote); - if (opts?.ssr) { - // we need to add an `await Promise.resolve()` because if the user imports this function - // on the client AND in a load function when loading the client module we will trigger - // an ssrLoadModule during dev. During a link preload, the module can be mistakenly - // loaded and transformed twice and the first time all its exports would be undefined - // triggering a dev server error. By adding a microtask we ensure that the module is fully loaded + if (opts?.ssr) { + // we need to add an `await Promise.resolve()` because if the user imports this function + // on the client AND in a load function when loading the client module we will trigger + // an ssrLoadModule during dev. During a link preload, the module can be mistakenly + // loaded and transformed twice and the first time all its exports would be undefined + // triggering a dev server error. By adding a microtask we ensure that the module is fully loaded - // Extra newlines to prevent syntax errors around missing semicolons or comments - code += - '\n\n' + - dedent` + // Extra newlines to prevent syntax errors around missing semicolons or comments + code += + '\n\n' + + dedent` import * as $$_self_$$ from './${path.basename(id)}'; import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal'; @@ -717,69 +732,70 @@ async function kit({ svelte_config }) { } `; - // Emit a dedicated entry chunk for this remote in SSR builds (prod only) - if (!dev_server) { - remote_original_by_hash.set(remote.hash, id); - if (!emitted_remote_hashes.has(remote.hash)) { - this.emitFile({ - type: 'chunk', - id: `\0sveltekit-remote:${remote.hash}`, - name: `remote-${remote.hash}` - }); - emitted_remote_hashes.add(remote.hash); + // Emit a dedicated entry chunk for this remote in SSR builds (prod only) + if (!dev_server) { + remote_original_by_hash.set(remote.hash, id); + if (!emitted_remote_hashes.has(remote.hash)) { + this.emitFile({ + type: 'chunk', + id: `\0sveltekit-remote:${remote.hash}`, + name: `remote-${remote.hash}` + }); + emitted_remote_hashes.add(remote.hash); + } } - } - return code; - } + return code; + } - // For the client, read the exports and create a new module that only contains fetch functions with the correct metadata + // For the client, read the exports and create a new module that only contains fetch functions with the correct metadata - /** @type {Map} */ - const map = new Map(); + /** @type {Map} */ + const map = new Map(); - // in dev, load the server module here (which will result in this hook - // being called again with `opts.ssr === true` if the module isn't - // already loaded) so we can determine what it exports - if (dev_server) { - const module = await dev_server.ssrLoadModule(id); + // in dev, load the server module here (which will result in this hook + // being called again with `opts.ssr === true` if the module isn't + // already loaded) so we can determine what it exports + if (dev_server) { + const module = await dev_server.ssrLoadModule(id); - for (const [name, value] of Object.entries(module)) { - const type = value?.__?.type; - if (type) { - map.set(name, type); + for (const [name, value] of Object.entries(module)) { + const type = value?.__?.type; + if (type) { + map.set(name, type); + } } } - } - // in prod, we already built and analysed the server code before - // building the client code, so `remote_exports` is populated - else if (build_metadata?.remotes) { - const exports = build_metadata?.remotes.get(remote.hash); - if (!exports) throw new Error('Expected to find metadata for remote file ' + id); + // in prod, we already built and analysed the server code before + // building the client code, so `remote_exports` is populated + else if (build_metadata?.remotes) { + const exports = build_metadata?.remotes.get(remote.hash); + if (!exports) throw new Error('Expected to find metadata for remote file ' + id); - for (const [name, value] of exports) { - map.set(name, value.type); + for (const [name, value] of exports) { + map.set(name, value.type); + } } - } - let namespace = '__remote'; - let uid = 1; - while (map.has(namespace)) namespace = `__remote${uid++}`; + let namespace = '__remote'; + let uid = 1; + while (map.has(namespace)) namespace = `__remote${uid++}`; - const exports = Array.from(map).map(([name, type]) => { - return `export const ${name} = ${namespace}.${type}('${remote.hash}/${name}');`; - }); + const exports = Array.from(map).map(([name, type]) => { + return `export const ${name} = ${namespace}.${type}('${remote.hash}/${name}');`; + }); - let result = `import * as ${namespace} from '__sveltekit/remote';\n\n${exports.join('\n')}\n`; + let result = `import * as ${namespace} from '__sveltekit/remote';\n\n${exports.join('\n')}\n`; - if (dev_server) { - result += `\nimport.meta.hot?.accept();\n`; - } + if (dev_server) { + result += `\nimport.meta.hot?.accept();\n`; + } - return { - code: result - }; + return { + code: result + }; + } } }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 41161822657c..b052ffafb205 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -493,8 +493,8 @@ importers: specifier: ^0.1.5 version: 0.1.5(svelte@5.53.5) vite-imagetools: - specifier: ^9.0.3 - version: 9.0.3(rollup@4.59.0) + specifier: ^10.0.0 + version: 10.0.0(rollup@4.59.0)(vite@8.0.0-beta.15(@types/node@24.10.13)(esbuild@0.27.3)(jiti@2.4.2)(yaml@2.8.0)) zimmerframe: specifier: ^1.1.2 version: 1.1.2 @@ -5672,9 +5672,11 @@ packages: resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - vite-imagetools@9.0.3: - resolution: {integrity: sha512-FwjApRNZyN+RucPW9Z9kf0dyzyi3r3zlDfrTnzHXNaYpmT3pZ5w//d6QkApy1iypbDm+3fq+Gwfv+PYA4j4uYw==} - engines: {node: '>=20.0.0'} + vite-imagetools@10.0.0: + resolution: {integrity: sha512-+83L32YPU/2BOHWhudO2+9T5HBvb3+0qHoUNN7fb0+XcAoXilx7aE25cDPWU5kBi5Yc750zYCvHxgfyR+tAuMA==} + engines: {node: '>=22.0.0'} + peerDependencies: + vite: '>=7.0.0' vite@8.0.0-beta.15: resolution: {integrity: sha512-RHX7IvsJlEfjyA1rS7MY0UsmF91etdLAamslHR5lfuO3W/BXRdXm2tRE64ztpSPZbKqB4wAAZ0AwtF6QzfKZLA==} @@ -10180,11 +10182,12 @@ snapshots: validate-npm-package-name@5.0.1: {} - vite-imagetools@9.0.3(rollup@4.59.0): + vite-imagetools@10.0.0(rollup@4.59.0)(vite@8.0.0-beta.15(@types/node@24.10.13)(esbuild@0.27.3)(jiti@2.4.2)(yaml@2.8.0)): dependencies: '@rollup/pluginutils': 5.1.3(rollup@4.59.0) imagetools-core: 9.1.0 sharp: 0.34.5 + vite: 8.0.0-beta.15(@types/node@24.10.13)(esbuild@0.27.3)(jiti@2.4.2)(yaml@2.8.0) transitivePeerDependencies: - rollup From 9d2ded21f6ab530979887c87a20d168315acd3e0 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:57:18 -0800 Subject: [PATCH 02/18] try this --- packages/kit/src/exports/vite/index.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index d5b180bd8100..dbc972855326 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -37,6 +37,7 @@ import { sveltekit_environment, sveltekit_server } from './module_ids.js'; +import { exactRegex } from 'rolldown/filter'; import { import_peer } from '../../utils/import.js'; import { compact } from '../../utils/array.js'; import { should_ignore, has_children } from './static_analysis/utils.js'; @@ -459,13 +460,13 @@ async function kit({ svelte_config }) { load: { filter: { id: [ - env_static_private, - env_static_public, - env_dynamic_private, - env_dynamic_public, - service_worker, - sveltekit_environment, - sveltekit_server + exactRegex(env_static_private), + exactRegex(env_static_public), + exactRegex(env_dynamic_private), + exactRegex(env_dynamic_public), + exactRegex(service_worker), + exactRegex(sveltekit_environment), + exactRegex(sveltekit_server) ] }, handler(id, options) { From faa3f5e32dabfeb718a797040040c3df5dc90d5b Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Fri, 27 Feb 2026 07:52:46 -0800 Subject: [PATCH 03/18] don't check for process.env.TEST on each invocation of load --- packages/kit/src/exports/vite/index.js | 126 +++++++++++++------------ 1 file changed, 66 insertions(+), 60 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index dbc972855326..d78d3464a8c8 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -575,83 +575,89 @@ async function kit({ svelte_config }) { } }, - load(id, options) { - if (options?.ssr === true || process.env.TEST === 'true') { - return; - } + load: + process.env.TEST === 'true' + ? undefined + : (id, options) => { + if (options?.ssr === true) { + return; + } - // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context - const is_internal = id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules); + // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context + const is_internal = + id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules); - const normalized = normalize_id(id, normalized_lib, normalized_cwd); + const normalized = normalize_id(id, normalized_lib, normalized_cwd); - const is_server_only = - normalized === '$env/static/private' || - normalized === '$env/dynamic/private' || - normalized === '$app/server' || - normalized.startsWith('$lib/server/') || - (is_internal && server_only_pattern.test(path.basename(id))); + const is_server_only = + normalized === '$env/static/private' || + normalized === '$env/dynamic/private' || + normalized === '$app/server' || + normalized.startsWith('$lib/server/') || + (is_internal && server_only_pattern.test(path.basename(id))); - if (is_server_only) { - // in dev, this doesn't exist, so we need to create it - manifest_data ??= sync.all(svelte_config, vite_config_env.mode).manifest_data; + if (is_server_only) { + // in dev, this doesn't exist, so we need to create it + manifest_data ??= sync.all(svelte_config, vite_config_env.mode).manifest_data; - /** @type {Set} */ - const entrypoints = new Set(); - for (const node of manifest_data.nodes) { - if (node.component) entrypoints.add(node.component); - if (node.universal) entrypoints.add(node.universal); - } + /** @type {Set} */ + const entrypoints = new Set(); + for (const node of manifest_data.nodes) { + if (node.component) entrypoints.add(node.component); + if (node.universal) entrypoints.add(node.universal); + } - if (manifest_data.hooks.client) entrypoints.add(manifest_data.hooks.client); - if (manifest_data.hooks.universal) entrypoints.add(manifest_data.hooks.universal); + if (manifest_data.hooks.client) entrypoints.add(manifest_data.hooks.client); + if (manifest_data.hooks.universal) entrypoints.add(manifest_data.hooks.universal); - const normalized = normalize_id(id, normalized_lib, normalized_cwd); - const chain = [normalized]; + const normalized = normalize_id(id, normalized_lib, normalized_cwd); + const chain = [normalized]; - let current = normalized; - let includes_remote_file = false; + let current = normalized; + let includes_remote_file = false; - while (true) { - const importers = import_map.get(current); - if (!importers) break; + while (true) { + const importers = import_map.get(current); + if (!importers) break; - const candidates = Array.from(importers).filter((importer) => !chain.includes(importer)); - if (candidates.length === 0) break; + const candidates = Array.from(importers).filter( + (importer) => !chain.includes(importer) + ); + if (candidates.length === 0) break; - chain.push((current = candidates[0])); + chain.push((current = candidates[0])); - includes_remote_file ||= svelte_config.kit.moduleExtensions.some((ext) => { - return current.endsWith(`.remote${ext}`); - }); + includes_remote_file ||= svelte_config.kit.moduleExtensions.some((ext) => { + return current.endsWith(`.remote${ext}`); + }); - if (entrypoints.has(current)) { - const pyramid = chain - .reverse() - .map((id, i) => { - return `${' '.repeat(i + 1)}${id}`; - }) - .join(' imports\n'); + if (entrypoints.has(current)) { + const pyramid = chain + .reverse() + .map((id, i) => { + return `${' '.repeat(i + 1)}${id}`; + }) + .join(' imports\n'); - if (includes_remote_file) { - error_for_missing_config( - 'remote functions', - 'kit.experimental.remoteFunctions', - 'true' - ); - } + if (includes_remote_file) { + error_for_missing_config( + 'remote functions', + 'kit.experimental.remoteFunctions', + 'true' + ); + } - let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`; - message += `\n\n${pyramid}`; - message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`; + let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`; + message += `\n\n${pyramid}`; + message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`; - throw stackless(message); - } - } + throw stackless(message); + } + } - throw new Error('An impossible situation occurred'); - } - } + throw new Error('An impossible situation occurred'); + } + } }; /** @type {import('vite').ViteDevServer} */ From 5f4f95a62c64a33cf0056a25e0197d55405055b1 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Fri, 27 Feb 2026 08:29:14 -0800 Subject: [PATCH 04/18] check pre-normalized URL in load for improved speed --- packages/kit/src/exports/vite/index.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index d78d3464a8c8..ebb965e119b6 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -29,6 +29,7 @@ import { s } from '../../utils/misc.js'; import { hash } from '../../utils/hash.js'; import { dedent } from '../../core/sync/utils.js'; import { + app_server, env_dynamic_private, env_dynamic_public, env_static_private, @@ -583,18 +584,15 @@ async function kit({ svelte_config }) { return; } - // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context - const is_internal = - id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules); - - const normalized = normalize_id(id, normalized_lib, normalized_cwd); - const is_server_only = - normalized === '$env/static/private' || - normalized === '$env/dynamic/private' || - normalized === '$app/server' || - normalized.startsWith('$lib/server/') || - (is_internal && server_only_pattern.test(path.basename(id))); + id === env_static_private || + id === env_dynamic_private || + id === app_server || + id.startsWith(`${normalized_lib}/server/`) || + // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context + (id.startsWith(normalized_cwd) && + !id.startsWith(normalized_node_modules) && + server_only_pattern.test(path.basename(id))); if (is_server_only) { // in dev, this doesn't exist, so we need to create it From 3c62417ec14e2a0be409653d1102bea23d417fc3 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Fri, 27 Feb 2026 09:46:53 -0800 Subject: [PATCH 05/18] convert if to filter --- packages/kit/src/exports/vite/index.js | 47 ++++++++++++++++---------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index ebb965e119b6..20cb491e8c30 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -170,6 +170,15 @@ let manifest_data; /** @type {import('types').ServerMetadata | undefined} only set at build time once analysis is finished */ let build_metadata = undefined; +/** + * TODO: SvelteKit 4 - replace with RegExp.escape - available only in Node 24 + * @param {string} str + * @returns + */ +const regExpEscape = function (str) { + return str.replace(/[-[\]{}()*+!<=:?.\\/\\^$|#\s,]/g, '\\$&'); +}; + /** * Returns the SvelteKit Vite plugin. Vite executes Rollup hooks as well as some of its own. * Background reading is available at: @@ -579,22 +588,26 @@ async function kit({ svelte_config }) { load: process.env.TEST === 'true' ? undefined - : (id, options) => { - if (options?.ssr === true) { - return; - } + : { + filter: { + id: [ + exactRegex(env_static_private), + exactRegex(env_dynamic_private), + exactRegex(app_server), + new RegExp(`^${normalized_lib}/server/`), + // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context + // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) + new RegExp( + `^(?!${regExpEscape(normalized_node_modules)})${regExpEscape(normalized_cwd)}.*(?:^|/)[^/]*${server_only_pattern.source}[^/]*$` + ) + ] + }, + handler(id, options) { + // TODO: can we replace this when migrating to the environment API? + if (options?.ssr === true) { + return; + } - const is_server_only = - id === env_static_private || - id === env_dynamic_private || - id === app_server || - id.startsWith(`${normalized_lib}/server/`) || - // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context - (id.startsWith(normalized_cwd) && - !id.startsWith(normalized_node_modules) && - server_only_pattern.test(path.basename(id))); - - if (is_server_only) { // in dev, this doesn't exist, so we need to create it manifest_data ??= sync.all(svelte_config, vite_config_env.mode).manifest_data; @@ -651,9 +664,9 @@ async function kit({ svelte_config }) { throw stackless(message); } - } - throw new Error('An impossible situation occurred'); + throw new Error('An impossible situation occurred'); + } } } }; From f4cc589ffe0fb3f001a801c078445104173fb418 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Fri, 27 Feb 2026 12:49:09 -0800 Subject: [PATCH 06/18] fix --- packages/kit/src/exports/vite/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 20cb491e8c30..53cd564a9f51 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -664,9 +664,9 @@ async function kit({ svelte_config }) { throw stackless(message); } - - throw new Error('An impossible situation occurred'); } + + throw new Error('An impossible situation occurred'); } } }; From 0348b12d5164fd9d26a86e2e84a7e29041a9b107 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Sat, 28 Feb 2026 17:51:21 +0800 Subject: [PATCH 07/18] snake_case --- packages/kit/src/exports/vite/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 53cd564a9f51..ba6c0b7bde79 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -175,7 +175,7 @@ let build_metadata = undefined; * @param {string} str * @returns */ -const regExpEscape = function (str) { +const reg_exp_escape = function (str) { return str.replace(/[-[\]{}()*+!<=:?.\\/\\^$|#\s,]/g, '\\$&'); }; @@ -598,7 +598,7 @@ async function kit({ svelte_config }) { // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) new RegExp( - `^(?!${regExpEscape(normalized_node_modules)})${regExpEscape(normalized_cwd)}.*(?:^|/)[^/]*${server_only_pattern.source}[^/]*$` + `^(?!${reg_exp_escape(normalized_node_modules)})${reg_exp_escape(normalized_cwd)}.*(?:^|/)[^/]*${server_only_pattern.source}[^/]*$` ) ] }, From 844f6385a7d46ba97bc95f82d7d0f8d046f7daf9 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Sat, 28 Feb 2026 18:29:48 +0800 Subject: [PATCH 08/18] use prefix helper --- packages/kit/src/exports/vite/index.js | 182 +++++++++++++------------ 1 file changed, 95 insertions(+), 87 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index ba6c0b7bde79..8c222cda8ce2 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -38,7 +38,7 @@ import { sveltekit_environment, sveltekit_server } from './module_ids.js'; -import { exactRegex } from 'rolldown/filter'; +import { exactRegex, prefixRegex } from 'rolldown/filter'; import { import_peer } from '../../utils/import.js'; import { compact } from '../../utils/array.js'; import { should_ignore, has_children } from './static_analysis/utils.js'; @@ -550,6 +550,7 @@ async function kit({ svelte_config }) { } }; + const skip_plugin_guard = process.env.TEST === 'true'; /** @type {Map>} */ const import_map = new Map(); const server_only_pattern = /.*\.server\..+/; @@ -566,109 +567,110 @@ async function kit({ svelte_config }) { // are added to the module graph enforce: 'pre', - async resolveId(id, importer, options) { - if (importer && !importer.endsWith('index.html')) { - const resolved = await this.resolve(id, importer, { ...options, skipSelf: true }); + resolveId: skip_plugin_guard + ? undefined + : async function (id, importer, options) { + if (importer && !importer.endsWith('index.html')) { + const resolved = await this.resolve(id, importer, { ...options, skipSelf: true }); - if (resolved) { - const normalized = normalize_id(resolved.id, normalized_lib, normalized_cwd); + if (resolved) { + const normalized = normalize_id(resolved.id, normalized_lib, normalized_cwd); - let importers = import_map.get(normalized); + let importers = import_map.get(normalized); - if (!importers) { - importers = new Set(); - import_map.set(normalized, importers); - } - - importers.add(normalize_id(importer, normalized_lib, normalized_cwd)); - } - } - }, - - load: - process.env.TEST === 'true' - ? undefined - : { - filter: { - id: [ - exactRegex(env_static_private), - exactRegex(env_dynamic_private), - exactRegex(app_server), - new RegExp(`^${normalized_lib}/server/`), - // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context - // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) - new RegExp( - `^(?!${reg_exp_escape(normalized_node_modules)})${reg_exp_escape(normalized_cwd)}.*(?:^|/)[^/]*${server_only_pattern.source}[^/]*$` - ) - ] - }, - handler(id, options) { - // TODO: can we replace this when migrating to the environment API? - if (options?.ssr === true) { - return; + if (!importers) { + importers = new Set(); + import_map.set(normalized, importers); } - // in dev, this doesn't exist, so we need to create it - manifest_data ??= sync.all(svelte_config, vite_config_env.mode).manifest_data; - - /** @type {Set} */ - const entrypoints = new Set(); - for (const node of manifest_data.nodes) { - if (node.component) entrypoints.add(node.component); - if (node.universal) entrypoints.add(node.universal); - } + importers.add(normalize_id(importer, normalized_lib, normalized_cwd)); + } + } + }, - if (manifest_data.hooks.client) entrypoints.add(manifest_data.hooks.client); - if (manifest_data.hooks.universal) entrypoints.add(manifest_data.hooks.universal); + load: skip_plugin_guard + ? undefined + : { + filter: { + id: [ + exactRegex(env_static_private), + exactRegex(env_dynamic_private), + exactRegex(app_server), + prefixRegex(`${normalized_lib}/server/`), + // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context + // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) + new RegExp( + `^(?!${reg_exp_escape(normalized_node_modules)})${reg_exp_escape(normalized_cwd)}.*(?:^|/)[^/]*${server_only_pattern.source}[^/]*$` + ) + ] + }, + handler(id, options) { + // TODO: replace with https://vite.dev/guide/api-environment-plugins#per-environment-plugins + if (options?.ssr === true) { + return; + } - const normalized = normalize_id(id, normalized_lib, normalized_cwd); - const chain = [normalized]; + // in dev, this doesn't exist, so we need to create it + manifest_data ??= sync.all(svelte_config, vite_config_env.mode).manifest_data; - let current = normalized; - let includes_remote_file = false; + /** @type {Set} */ + const entrypoints = new Set(); + for (const node of manifest_data.nodes) { + if (node.component) entrypoints.add(node.component); + if (node.universal) entrypoints.add(node.universal); + } - while (true) { - const importers = import_map.get(current); - if (!importers) break; + if (manifest_data.hooks.client) entrypoints.add(manifest_data.hooks.client); + if (manifest_data.hooks.universal) entrypoints.add(manifest_data.hooks.universal); - const candidates = Array.from(importers).filter( - (importer) => !chain.includes(importer) - ); - if (candidates.length === 0) break; + const normalized = normalize_id(id, normalized_lib, normalized_cwd); + const chain = [normalized]; - chain.push((current = candidates[0])); + let current = normalized; + let includes_remote_file = false; - includes_remote_file ||= svelte_config.kit.moduleExtensions.some((ext) => { - return current.endsWith(`.remote${ext}`); - }); + while (true) { + const importers = import_map.get(current); + if (!importers) break; - if (entrypoints.has(current)) { - const pyramid = chain - .reverse() - .map((id, i) => { - return `${' '.repeat(i + 1)}${id}`; - }) - .join(' imports\n'); + const candidates = Array.from(importers).filter( + (importer) => !chain.includes(importer) + ); + if (candidates.length === 0) break; - if (includes_remote_file) { - error_for_missing_config( - 'remote functions', - 'kit.experimental.remoteFunctions', - 'true' - ); - } + chain.push((current = candidates[0])); - let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`; - message += `\n\n${pyramid}`; - message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`; + includes_remote_file ||= svelte_config.kit.moduleExtensions.some((ext) => { + return current.endsWith(`.remote${ext}`); + }); - throw stackless(message); + if (entrypoints.has(current)) { + const pyramid = chain + .reverse() + .map((id, i) => { + return `${' '.repeat(i + 1)}${id}`; + }) + .join(' imports\n'); + + if (includes_remote_file) { + error_for_missing_config( + 'remote functions', + 'kit.experimental.remoteFunctions', + 'true' + ); } - } - throw new Error('An impossible situation occurred'); + let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`; + message += `\n\n${pyramid}`; + message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`; + + throw stackless(message); + } } + + throw new Error('An impossible situation occurred'); } + } }; /** @type {import('vite').ViteDevServer} */ @@ -687,13 +689,19 @@ async function kit({ svelte_config }) { const plugin_remote = { name: 'vite-plugin-sveltekit-remote', - resolveId(id) { - if (id.startsWith('\0sveltekit-remote:')) return id; + // prevent other plugins from resolving our remote virtual module + resolveId: { + filter: { + id: prefixRegex('\0sveltekit-remote:') + }, + handler(id) { + return id; + } }, load: { filter: { - id: /^\0sveltekit-remote:/ + id: prefixRegex('\0sveltekit-remote:') }, handler(id) { // On-the-fly generated entry point for remote file just forwards the original module From e77250e5841e5cf5f412b5843db2e3c3ea38ff98 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Sat, 28 Feb 2026 18:30:40 +0800 Subject: [PATCH 09/18] import ordering --- packages/kit/src/exports/vite/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 8c222cda8ce2..118195d77f4c 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -3,6 +3,8 @@ import path from 'node:path'; import process from 'node:process'; import { styleText } from 'node:util'; +import { exactRegex, prefixRegex } from 'rolldown/filter'; + import { copy, mkdirp, posixify, read, resolve_entry, rimraf } from '../../utils/filesystem.js'; import { create_static_module, create_dynamic_module } from '../../core/env.js'; import * as sync from '../../core/sync/sync.js'; @@ -38,7 +40,6 @@ import { sveltekit_environment, sveltekit_server } from './module_ids.js'; -import { exactRegex, prefixRegex } from 'rolldown/filter'; import { import_peer } from '../../utils/import.js'; import { compact } from '../../utils/array.js'; import { should_ignore, has_children } from './static_analysis/utils.js'; From d0ebf0c8e9edd84e2440b3406b00358eacbb1fd9 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Sat, 28 Feb 2026 18:37:56 +0800 Subject: [PATCH 10/18] non-capturing groups --- packages/kit/src/exports/vite/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 118195d77f4c..328709ceb77e 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -723,7 +723,7 @@ async function kit({ svelte_config }) { transform: { filter: { id: new RegExp( - `\\.remote(${svelte_config.kit.moduleExtensions.map((e) => e.replaceAll('.', '\\.')).join('|')})(\\?.*)?$` + `\\.remote(?:${svelte_config.kit.moduleExtensions.map((e) => e.replaceAll('.', '\\.')).join('|')})(?:\\?.*)?$` ) }, async handler(code, id, opts) { From 0ef5f0bc9d2bcd833252f98fa8fde922bc2516e8 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sat, 28 Feb 2026 05:55:58 -0800 Subject: [PATCH 11/18] Update packages/kit/src/exports/vite/index.js Co-authored-by: Tee Ming --- packages/kit/src/exports/vite/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 328709ceb77e..3b8083b4b9ac 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -601,7 +601,7 @@ async function kit({ svelte_config }) { // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) new RegExp( - `^(?!${reg_exp_escape(normalized_node_modules)})${reg_exp_escape(normalized_cwd)}.*(?:^|/)[^/]*${server_only_pattern.source}[^/]*$` + `^(?!${reg_exp_escape(normalized_node_modules)})${reg_exp_escape(normalized_cwd)}${server_only_pattern.source}$` ) ] }, From 70626f9cb945f8ab547bcdda958a8f14de6bfe4f Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sat, 28 Feb 2026 07:48:00 -0800 Subject: [PATCH 12/18] try this --- packages/kit/src/exports/vite/index.js | 37 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 3b8083b4b9ac..a1a465973c4c 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -3,7 +3,7 @@ import path from 'node:path'; import process from 'node:process'; import { styleText } from 'node:util'; -import { exactRegex, prefixRegex } from 'rolldown/filter'; +import { exactRegex, exclude, importerId, include, prefixRegex } from 'rolldown/filter'; import { copy, mkdirp, posixify, read, resolve_entry, rimraf } from '../../utils/filesystem.js'; import { create_static_module, create_dynamic_module } from '../../core/env.js'; @@ -570,21 +570,30 @@ async function kit({ svelte_config }) { resolveId: skip_plugin_guard ? undefined - : async function (id, importer, options) { - if (importer && !importer.endsWith('index.html')) { - const resolved = await this.resolve(id, importer, { ...options, skipSelf: true }); - - if (resolved) { - const normalized = normalize_id(resolved.id, normalized_lib, normalized_cwd); - - let importers = import_map.get(normalized); + : { + // TODO: remove cast when Vite supports it + // Vite's resolveId filter types don't yet expose the composable filter API, + // but rolldown (the underlying bundler) supports it at runtime + filter: /** @type {any} */ ([ + exclude(importerId(/index\.html$/)), + include(importerId(/.+/)) + ]), + async handler(id, importer, options) { + if (importer && !importer.endsWith('index.html')) { + const resolved = await this.resolve(id, importer, { ...options, skipSelf: true }); + + if (resolved) { + const normalized = normalize_id(resolved.id, normalized_lib, normalized_cwd); + + let importers = import_map.get(normalized); + + if (!importers) { + importers = new Set(); + import_map.set(normalized, importers); + } - if (!importers) { - importers = new Set(); - import_map.set(normalized, importers); + importers.add(normalize_id(importer, normalized_lib, normalized_cwd)); } - - importers.add(normalize_id(importer, normalized_lib, normalized_cwd)); } } }, From da9faf6591bc91141e3f2550395d1cd12e75b8e9 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sat, 28 Feb 2026 08:13:02 -0800 Subject: [PATCH 13/18] TODO --- packages/kit/src/exports/vite/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index a1a465973c4c..3ac5cdb073ac 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -572,6 +572,7 @@ async function kit({ svelte_config }) { ? undefined : { // TODO: remove cast when Vite supports it + // https://github.com/vitejs/rolldown-vite/issues/605 // Vite's resolveId filter types don't yet expose the composable filter API, // but rolldown (the underlying bundler) supports it at runtime filter: /** @type {any} */ ([ @@ -607,6 +608,7 @@ async function kit({ svelte_config }) { exactRegex(env_dynamic_private), exactRegex(app_server), prefixRegex(`${normalized_lib}/server/`), + // TODO: remove this check? https://github.com/sveltejs/kit/issues/12529 // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) new RegExp( From 3e9f3b8e798732fd927001596f0a3e5c6c9fd164 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sat, 28 Feb 2026 08:42:41 -0800 Subject: [PATCH 14/18] swap ordering --- packages/kit/src/exports/vite/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 3ac5cdb073ac..ffcf7c51adb5 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -608,11 +608,11 @@ async function kit({ svelte_config }) { exactRegex(env_dynamic_private), exactRegex(app_server), prefixRegex(`${normalized_lib}/server/`), - // TODO: remove this check? https://github.com/sveltejs/kit/issues/12529 + // TODO: remove the cwd portion of this check? https://github.com/sveltejs/kit/issues/12529 // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) new RegExp( - `^(?!${reg_exp_escape(normalized_node_modules)})${reg_exp_escape(normalized_cwd)}${server_only_pattern.source}$` + `^${reg_exp_escape(normalized_cwd)}(?!${reg_exp_escape(normalized_node_modules)})${server_only_pattern.source}$` ) ] }, From c5779ade8aad57c9a98f5840e2fff14bab96c847 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:01:49 -0800 Subject: [PATCH 15/18] Revert "swap ordering" This reverts commit 3e9f3b8e798732fd927001596f0a3e5c6c9fd164. --- packages/kit/src/exports/vite/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index ffcf7c51adb5..3ac5cdb073ac 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -608,11 +608,11 @@ async function kit({ svelte_config }) { exactRegex(env_dynamic_private), exactRegex(app_server), prefixRegex(`${normalized_lib}/server/`), - // TODO: remove the cwd portion of this check? https://github.com/sveltejs/kit/issues/12529 + // TODO: remove this check? https://github.com/sveltejs/kit/issues/12529 // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) new RegExp( - `^${reg_exp_escape(normalized_cwd)}(?!${reg_exp_escape(normalized_node_modules)})${server_only_pattern.source}$` + `^(?!${reg_exp_escape(normalized_node_modules)})${reg_exp_escape(normalized_cwd)}${server_only_pattern.source}$` ) ] }, From d4bd8c3d9db02937116e4d5ed6d8dae3073a1d77 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:01:56 -0800 Subject: [PATCH 16/18] Revert "TODO" This reverts commit da9faf6591bc91141e3f2550395d1cd12e75b8e9. --- packages/kit/src/exports/vite/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index 3ac5cdb073ac..a1a465973c4c 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -572,7 +572,6 @@ async function kit({ svelte_config }) { ? undefined : { // TODO: remove cast when Vite supports it - // https://github.com/vitejs/rolldown-vite/issues/605 // Vite's resolveId filter types don't yet expose the composable filter API, // but rolldown (the underlying bundler) supports it at runtime filter: /** @type {any} */ ([ @@ -608,7 +607,6 @@ async function kit({ svelte_config }) { exactRegex(env_dynamic_private), exactRegex(app_server), prefixRegex(`${normalized_lib}/server/`), - // TODO: remove this check? https://github.com/sveltejs/kit/issues/12529 // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) new RegExp( From 6d722b2cad101b3ce54253936540f3f3d34843fe Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:07:06 -0800 Subject: [PATCH 17/18] remove filter --- packages/kit/src/exports/vite/index.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index a1a465973c4c..afbc4a1c984f 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -571,13 +571,12 @@ async function kit({ svelte_config }) { resolveId: skip_plugin_guard ? undefined : { - // TODO: remove cast when Vite supports it - // Vite's resolveId filter types don't yet expose the composable filter API, - // but rolldown (the underlying bundler) supports it at runtime - filter: /** @type {any} */ ([ - exclude(importerId(/index\.html$/)), - include(importerId(/.+/)) - ]), + // TODO: use composable filter API here when supported: + // https://github.com/vitejs/rolldown-vite/issues/605 + // filter: ([ + // exclude(importerId(/index\.html$/)), + // include(importerId(/.+/)) + // ]), async handler(id, importer, options) { if (importer && !importer.endsWith('index.html')) { const resolved = await this.resolve(id, importer, { ...options, skipSelf: true }); @@ -609,6 +608,9 @@ async function kit({ svelte_config }) { prefixRegex(`${normalized_lib}/server/`), // skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context // should be equivalent to: (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules) && server_only_pattern.test(path.basename(id)) + // TODO: address https://github.com/sveltejs/kit/issues/12529 + // if we decide to do it then remove the CWD portion of the regex + // if we decide not to do it then this regex is complicated enough that it should be refactored out and independently tested new RegExp( `^(?!${reg_exp_escape(normalized_node_modules)})${reg_exp_escape(normalized_cwd)}${server_only_pattern.source}$` ) From 0bcc952c2c855af0763e138df06999ff5bba3d10 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:08:27 -0800 Subject: [PATCH 18/18] remove unused filters --- packages/kit/src/exports/vite/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js index afbc4a1c984f..96ccab11bb78 100644 --- a/packages/kit/src/exports/vite/index.js +++ b/packages/kit/src/exports/vite/index.js @@ -3,7 +3,7 @@ import path from 'node:path'; import process from 'node:process'; import { styleText } from 'node:util'; -import { exactRegex, exclude, importerId, include, prefixRegex } from 'rolldown/filter'; +import { exactRegex, prefixRegex } from 'rolldown/filter'; import { copy, mkdirp, posixify, read, resolve_entry, rimraf } from '../../utils/filesystem.js'; import { create_static_module, create_dynamic_module } from '../../core/env.js';