Skip to content

Commit 095013d

Browse files
dominikgbenmccann
andauthored
feat: add option disableDependencyReinclusion (#161)
* feat: add option disableDependencyReinclude * fix: update lockfile for new test dependency * refactor: rename option disableDependencyReinclude to disableDependencyReinclusion * docs: add suggested changes Co-authored-by: Ben McCann <[email protected]> * docs: fix re-include example Co-authored-by: Ben McCann <[email protected]>
1 parent 0141699 commit 095013d

File tree

11 files changed

+111
-16
lines changed

11 files changed

+111
-16
lines changed

.changeset/friendly-deers-own.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/vite-plugin-svelte': minor
3+
---
4+
5+
Add option disableDependencyReinclusion to offer users a way out of automatic optimization for hybrid packages

docs/config.md

+15
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,21 @@ A [minimatch pattern](https://github.com/isaacs/minimatch), or array of patterns
156156

157157
Some Vite plugins can contribute additional preprocessors by defining [api.sveltePreprocess](./faq.md#how-do-i-add-a-svelte-preprocessor-from-a-vite-plugin). If you don't want to use them, set this to true to ignore them all or use an array of strings with plugin names to specify which.
158158

159+
### disableDependencyReinclusion
160+
161+
- **Type:** `boolean | string[]`
162+
- **Default:** `false`
163+
164+
vite-plugin-svelte automatically manages [pre-bundling for Svelte components](./faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies).
165+
To opt-out of this automatic behavior you can use
166+
167+
- `disableDependencyReinclusion: true` to disable all re-inclusions
168+
- `disableDependencyReinclusion: ['foo']` to disable re-inclusions only for dependencies of `foo`.
169+
170+
If you want to manually re-include the dependency `bar`of `foo`, you can add `{optimizeDeps:{include:['foo > bar']}}` to your Vite config
171+
172+
> This is currently required for hybrid packages like Routify, that export both Node and browser code.
173+
159174
## Experimental options
160175

161176
These options are considered experimental and breaking changes to them can occur in any release! Specify them under the `experimental` option.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env node
2+
console.log('hybrid svelte');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Dependency from './src/components/Dependency.svelte';
2+
export default Dependency;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"version": "1.0.0",
3+
"private": true,
4+
"name": "e2e-test-dep-svelte-hybrid",
5+
"bin": "cli.js",
6+
"main": "index.js",
7+
"svelte": "index.js",
8+
"files": [
9+
"index.js",
10+
"cli.js",
11+
"package.json"
12+
],
13+
"dependencies": {
14+
"@types/node": "^16.7.8",
15+
"e2e-test-dep-cjs-only": "workspace:*"
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<script>
2+
const label = 'dependency-import';
3+
import * as cjsOnly from 'e2e-test-dep-cjs-only';
4+
const { cjs } = cjsOnly;
5+
</script>
6+
7+
<div id="dependency-import"><span class="label">{label}</span></div>
8+
<div id="sticky-dep" class="sticky-dep">sticky-dep</div>
9+
<div id="cjs-only-dependency">{cjs()}</div>
10+
11+
<style>
12+
.label {
13+
color: green;
14+
}
15+
.sticky-dep {
16+
position: sticky;
17+
}
18+
</style>

packages/e2e-tests/package-json-svelte-field/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"preview": "vite preview"
99
},
1010
"dependencies": {
11-
"e2e-test-dep-svelte-nested": "workspace:*"
11+
"e2e-test-dep-svelte-nested": "workspace:*",
12+
"e2e-test-dep-svelte-hybrid": "workspace:*"
1213
},
1314
"devDependencies": {
1415
"@sveltejs/vite-plugin-svelte": "workspace:*",

packages/e2e-tests/package-json-svelte-field/vite.config.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ const { defineConfig } = require('vite');
33

44
module.exports = defineConfig(({ command, mode }) => {
55
return {
6-
plugins: [svelte()],
6+
plugins: [
7+
svelte({
8+
disableDependencyReinclusion: ['e2e-test-dep-svelte-hybrid']
9+
})
10+
],
711
build: {
812
// make build faster by skipping transforms and minification
913
target: 'esnext',

packages/vite-plugin-svelte/src/utils/__tests__/dependencies.spec.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ describe('dependencies', () => {
1313
const deps = findRootSvelteDependencies(
1414
path.resolve('packages/e2e-tests/package-json-svelte-field')
1515
);
16-
expect(deps).toHaveLength(2);
16+
expect(deps).toHaveLength(3);
1717
expect(deps[0].name).toBe('e2e-test-dep-svelte-nested');
1818
expect(deps[1].name).toBe('e2e-test-dep-svelte-simple');
1919
expect(deps[1].path).toEqual(['e2e-test-dep-svelte-nested']);
20+
expect(deps[2].name).toBe('e2e-test-dep-svelte-hybrid');
2021
});
2122
});
2223
});

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

+33-12
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const knownOptions = new Set([
2727
'preprocess',
2828
'hot',
2929
'ignorePluginPreprocessors',
30+
'disableDependencyReinclusion',
3031
'experimental'
3132
]);
3233

@@ -184,7 +185,7 @@ export function buildExtraViteConfig(
184185
// extra handling for svelte dependencies in the project
185186
const svelteDeps = findRootSvelteDependencies(options.root);
186187
const extraViteConfig: Partial<UserConfig> = {
187-
optimizeDeps: buildOptimizeDepsForSvelte(svelteDeps, config.optimizeDeps),
188+
optimizeDeps: buildOptimizeDepsForSvelte(svelteDeps, options, config.optimizeDeps),
188189
resolve: {
189190
mainFields: [...SVELTE_RESOLVE_MAIN_FIELDS],
190191
dedupe: [...SVELTE_IMPORTS, ...SVELTE_HMR_IMPORTS]
@@ -214,6 +215,7 @@ export function buildExtraViteConfig(
214215

215216
function buildOptimizeDepsForSvelte(
216217
svelteDeps: SvelteDependency[],
218+
options: ResolvedOptions,
217219
optimizeDeps?: DepOptimizationOptions
218220
): DepOptimizationOptions {
219221
// include svelte imports for optimization unless explicitly excluded
@@ -244,18 +246,24 @@ function buildOptimizeDepsForSvelte(
244246
log.debug(`automatically excluding found svelte dependencies: ${svelteDepsToExclude.join(', ')}`);
245247
exclude.push(...svelteDepsToExclude.filter((x) => !isExcluded(x)));
246248

247-
const transitiveDepsToInclude = svelteDeps
248-
.filter((dep) => isExcluded(dep.name))
249-
.flatMap((dep) =>
250-
Object.keys(dep.pkg.dependencies || {})
251-
.filter((depOfDep) => !isExcluded(depOfDep))
252-
.map((depOfDep) => dep.path.concat(dep.name, depOfDep).join(' > '))
249+
if (options.disableDependencyReinclusion !== true) {
250+
const disabledReinclusions = options.disableDependencyReinclusion || [];
251+
if (disabledReinclusions.length > 0) {
252+
log.debug(`not reincluding transitive dependencies of`, disabledReinclusions);
253+
}
254+
const transitiveDepsToInclude = svelteDeps
255+
.filter((dep) => !disabledReinclusions.includes(dep.name) && isExcluded(dep.name))
256+
.flatMap((dep) =>
257+
Object.keys(dep.pkg.dependencies || {})
258+
.filter((depOfDep) => !isExcluded(depOfDep))
259+
.map((depOfDep) => dep.path.concat(dep.name, depOfDep).join(' > '))
260+
);
261+
log.debug(
262+
`reincluding transitive dependencies of excluded svelte dependencies`,
263+
transitiveDepsToInclude
253264
);
254-
log.debug(
255-
`reincluding transitive dependencies of excluded svelte dependencies`,
256-
transitiveDepsToInclude
257-
);
258-
include.push(...transitiveDepsToInclude);
265+
include.push(...transitiveDepsToInclude);
266+
}
259267

260268
return { include, exclude };
261269
}
@@ -372,6 +380,19 @@ export interface Options {
372380
*/
373381
ignorePluginPreprocessors?: boolean | string[];
374382

383+
/**
384+
* vite-plugin-svelte automatically handles excluding svelte libraries and reinclusion of their dependencies
385+
* in vite.optimizeDeps.
386+
*
387+
* `disableDependencyReinclusion: true` disables all reinclusions
388+
* `disableDependencyReinclusion: ['foo','bar']` disables reinclusions for dependencies of foo and bar
389+
*
390+
* This should be used for hybrid packages that contain both node and browser dependencies, eg Routify
391+
*
392+
* @default false
393+
*/
394+
disableDependencyReinclusion?: boolean | string[];
395+
375396
/**
376397
* These options are considered experimental and breaking changes to them can occur in any release
377398
*/

pnpm-lock.yaml

+10-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)