Skip to content

Commit be13366

Browse files
authored
fix: preserve reincludes of excluded with prebundleSvelteLibraries (#493)
* fix: preserve reincludes of excluded when prebundleSvelteLibraries is true * fix: keep reincludes for nested exclusions as well * fix: omit final segment
1 parent a1ae9c0 commit be13366

File tree

4 files changed

+63
-42
lines changed

4 files changed

+63
-42
lines changed

.changeset/fuzzy-pets-drop.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/vite-plugin-svelte': patch
3+
---
4+
5+
when prebundleSvelteLibraries is true and a dependency is manually excluded, generate reincludes for it's cjs deps

packages/e2e-tests/prebundle-svelte-deps/__tests__/prebundle-svelte-deps.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,16 @@ if (!isBuild) {
2929
const metadata = JSON.parse(metadataFile);
3030
const optimizedPaths = Object.keys(metadata.optimized);
3131
expect(optimizedPaths).toContain('e2e-test-dep-svelte-simple');
32-
expect(optimizedPaths).toContain('e2e-test-dep-svelte-hybrid');
3332
expect(optimizedPaths).toContain('e2e-test-dep-svelte-api-only');
33+
expect(optimizedPaths).toContain('e2e-test-dep-svelte-nested');
3434
});
3535

3636
test('should not optimize excluded svelte dependencies', () => {
3737
const metadataFile = readVitePrebundleMetadata();
3838
const metadata = JSON.parse(metadataFile);
3939
const optimizedPaths = Object.keys(metadata.optimized);
4040
expect(optimizedPaths).not.toContain('e2e-test-dep-scss-only');
41+
expect(optimizedPaths).not.toContain('e2e-test-dep-svelte-hybrid');
42+
expect(optimizedPaths).toContain('e2e-test-dep-svelte-hybrid > e2e-test-dep-cjs-only');
4143
});
4244
}

