Skip to content

feat: add option disableDependencyReinclude #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/friendly-deers-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/vite-plugin-svelte': minor
---

Add option disableDependencyReinclusion to offer users a way out of automatic optimization for hybrid packages
15 changes: 15 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,21 @@ A [minimatch pattern](https://github.com/isaacs/minimatch), or array of patterns

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.

### disableDependencyReinclusion

- **Type:** `boolean | string[]`
- **Default:** `false`

vite-plugin-svelte automatically manages [pre-bundling for Svelte components](./faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies).
To opt-out of this automatic behavior you can use

- `disableDependencyReinclusion: true` to disable all re-inclusions
- `disableDependencyReinclusion: ['foo']` to disable re-inclusions only for dependencies of `foo`.

If you want to manually re-include the dependency `bar`of `foo`, you can add `{optimizeDeps:{include:['foo > bar']}}` to your Vite config

> This is currently required for hybrid packages like Routify, that export both Node and browser code.

## Experimental options

These options are considered experimental and breaking changes to them can occur in any release! Specify them under the `experimental` option.
Expand Down
2 changes: 2 additions & 0 deletions packages/e2e-tests/_test_dependencies/svelte-hybrid/cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env node
console.log('hybrid svelte');
2 changes: 2 additions & 0 deletions packages/e2e-tests/_test_dependencies/svelte-hybrid/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Dependency from './src/components/Dependency.svelte';
export default Dependency;
17 changes: 17 additions & 0 deletions packages/e2e-tests/_test_dependencies/svelte-hybrid/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"version": "1.0.0",
"private": true,
"name": "e2e-test-dep-svelte-hybrid",
"bin": "cli.js",
"main": "index.js",
"svelte": "index.js",
"files": [
"index.js",
"cli.js",
"package.json"
],
"dependencies": {
"@types/node": "^16.7.8",
"e2e-test-dep-cjs-only": "workspace:*"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script>
const label = 'dependency-import';
import * as cjsOnly from 'e2e-test-dep-cjs-only';
const { cjs } = cjsOnly;
</script>

<div id="dependency-import"><span class="label">{label}</span></div>
<div id="sticky-dep" class="sticky-dep">sticky-dep</div>
<div id="cjs-only-dependency">{cjs()}</div>

<style>
.label {
color: green;
}
.sticky-dep {
position: sticky;
}
</style>
3 changes: 2 additions & 1 deletion packages/e2e-tests/package-json-svelte-field/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"preview": "vite preview"
},
"dependencies": {
"e2e-test-dep-svelte-nested": "workspace:*"
"e2e-test-dep-svelte-nested": "workspace:*",
"e2e-test-dep-svelte-hybrid": "workspace:*"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "workspace:*",
Expand Down
6 changes: 5 additions & 1 deletion packages/e2e-tests/package-json-svelte-field/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ const { defineConfig } = require('vite');

module.exports = defineConfig(({ command, mode }) => {
return {
plugins: [svelte()],
plugins: [
svelte({
disableDependencyReinclusion: ['e2e-test-dep-svelte-hybrid']
})
],
build: {
// make build faster by skipping transforms and minification
target: 'esnext',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ describe('dependencies', () => {
const deps = findRootSvelteDependencies(
path.resolve('packages/e2e-tests/package-json-svelte-field')
);
expect(deps).toHaveLength(2);
expect(deps).toHaveLength(3);
expect(deps[0].name).toBe('e2e-test-dep-svelte-nested');
expect(deps[1].name).toBe('e2e-test-dep-svelte-simple');
expect(deps[1].path).toEqual(['e2e-test-dep-svelte-nested']);
expect(deps[2].name).toBe('e2e-test-dep-svelte-hybrid');
});
});
});
45 changes: 33 additions & 12 deletions packages/vite-plugin-svelte/src/utils/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const knownOptions = new Set([
'preprocess',
'hot',
'ignorePluginPreprocessors',
'disableDependencyReinclusion',
'experimental'
]);

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

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

const transitiveDepsToInclude = svelteDeps
.filter((dep) => isExcluded(dep.name))
.flatMap((dep) =>
Object.keys(dep.pkg.dependencies || {})
.filter((depOfDep) => !isExcluded(depOfDep))
.map((depOfDep) => dep.path.concat(dep.name, depOfDep).join(' > '))
if (options.disableDependencyReinclusion !== true) {
const disabledReinclusions = options.disableDependencyReinclusion || [];
if (disabledReinclusions.length > 0) {
log.debug(`not reincluding transitive dependencies of`, disabledReinclusions);
}
const transitiveDepsToInclude = svelteDeps
.filter((dep) => !disabledReinclusions.includes(dep.name) && isExcluded(dep.name))
.flatMap((dep) =>
Object.keys(dep.pkg.dependencies || {})
.filter((depOfDep) => !isExcluded(depOfDep))
.map((depOfDep) => dep.path.concat(dep.name, depOfDep).join(' > '))
);
log.debug(
`reincluding transitive dependencies of excluded svelte dependencies`,
transitiveDepsToInclude
);
log.debug(
`reincluding transitive dependencies of excluded svelte dependencies`,
transitiveDepsToInclude
);
include.push(...transitiveDepsToInclude);
include.push(...transitiveDepsToInclude);
}

return { include, exclude };
}
Expand Down Expand Up @@ -372,6 +380,19 @@ export interface Options {
*/
ignorePluginPreprocessors?: boolean | string[];

/**
* vite-plugin-svelte automatically handles excluding svelte libraries and reinclusion of their dependencies
* in vite.optimizeDeps.
*
* `disableDependencyReinclusion: true` disables all reinclusions
* `disableDependencyReinclusion: ['foo','bar']` disables reinclusions for dependencies of foo and bar
*
* This should be used for hybrid packages that contain both node and browser dependencies, eg Routify
*
* @default false
*/
disableDependencyReinclusion?: boolean | string[];

/**
* These options are considered experimental and breaking changes to them can occur in any release
*/
Expand Down
11 changes: 10 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.