From 6b68fd7a23dfae9f3be8042dfdfa7f4680bc67ee Mon Sep 17 00:00:00 2001 From: dominikg Date: Sat, 12 Nov 2022 12:41:03 +0100 Subject: [PATCH 01/14] feat: enable prebundleSvelteLibraries by default --- .changeset/calm-rules-push.md | 5 ++ docs/config.md | 8 ++- docs/faq.md | 30 ++++++++++- .../package-json-svelte-field.spec.ts | 15 +----- .../package-json-svelte-field/vite.config.js | 3 ++ .../__tests__/prebundle-svelte-deps.spec.ts | 54 +++++++++++++------ .../prebundle-svelte-deps/vite.config.js | 8 +++ .../vite-plugin-svelte/src/utils/options.ts | 9 ++-- 8 files changed, 97 insertions(+), 35 deletions(-) create mode 100644 .changeset/calm-rules-push.md diff --git a/.changeset/calm-rules-push.md b/.changeset/calm-rules-push.md new file mode 100644 index 000000000..1ffa1027e --- /dev/null +++ b/.changeset/calm-rules-push.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/vite-plugin-svelte': minor +--- + +enable `prebundleSvelteLibraries` by default diff --git a/docs/config.md b/docs/config.md index 1a3b6923f..06de9a185 100644 --- a/docs/config.md +++ b/docs/config.md @@ -204,9 +204,13 @@ A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patt ### prebundleSvelteLibraries - **Type:** `boolean` -- **Default:** `false` +- **Default:** `true` + + Enable support for Vite optimizeDeps to pre-bundle Svelte libraries. + + This option improves page loading for the dev server in most applications when using svelte component libraries. - Force Vite to pre-bundle Svelte libraries. Setting this `true` should improve initial page load performance, especially when using large Svelte libraries. See the [FAQ](./faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies) for details of the pre-bundling implementation. + See the [FAQ](./faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies) for details and how to fine-tune it for huge libraries. ## Experimental options diff --git a/docs/faq.md b/docs/faq.md index 3dd9e55c5..66c931e57 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -99,4 +99,32 @@ For reference, check out [windicss](https://github.com/windicss/vite-plugin-wind ### What is going on with Vite and `Pre-bundling dependencies:`? -Pre-bundling dependencies is an [optimization in Vite](https://vitejs.dev/guide/dep-pre-bundling.html). It is required for CJS dependencies, as Vite's development server only works with ES modules on the client side. Importantly for Svelte libraries and ESM modules, prebundling combines component libraries into a single file to speed up the initial page load. Try setting the [`prebundleSvelteLibraries`](./config.md#prebundleSvelteLibraries) option to `true` to speed things up. This will likely be enabled by default in future version of the plugin. +Pre-bundling dependencies is an [optimization in Vite](https://vitejs.dev/guide/dep-pre-bundling.html). + +It is required for CJS dependencies, as Vite's development server only works with ES modules on the client side. +Importantly for Svelte libraries and ESM modules, prebundling combines component libraries into a single file to speed up the initial page load. + +For huge libraries where you only import a few components this can lead to slower first start, as all components have to be compiled once, even if you never use them. +It also slows down re-prebundling, which can happen when vite discovers new dependencies or you change your svelte config. + +In that case, add these huge libraries to optimizeDeps.exclude and use deep imports to import the components you need. + +e.g. + +```js +// vite.config.js +export default defineConfig({ + optimizeDeps: { + exclude: ['svelte-2000-icons'] // do not pre-bundle svelte-2000-icons + } +}); +``` + +```html + + + +``` diff --git a/packages/e2e-tests/package-json-svelte-field/__tests__/package-json-svelte-field.spec.ts b/packages/e2e-tests/package-json-svelte-field/__tests__/package-json-svelte-field.spec.ts index 04563ab6a..beafe10c8 100644 --- a/packages/e2e-tests/package-json-svelte-field/__tests__/package-json-svelte-field.spec.ts +++ b/packages/e2e-tests/package-json-svelte-field/__tests__/package-json-svelte-field.spec.ts @@ -1,18 +1,5 @@ -import { getText, isBuild, readVitePrebundleMetadata } from '~utils'; +import { getText } from '~utils'; test('should render component imported via svelte field in package.json', async () => { expect(await getText('#test-id')).toBe('svelte field works'); }); - -if (!isBuild) { - test('should optimize nested cjs deps of excluded svelte deps', () => { - const metadataFile = readVitePrebundleMetadata(); - const metadata = JSON.parse(metadataFile); - const optimizedPaths = Object.keys(metadata.optimized); - expect(optimizedPaths).not.toContain('e2e-test-dep-svelte-nested'); - expect(optimizedPaths).not.toContain('e2e-test-dep-svelte-simple'); - expect(optimizedPaths).toContain( - 'e2e-test-dep-svelte-nested > e2e-test-dep-svelte-simple > e2e-test-dep-cjs-only' - ); - }); -} diff --git a/packages/e2e-tests/package-json-svelte-field/vite.config.js b/packages/e2e-tests/package-json-svelte-field/vite.config.js index 20e9a8e57..ef38d6754 100644 --- a/packages/e2e-tests/package-json-svelte-field/vite.config.js +++ b/packages/e2e-tests/package-json-svelte-field/vite.config.js @@ -4,6 +4,9 @@ import { defineConfig } from 'vite'; export default defineConfig(({ command, mode }) => { return { plugins: [svelte()], + optimizeDeps: { + exclude: ['e2e-test-dep-scss-only'] + }, build: { // make build faster by skipping transforms and minification target: 'esnext', diff --git a/packages/e2e-tests/prebundle-svelte-deps/__tests__/prebundle-svelte-deps.spec.ts b/packages/e2e-tests/prebundle-svelte-deps/__tests__/prebundle-svelte-deps.spec.ts index a04ab6c82..a5604d633 100644 --- a/packages/e2e-tests/prebundle-svelte-deps/__tests__/prebundle-svelte-deps.spec.ts +++ b/packages/e2e-tests/prebundle-svelte-deps/__tests__/prebundle-svelte-deps.spec.ts @@ -1,29 +1,27 @@ -import { browserLogs, getText, isBuild, readVitePrebundleMetadata } from '~utils'; +import { + browserLogs, + editFile, + getText, + isBuild, + readVitePrebundleMetadata, + waitForServerRestartAndReloadPage +} from '~utils'; -test('should not have failed requests', async () => { +async function expectPageToWork() { browserLogs.forEach((msg) => { expect(msg).not.toMatch('404'); }); -}); - -test('should render Hybrid import', async () => { expect(await getText('#hybrid .label')).toBe('dependency-import'); -}); - -test('should render Simple import', async () => { expect(await getText('#hybrid .label')).toBe('dependency-import'); -}); - -test('should render Nested import', async () => { expect(await getText('#nested #message')).toBe('nested'); expect(await getText('#nested #cjs-and-esm')).toBe('esm'); -}); - -test('should render api-only import', async () => { expect(await getText('#api-only')).toBe('api loaded: true'); -}); +} if (!isBuild) { + test('page works with pre-bundling enabled', async () => { + await expectPageToWork(); + }); test('should optimize svelte dependencies', () => { const metadataFile = readVitePrebundleMetadata(); const metadata = JSON.parse(metadataFile); @@ -39,4 +37,30 @@ if (!isBuild) { const optimizedPaths = Object.keys(metadata.optimized); expect(optimizedPaths).not.toContain('e2e-test-dep-scss-only'); }); + + test('page works with pre-bundling disabled', async () => { + editFile('svelte.config.js', (c) => + c.replace('prebundleSvelteLibraries: true', 'prebundleSvelteLibraries: false') + ); + await waitForServerRestartAndReloadPage(); + await expectPageToWork(); + const metadataFile = readVitePrebundleMetadata(); + const metadata = JSON.parse(metadataFile); + const optimizedPaths = Object.keys(metadata.optimized); + expect(optimizedPaths).not.toContain('e2e-test-dep-svelte-simple'); + expect(optimizedPaths).not.toContain('e2e-test-dep-svelte-hybrid'); + + // this is a bit surprising, we always include js-libraries using svelte + expect(optimizedPaths).toContain('e2e-test-dep-svelte-api-only'); + + expect(optimizedPaths).toContain('e2e-test-dep-svelte-hybrid > e2e-test-dep-cjs-only'); + expect(optimizedPaths).toContain('e2e-test-dep-svelte-simple > e2e-test-dep-cjs-only'); + expect(optimizedPaths).toContain( + 'e2e-test-dep-svelte-nested > e2e-test-dep-svelte-simple > e2e-test-dep-cjs-only' + ); + }); +} else { + test('page works', async () => { + await expectPageToWork(); + }); } diff --git a/packages/e2e-tests/prebundle-svelte-deps/vite.config.js b/packages/e2e-tests/prebundle-svelte-deps/vite.config.js index d6ba95770..7088684b7 100644 --- a/packages/e2e-tests/prebundle-svelte-deps/vite.config.js +++ b/packages/e2e-tests/prebundle-svelte-deps/vite.config.js @@ -13,5 +13,13 @@ export default defineConfig({ // make build faster by skipping transforms and minification target: 'esnext', minify: false + }, + server: { + watch: { + // During tests we edit the files too fast and sometimes chokidar + // misses change events, so enforce polling for consistency + usePolling: true, + interval: 100 + } } }); diff --git a/packages/vite-plugin-svelte/src/utils/options.ts b/packages/vite-plugin-svelte/src/utils/options.ts index 34f43ffb3..a0c850d1a 100644 --- a/packages/vite-plugin-svelte/src/utils/options.ts +++ b/packages/vite-plugin-svelte/src/utils/options.ts @@ -131,7 +131,8 @@ export async function preResolveOptions( }; const defaultOptions: Partial = { extensions: ['.svelte'], - emitCss: true + emitCss: true, + prebundleSvelteLibraries: true }; const svelteConfig = convertPluginOptions( await loadSvelteConfig(viteConfigWithResolvedRoot, inlineOptions) @@ -551,9 +552,11 @@ export interface PluginOptions { disableDependencyReinclusion?: boolean | string[]; /** - * Force Vite to pre-bundle Svelte libraries + * Enable support for vite optimizeDeps to pre-bundle Svelte libraries * - * @default false + * to disable pre-bundling for a specific library, add it to optimizeDeps.exclude. + * + * @default true */ prebundleSvelteLibraries?: boolean; From d667f0a4581f2a6f664e5d01b65d53ba99262e8f Mon Sep 17 00:00:00 2001 From: dominikg Date: Sat, 12 Nov 2022 12:57:24 +0100 Subject: [PATCH 02/14] docs: add information about switching from deep imports to package imports for prebundled --- .changeset/calm-rules-push.md | 11 ++++++++++- docs/faq.md | 7 +++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.changeset/calm-rules-push.md b/.changeset/calm-rules-push.md index 1ffa1027e..9eef730cc 100644 --- a/.changeset/calm-rules-push.md +++ b/.changeset/calm-rules-push.md @@ -2,4 +2,13 @@ '@sveltejs/vite-plugin-svelte': minor --- -enable `prebundleSvelteLibraries` by default +enable `prebundleSvelteLibraries` by default to improve page loading for the dev server. + +If you are using deep imports for svelte libraries that are now prebundled, update your imports to use the package index instead. + +```diff +- import SomeComponent from 'some-library/src/SomeComponent.svelte' ++ import {SomeComponent} from 'some-library' +``` + +see [FAQ](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies) for more information about prebundleSvelteLibraries and how to tune it. diff --git a/docs/faq.md b/docs/faq.md index 66c931e57..195165665 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -104,6 +104,13 @@ Pre-bundling dependencies is an [optimization in Vite](https://vitejs.dev/guide/ It is required for CJS dependencies, as Vite's development server only works with ES modules on the client side. Importantly for Svelte libraries and ESM modules, prebundling combines component libraries into a single file to speed up the initial page load. +For prebundled svelte libraries it is recommended that you do not use deep imports. + +```diff +- import SomeComponent from 'some-library/src/SomeComponent.svelte' ++ import {SomeComponent} from 'some-library' +``` + For huge libraries where you only import a few components this can lead to slower first start, as all components have to be compiled once, even if you never use them. It also slows down re-prebundling, which can happen when vite discovers new dependencies or you change your svelte config. From d91aa556f47187ab4f6e07b0fcdc0e3e9f7bf25b Mon Sep 17 00:00:00 2001 From: dominikg Date: Mon, 21 Nov 2022 21:09:25 +0100 Subject: [PATCH 03/14] docs: update prebundling faq --- docs/faq.md | 69 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 195165665..bc351b735 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -99,39 +99,74 @@ For reference, check out [windicss](https://github.com/windicss/vite-plugin-wind ### What is going on with Vite and `Pre-bundling dependencies:`? -Pre-bundling dependencies is an [optimization in Vite](https://vitejs.dev/guide/dep-pre-bundling.html). +Prebundling dependencies is an [optimization in Vite](https://vitejs.dev/guide/dep-pre-bundling.html). + +> We only use prebundling during **development**, the following does not apply to or describe the built application It is required for CJS dependencies, as Vite's development server only works with ES modules on the client side. -Importantly for Svelte libraries and ESM modules, prebundling combines component libraries into a single file to speed up the initial page load. +Importantly for Svelte libraries and ES modules, it also reduces the number of http requests when you load a page from the dev server and caches files so subsequent starts are even faster. + +The way prebundling Svelte libraries affects your dev-server load times depends on the import style you use, index or deep: + +#### index imports -For prebundled svelte libraries it is recommended that you do not use deep imports. +offers better DX but can cause noticable delays on your machine, esp. for libraries with many files. ```diff -- import SomeComponent from 'some-library/src/SomeComponent.svelte' -+ import {SomeComponent} from 'some-library' +import {SomeComponent} from 'some-library' ++ only one request per library ++ intellisense for the whole library after first import +- compiles the whole library even if you only use a few components +- slower build and dev-server ssr ``` -For huge libraries where you only import a few components this can lead to slower first start, as all components have to be compiled once, even if you never use them. -It also slows down re-prebundling, which can happen when vite discovers new dependencies or you change your svelte config. +#### deep imports + +offers snappier dev and faster builds for libraries with many files at the expense of some DX + +```diff +import SomeComponent from 'some-library/src/SomeComponent.svelte' ++ compiles only the components you import ++ faster build and dev-server ssr +- one request per import can slow down initial load if you use a lot of components +- intellisense only for imported components +``` + +#### a word on import (re-)writing with plugins or preprocessors (auto-import, optimizeImports etc) + +**Do not use them in combination with prebundling!** -In that case, add these huge libraries to optimizeDeps.exclude and use deep imports to import the components you need. +Prebundling works by reading your .svelte files from disk. scanning them for imports. It cannot detect +added/changed/removed imports and these then cause extra requests, delays and render the prebundled files from the initial scan moot. +If you prefer to use these tools, please exclude the libraries you use them with from prebundling. -e.g. +#### excluding libraries from prebundling + +If you want to disable prebundling for a single library, use optimizeDeps.exclude ```js // vite.config.js export default defineConfig({ optimizeDeps: { - exclude: ['svelte-2000-icons'] // do not pre-bundle svelte-2000-icons + exclude: ['some-library'] // do not pre-bundle some-library } }); ``` -```html - - - +Or disable it for all Svelte libraries + +```js +// svelte.config.js +export default { + vitePlugin: { + prebundleSvelteLibraries: false + } +}; ``` + +#### so what should i do? + +There is no golden rule, but follow these recommendations: + +1. **never** combine auto-import or optimizeImports with prebundling +2. check the compile stats during dev to help deciding which import style works best for your app From c935cecba44d0c1e79cb4f9d6e60d9cb6d40fffe Mon Sep 17 00:00:00 2001 From: dominikg Date: Mon, 21 Nov 2022 21:13:00 +0100 Subject: [PATCH 04/14] docs: update changeset to remove outdated advice --- .changeset/calm-rules-push.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.changeset/calm-rules-push.md b/.changeset/calm-rules-push.md index 9eef730cc..0b54258e0 100644 --- a/.changeset/calm-rules-push.md +++ b/.changeset/calm-rules-push.md @@ -4,11 +4,4 @@ enable `prebundleSvelteLibraries` by default to improve page loading for the dev server. -If you are using deep imports for svelte libraries that are now prebundled, update your imports to use the package index instead. - -```diff -- import SomeComponent from 'some-library/src/SomeComponent.svelte' -+ import {SomeComponent} from 'some-library' -``` - -see [FAQ](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies) for more information about prebundleSvelteLibraries and how to tune it. +see the [FAQ](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies) for more information about `prebundleSvelteLibraries` and how to tune it. From fff972bd67b5a49abb9c377e0ad65e272be78321 Mon Sep 17 00:00:00 2001 From: Dominik G Date: Mon, 21 Nov 2022 21:14:28 +0100 Subject: [PATCH 05/14] docs: Apply suggestions from code review Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com> --- docs/config.md | 4 ++-- packages/vite-plugin-svelte/src/utils/options.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/config.md b/docs/config.md index 06de9a185..4b3572e29 100644 --- a/docs/config.md +++ b/docs/config.md @@ -206,9 +206,9 @@ A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patt - **Type:** `boolean` - **Default:** `true` - Enable support for Vite optimizeDeps to pre-bundle Svelte libraries. + Enable [Vite's dependency prebundling](https://vitejs.dev/guide/dep-pre-bundling.html) for Svelte libraries. - This option improves page loading for the dev server in most applications when using svelte component libraries. + This option improves page loading for the dev server in most applications when using Svelte component libraries. See the [FAQ](./faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies) for details and how to fine-tune it for huge libraries. diff --git a/packages/vite-plugin-svelte/src/utils/options.ts b/packages/vite-plugin-svelte/src/utils/options.ts index a0c850d1a..cdbe17800 100644 --- a/packages/vite-plugin-svelte/src/utils/options.ts +++ b/packages/vite-plugin-svelte/src/utils/options.ts @@ -552,9 +552,9 @@ export interface PluginOptions { disableDependencyReinclusion?: boolean | string[]; /** - * Enable support for vite optimizeDeps to pre-bundle Svelte libraries + * Enable support for Vite's dependency optimization to prebundle Svelte libraries * - * to disable pre-bundling for a specific library, add it to optimizeDeps.exclude. + * to disable prebundling for a specific library, add it to `optimizeDeps.exclude`. * * @default true */ From c43423b9b1fa7e5f4bbf3afbc197eae5bc95ec1c Mon Sep 17 00:00:00 2001 From: dominikg Date: Mon, 21 Nov 2022 23:07:45 +0100 Subject: [PATCH 06/14] docs: improve recommendations --- docs/faq.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index bc351b735..f5e85ac3d 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -164,9 +164,11 @@ export default { }; ``` -#### so what should i do? +#### recommendations -There is no golden rule, but follow these recommendations: +There is no golden rule, but you can follow these recommendations: -1. **never** combine auto-import or optimizeImports with prebundling -2. check the compile stats during dev to help deciding which import style works best for your app +1. **Never** combine auto-import or optimizeImports with prebundling +2. Start with index imports and if your dev-server or build process feels slow, check compile stats to see if switching to deep imports can improve the experience. +3. Do not mix deep and index imports for the same library, use one style consistently. +4. Use different import styles for different libraries where it helps. E.g. deep imports for the few icons of that one huge icon library, but index import for the component library that is heavily used. From eccc49149e0ac2fbdeccb2c746886c6eb0dcc952 Mon Sep 17 00:00:00 2001 From: dominikg Date: Mon, 21 Nov 2022 23:08:53 +0100 Subject: [PATCH 07/14] fix: make sure prebundleSvelteLibraries is not used for build or ssr --- packages/vite-plugin-svelte/src/utils/options.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/vite-plugin-svelte/src/utils/options.ts b/packages/vite-plugin-svelte/src/utils/options.ts index cdbe17800..01b66fcb3 100644 --- a/packages/vite-plugin-svelte/src/utils/options.ts +++ b/packages/vite-plugin-svelte/src/utils/options.ts @@ -369,6 +369,8 @@ export async function buildExtraViteConfig( if (options.prebundleSvelteLibraries) { extraViteConfig.optimizeDeps = { ...extraViteConfig.optimizeDeps, + // only prebundle for dev, build isn't working with vite-plugin-svelte + disabled: 'build', // Experimental Vite API to allow these extensions to be scanned and prebundled // @ts-ignore extensions: options.extensions ?? ['.svelte'], @@ -379,6 +381,10 @@ export async function buildExtraViteConfig( plugins: [{ name: facadeEsbuildSveltePluginName, setup: () => {} }] } }; + extraViteConfig.ssr.optimizeDeps = { + // do not prebundle for ssr, not working with vite-plugin-svelte + disabled: true + }; } // enable hmrPartialAccept if not explicitly disabled From b1a8aff98aaf5159bbc6b95e62f42732bc3236e5 Mon Sep 17 00:00:00 2001 From: Dominik G Date: Tue, 22 Nov 2022 00:00:23 +0100 Subject: [PATCH 08/14] docs: Apply suggestions from code review Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com> --- docs/faq.md | 2 +- packages/vite-plugin-svelte/src/utils/options.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index f5e85ac3d..ea1206089 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -136,7 +136,7 @@ import SomeComponent from 'some-library/src/SomeComponent.svelte' **Do not use them in combination with prebundling!** -Prebundling works by reading your .svelte files from disk. scanning them for imports. It cannot detect +Prebundling works by reading your `.svelte` files from disk and scanning them for imports. It cannot detect added/changed/removed imports and these then cause extra requests, delays and render the prebundled files from the initial scan moot. If you prefer to use these tools, please exclude the libraries you use them with from prebundling. diff --git a/packages/vite-plugin-svelte/src/utils/options.ts b/packages/vite-plugin-svelte/src/utils/options.ts index 01b66fcb3..ce00ec299 100644 --- a/packages/vite-plugin-svelte/src/utils/options.ts +++ b/packages/vite-plugin-svelte/src/utils/options.ts @@ -558,9 +558,9 @@ export interface PluginOptions { disableDependencyReinclusion?: boolean | string[]; /** - * Enable support for Vite's dependency optimization to prebundle Svelte libraries + * Enable support for Vite's dependency optimization to prebundle Svelte libraries. * - * to disable prebundling for a specific library, add it to `optimizeDeps.exclude`. + * To disable prebundling for a specific library, add it to `optimizeDeps.exclude`. * * @default true */ From 3ef1c80977c77a6d05da78615ba47e124cbee781 Mon Sep 17 00:00:00 2001 From: Dominik G Date: Tue, 22 Nov 2022 09:45:29 +0100 Subject: [PATCH 09/14] docs: Apply suggestions from code review Co-authored-by: Bjorn Lu --- docs/faq.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index ea1206089..b44f9d343 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -108,21 +108,21 @@ Importantly for Svelte libraries and ES modules, it also reduces the number of h The way prebundling Svelte libraries affects your dev-server load times depends on the import style you use, index or deep: -#### index imports +#### Index imports -offers better DX but can cause noticable delays on your machine, esp. for libraries with many files. +Offers better DX but can cause noticable delays on your machine, especially for libraries with many files. ```diff -import {SomeComponent} from 'some-library' +import { SomeComponent } from 'some-library' + only one request per library + intellisense for the whole library after first import - compiles the whole library even if you only use a few components - slower build and dev-server ssr ``` -#### deep imports +#### Deep imports -offers snappier dev and faster builds for libraries with many files at the expense of some DX +Offers snappier dev and faster builds for libraries with many files at the expense of some DX ```diff import SomeComponent from 'some-library/src/SomeComponent.svelte' @@ -132,7 +132,7 @@ import SomeComponent from 'some-library/src/SomeComponent.svelte' - intellisense only for imported components ``` -#### a word on import (re-)writing with plugins or preprocessors (auto-import, optimizeImports etc) +#### Rewriting imports with plugins or preprocessors **Do not use them in combination with prebundling!** @@ -140,9 +140,9 @@ Prebundling works by reading your `.svelte` files from disk and scanning them fo added/changed/removed imports and these then cause extra requests, delays and render the prebundled files from the initial scan moot. If you prefer to use these tools, please exclude the libraries you use them with from prebundling. -#### excluding libraries from prebundling +#### Excluding libraries from prebundling -If you want to disable prebundling for a single library, use optimizeDeps.exclude +If you want to disable prebundling for a single library, use `optimizeDeps.exclude` ```js // vite.config.js @@ -164,7 +164,7 @@ export default { }; ``` -#### recommendations +#### Recommendations There is no golden rule, but you can follow these recommendations: From df161700e7c2a9fb5535b1db8c47f885273ef321 Mon Sep 17 00:00:00 2001 From: dominikg Date: Tue, 22 Nov 2022 10:04:28 +0100 Subject: [PATCH 10/14] docs: update follow-up wording after previous changes --- docs/faq.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index b44f9d343..a360406ff 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -134,7 +134,7 @@ import SomeComponent from 'some-library/src/SomeComponent.svelte' #### Rewriting imports with plugins or preprocessors -**Do not use them in combination with prebundling!** +**Do not use it in combination with prebundling!** Prebundling works by reading your `.svelte` files from disk and scanning them for imports. It cannot detect added/changed/removed imports and these then cause extra requests, delays and render the prebundled files from the initial scan moot. @@ -168,7 +168,7 @@ export default { There is no golden rule, but you can follow these recommendations: -1. **Never** combine auto-import or optimizeImports with prebundling +1. **Never** combine plugins or preprocessors that rewrite imports with prebundling 2. Start with index imports and if your dev-server or build process feels slow, check compile stats to see if switching to deep imports can improve the experience. 3. Do not mix deep and index imports for the same library, use one style consistently. 4. Use different import styles for different libraries where it helps. E.g. deep imports for the few icons of that one huge icon library, but index import for the component library that is heavily used. From 4413ff45cdb701e7ac8f844819c6d4ed24bbe149 Mon Sep 17 00:00:00 2001 From: dominikg Date: Tue, 22 Nov 2022 12:13:41 +0100 Subject: [PATCH 11/14] fix: only enable prebundleSvelteLibraries for dev, log warnings if it is enabled during build or ssr --- .changeset/calm-rules-push.md | 2 +- docs/faq.md | 5 ++ .../vite-plugin-svelte/src/utils/options.ts | 55 ++++++++++++++++--- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/.changeset/calm-rules-push.md b/.changeset/calm-rules-push.md index 0b54258e0..288abd255 100644 --- a/.changeset/calm-rules-push.md +++ b/.changeset/calm-rules-push.md @@ -2,6 +2,6 @@ '@sveltejs/vite-plugin-svelte': minor --- -enable `prebundleSvelteLibraries` by default to improve page loading for the dev server. +enable `prebundleSvelteLibraries` during dev by default to improve page loading for the dev server. see the [FAQ](https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#what-is-going-on-with-vite-and-pre-bundling-dependencies) for more information about `prebundleSvelteLibraries` and how to tune it. diff --git a/docs/faq.md b/docs/faq.md index a360406ff..2fc34ecd7 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -172,3 +172,8 @@ There is no golden rule, but you can follow these recommendations: 2. Start with index imports and if your dev-server or build process feels slow, check compile stats to see if switching to deep imports can improve the experience. 3. Do not mix deep and index imports for the same library, use one style consistently. 4. Use different import styles for different libraries where it helps. E.g. deep imports for the few icons of that one huge icon library, but index import for the component library that is heavily used. + +#### I get a warning `Incompatible options: prebundleSvelteLibraries ...` + +This warning only occurs if you use non-default settings in your vite config that can cause problems in combination with prebundleSvelteLibraries. +You should not use prebundleSvelteLibraries during build or for ssr, disable one of the incompatible options to make that warning (and subsequent errors) go away. diff --git a/packages/vite-plugin-svelte/src/utils/options.ts b/packages/vite-plugin-svelte/src/utils/options.ts index ec5745566..7aabaaf91 100644 --- a/packages/vite-plugin-svelte/src/utils/options.ts +++ b/packages/vite-plugin-svelte/src/utils/options.ts @@ -134,10 +134,11 @@ export async function preResolveOptions( ...viteUserConfig, root: resolveViteRoot(viteUserConfig) }; + const isBuild = viteEnv.command === 'build'; const defaultOptions: Partial = { extensions: ['.svelte'], emitCss: true, - prebundleSvelteLibraries: true + prebundleSvelteLibraries: !isBuild }; const svelteConfig = convertPluginOptions( await loadSvelteConfig(viteConfigWithResolvedRoot, inlineOptions) @@ -145,7 +146,7 @@ export async function preResolveOptions( const extraOptions: Partial = { root: viteConfigWithResolvedRoot.root!, - isBuild: viteEnv.command === 'build', + isBuild, isServe: viteEnv.command === 'serve', isDebug: process.env.DEBUG != null }; @@ -367,8 +368,6 @@ export async function buildExtraViteConfig( if (options.prebundleSvelteLibraries) { extraViteConfig.optimizeDeps = { ...extraViteConfig.optimizeDeps, - // only prebundle for dev, build isn't working with vite-plugin-svelte - disabled: 'build', // Experimental Vite API to allow these extensions to be scanned and prebundled // @ts-ignore extensions: options.extensions ?? ['.svelte'], @@ -379,10 +378,6 @@ export async function buildExtraViteConfig( plugins: [{ name: facadeEsbuildSveltePluginName, setup: () => {} }] } }; - extraViteConfig.ssr.optimizeDeps = { - // do not prebundle for ssr, not working with vite-plugin-svelte - disabled: true - }; } // enable hmrPartialAccept if not explicitly disabled @@ -395,9 +390,53 @@ export async function buildExtraViteConfig( log.debug('enabling "experimental.hmrPartialAccept" in vite config'); extraViteConfig.experimental = { hmrPartialAccept: true }; } + validateViteConfig(extraViteConfig, config, options); return extraViteConfig; } +function validateViteConfig( + extraViteConfig: Partial, + config: UserConfig, + options: PreResolvedOptions +) { + const { prebundleSvelteLibraries, isBuild } = options; + if (prebundleSvelteLibraries) { + const isEnabled = (option: 'dev' | 'build' | boolean) => + option !== true && option != (isBuild ? 'build' : 'dev'); + const logWarning = (name: string, value: 'dev' | 'build' | boolean, recommendation: string) => + log.warn.once( + `Incompatible options: \`prebundleSvelteLibraries: true\` and vite \`${name}: ${JSON.stringify( + value + )}\` ${isBuild ? 'during build.' : '.'} ${recommendation}` + ); + const viteOptimizeDepsDisabled = config.optimizeDeps?.disabled ?? 'build'; // fall back to vite default + const viteSsrOptimizeDepsDisabled = config.ssr?.optimizeDeps?.disabled ?? true; // fall back to undocumented vite default + const isOptimizeDepsEnabled = isEnabled(viteOptimizeDepsDisabled); + const isSsrOptimizeDepsEnabled = isEnabled(viteSsrOptimizeDepsDisabled); + if (!isBuild && !isOptimizeDepsEnabled) { + logWarning( + 'optimizeDeps.disabled', + viteOptimizeDepsDisabled, + 'Forcing `optimizeDeps.disabled: "build"`. Disable prebundleSvelteLibraries or update your vite config to enable optimizeDeps during dev.' + ); + extraViteConfig.optimizeDeps!.disabled = 'build'; + } else if (isBuild && isOptimizeDepsEnabled) { + logWarning( + 'optimizeDeps.disabled', + viteOptimizeDepsDisabled, + 'Disable optimizeDeps or prebundleSvelteLibraries for build if you experience errors.' + ); + } + if (isSsrOptimizeDepsEnabled) { + logWarning( + 'ssr.optimizeDeps.disabled', + viteSsrOptimizeDepsDisabled, + 'Disable ssr.optimizeDeps or prebundleSvelteLibraries if you experience errors.' + ); + } + } +} + async function buildExtraConfigForDependencies(options: PreResolvedOptions, config: UserConfig) { // extra handling for svelte dependencies in the project const depsConfig = await crawlFrameworkPkgs({ From 076a8ad5b7cadb71eeb0fe6ffeef8486195104bc Mon Sep 17 00:00:00 2001 From: dominikg Date: Tue, 22 Nov 2022 12:31:29 +0100 Subject: [PATCH 12/14] docs: update default value in docs --- docs/config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config.md b/docs/config.md index 4b3572e29..e6aa9b7a6 100644 --- a/docs/config.md +++ b/docs/config.md @@ -204,7 +204,7 @@ A [picomatch pattern](https://github.com/micromatch/picomatch), or array of patt ### prebundleSvelteLibraries - **Type:** `boolean` -- **Default:** `true` +- **Default:** `true` for dev, `false` for build Enable [Vite's dependency prebundling](https://vitejs.dev/guide/dep-pre-bundling.html) for Svelte libraries. From 1c657b14a55f00dcdc1d1995dfbb6b618d0ccac2 Mon Sep 17 00:00:00 2001 From: dominikg Date: Tue, 22 Nov 2022 13:22:53 +0100 Subject: [PATCH 13/14] fix: remove warning for ssr.optimizeDeps, we don't add the svelte esbuild plugin for that so it does whatever, but won't break because of prebundleSvelteLibraries --- packages/vite-plugin-svelte/src/utils/options.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/vite-plugin-svelte/src/utils/options.ts b/packages/vite-plugin-svelte/src/utils/options.ts index 038d64765..c31fff6bb 100644 --- a/packages/vite-plugin-svelte/src/utils/options.ts +++ b/packages/vite-plugin-svelte/src/utils/options.ts @@ -419,9 +419,7 @@ function validateViteConfig( )}\` ${isBuild ? 'during build.' : '.'} ${recommendation}` ); const viteOptimizeDepsDisabled = config.optimizeDeps?.disabled ?? 'build'; // fall back to vite default - const viteSsrOptimizeDepsDisabled = config.ssr?.optimizeDeps?.disabled ?? true; // fall back to undocumented vite default const isOptimizeDepsEnabled = isEnabled(viteOptimizeDepsDisabled); - const isSsrOptimizeDepsEnabled = isEnabled(viteSsrOptimizeDepsDisabled); if (!isBuild && !isOptimizeDepsEnabled) { logWarning( 'optimizeDeps.disabled', @@ -436,13 +434,6 @@ function validateViteConfig( 'Disable optimizeDeps or prebundleSvelteLibraries for build if you experience errors.' ); } - if (isSsrOptimizeDepsEnabled) { - logWarning( - 'ssr.optimizeDeps.disabled', - viteSsrOptimizeDepsDisabled, - 'Disable ssr.optimizeDeps or prebundleSvelteLibraries if you experience errors.' - ); - } } } From 06b9de434b118e87f6891eacc66bd9b2ef1ddc64 Mon Sep 17 00:00:00 2001 From: Dominik G Date: Tue, 22 Nov 2022 13:28:53 +0100 Subject: [PATCH 14/14] Apply suggestions from code review Co-authored-by: Bjorn Lu --- packages/vite-plugin-svelte/src/utils/options.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vite-plugin-svelte/src/utils/options.ts b/packages/vite-plugin-svelte/src/utils/options.ts index c31fff6bb..f6a270819 100644 --- a/packages/vite-plugin-svelte/src/utils/options.ts +++ b/packages/vite-plugin-svelte/src/utils/options.ts @@ -411,7 +411,7 @@ function validateViteConfig( const { prebundleSvelteLibraries, isBuild } = options; if (prebundleSvelteLibraries) { const isEnabled = (option: 'dev' | 'build' | boolean) => - option !== true && option != (isBuild ? 'build' : 'dev'); + option !== true && option !== (isBuild ? 'build' : 'dev'); const logWarning = (name: string, value: 'dev' | 'build' | boolean, recommendation: string) => log.warn.once( `Incompatible options: \`prebundleSvelteLibraries: true\` and vite \`${name}: ${JSON.stringify( @@ -622,7 +622,7 @@ export interface PluginOptions { * * To disable prebundling for a specific library, add it to `optimizeDeps.exclude`. * - * @default true + * @default true for dev, false for build */ prebundleSvelteLibraries?: boolean;