packages/e2e-tests/prebundle-svelte-deps/vite.config.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import { svelte } from '@sveltejs/vite-plugin-svelte';
55
export default defineConfig({
66
plugins: [svelte()],
77
optimizeDeps: {
8-
// TODO this must be excluded because nested has an scss dep that prebundle can't handle!
9-
// figure out how to exclude it automatically or at least tell the user about it in a more friendly way
10-
exclude: ['e2e-test-dep-scss-only']
8+
exclude: [
9+
// TODO this must be excluded because nested has an scss dep that prebundle can't handle!
10+
// figure out how to exclude it automatically or at least tell the user about it in a more friendly way
11+
'e2e-test-dep-scss-only',
12+
'e2e-test-dep-svelte-hybrid'
13+
]
1114
},
1215
build: {
1316
// make build faster by skipping transforms and minification

packages/vite-plugin-svelte/src/utils/options.ts

Lines changed: 49 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -323,49 +323,47 @@ export async function buildExtraViteConfig(
323323
// knownJsSrcExtensions: options.extensions
324324
};
325325

326-
const optimizeDepsConfig = buildOptimizeDepsForSvelte(config);
327-
const ssrConfig = buildSSROptionsForSvelte(config);
328-
const crawlConfig = await getCrawlPkgsConfig(options, config);
329-
326+
const extraSvelteConfig = buildExtraConfigForSvelte(config);
327+
const extraDepsConfig = await buildExtraConfigForDependencies(options, config);
328+
// merge extra svelte and deps config, but make sure dep values are not contradicting svelte
330329
extraViteConfig.optimizeDeps = {
331330
include: [
332-
...optimizeDepsConfig.include,
333-
...crawlConfig.optimizeDeps.include.filter(
334-
(dep) => !isDepExcluded(dep, optimizeDepsConfig.exclude)
331+
...extraSvelteConfig.optimizeDeps.include,
332+
...extraDepsConfig.optimizeDeps.include.filter(
333+
(dep) => !isDepExcluded(dep, extraSvelteConfig.optimizeDeps.exclude)
335334
)
336335
],
337336
exclude: [
338-
...optimizeDepsConfig.exclude,
339-
...crawlConfig.optimizeDeps.exclude.filter(
340-
(dep) => !isDepIncluded(dep, optimizeDepsConfig.include)
337+
...extraSvelteConfig.optimizeDeps.exclude,
338+
...extraDepsConfig.optimizeDeps.exclude.filter(
339+
(dep) => !isDepIncluded(dep, extraSvelteConfig.optimizeDeps.include)
341340
)
342341
]
343342
};
344343

345344
extraViteConfig.ssr = {
346-
noExternal: [
347-
...ssrConfig.noExternal,
348-
...crawlConfig.ssr.noExternal.filter((dep) => !isDepExternaled(dep, ssrConfig.external))
349-
],
350345
external: [
351-
...ssrConfig.external,
352-
...crawlConfig.ssr.external.filter((dep) => !isDepNoExternaled(dep, ssrConfig.noExternal))
346+
...extraSvelteConfig.ssr.external,
347+
...extraDepsConfig.ssr.external.filter(
348+
(dep) => !isDepNoExternaled(dep, extraSvelteConfig.ssr.noExternal)
349+
)
350+
],
351+
noExternal: [
352+
...extraSvelteConfig.ssr.noExternal,
353+
...extraDepsConfig.ssr.noExternal.filter(
354+
(dep) => !isDepExternaled(dep, extraSvelteConfig.ssr.external)
355+
)
353356
]
354357
};
355358

356359
// handle prebundling for svelte files
357360
if (options.prebundleSvelteLibraries) {
358-
extraViteConfig.optimizeDeps = {
359-
...extraViteConfig.optimizeDeps,
360-
// Experimental Vite API to allow these extensions to be scanned and prebundled
361-
// @ts-ignore
362-
extensions: options.extensions ?? ['.svelte'],
363-
// Add esbuild plugin to prebundle Svelte files.
364-
// Currently a placeholder as more information is needed after Vite config is resolved,
365-
// the real Svelte plugin is added in `patchResolvedViteConfig()`
366-
esbuildOptions: {
367-
plugins: [{ name: facadeEsbuildSveltePluginName, setup: () => {} }]
368-
}
361+
extraViteConfig.optimizeDeps.extensions = options.extensions ?? ['.svelte'];
362+
// Add esbuild plugin to prebundle Svelte files.
363+
// Currently a placeholder as more information is needed after Vite config is resolved,
364+
// the real Svelte plugin is added in `patchResolvedViteConfig()`
365+
extraViteConfig.optimizeDeps.esbuildOptions = {
366+
plugins: [{ name: facadeEsbuildSveltePluginName, setup: () => {} }]
369367
};
370368
}
371369

@@ -382,7 +380,7 @@ export async function buildExtraViteConfig(
382380
return extraViteConfig;
383381
}
384382

385-
async function getCrawlPkgsConfig(options: PreResolvedOptions, config: UserConfig) {
383+
async function buildExtraConfigForDependencies(options: PreResolvedOptions, config: UserConfig) {
386384
// extra handling for svelte dependencies in the project
387385
const depsConfig = await crawlFrameworkPkgs({
388386
root: options.root,
@@ -404,11 +402,28 @@ async function getCrawlPkgsConfig(options: PreResolvedOptions, config: UserConfi
404402
}
405403
});
406404

407-
log.debug('crawl svelte packages result', depsConfig);
405+
log.debug('extra config for dependencies generated by vitefu', depsConfig);
408406

409407
if (options.prebundleSvelteLibraries) {
410-
depsConfig.optimizeDeps = { include: [], exclude: [] };
411-
} else if (options.disableDependencyReinclusion === true) {
408+
// prebundling enabled, so we don't need extra dependency excludes
409+
depsConfig.optimizeDeps.exclude = [];
410+
// but keep dependency reinclusions of explicit user excludes
411+
const userExclude = config.optimizeDeps?.exclude;
412+
depsConfig.optimizeDeps.include = !userExclude
413+
? []
414+
: depsConfig.optimizeDeps.include.filter((dep: string) => {
415+
// reincludes look like this: foo > bar > baz
416+
// in case foo or bar are excluded, we have to retain the reinclude even with prebundling
417+
return (
418+
dep.includes('>') &&
419+
dep
420+
.split('>')
421+
.slice(0, -1)
422+
.some((d) => isDepExcluded(d.trim(), userExclude))
423+
);
424+
});
425+
}
426+
if (options.disableDependencyReinclusion === true) {
412427
depsConfig.optimizeDeps.include = depsConfig.optimizeDeps.include.filter(
413428
(dep) => !dep.includes('>')
414429
);
@@ -421,12 +436,12 @@ async function getCrawlPkgsConfig(options: PreResolvedOptions, config: UserConfi
421436
});
422437
}
423438

424-
log.debug('processed crawl svelte packages result', depsConfig);
439+
log.debug('post-processed extra config for dependencies', depsConfig);
425440

426441
return depsConfig;
427442
}
428443

429-
function buildOptimizeDepsForSvelte(config: UserConfig) {
444+
function buildExtraConfigForSvelte(config: UserConfig) {
430445
// include svelte imports for optimization unless explicitly excluded
431446
const include: string[] = [];
432447
const exclude: string[] = ['svelte-hmr'];
@@ -439,18 +454,14 @@ function buildOptimizeDepsForSvelte(config: UserConfig) {
439454
} else {
440455
log.debug('"svelte" is excluded in optimizeDeps.exclude, skipped adding it to include.');
441456
}
442-
return { include, exclude };
443-
}
444-
445-
function buildSSROptionsForSvelte(config: UserConfig) {
446457
const noExternal: (string | RegExp)[] = [];
447458
const external: string[] = [];
448459
// add svelte to ssr.noExternal unless it is present in ssr.external
449460
// so we can resolve it with svelte/ssr
450461
if (!isDepExternaled('svelte', config.ssr?.external ?? [])) {
451462
noExternal.push('svelte', /^svelte\//);
452463
}
453-
return { noExternal, external };
464+
return { optimizeDeps: { include, exclude }, ssr: { noExternal, external } };
454465
}
455466

456467
export function patchResolvedViteConfig(viteConfig: ResolvedConfig, options: ResolvedOptions) {

0 commit comments

Comments
 (0)