Skip to content

Commit 4645ad5

Browse files
Rich Harrisbenmccann
Rich Harris
andauthored
force Vite to bundle component libraries in SSR (#1148)
* force Vite to bundle component libraries in SSR - fixes #904 * get things working * lockfile, again * update docs * Update documentation/faq/70-packages.md Co-authored-by: Ben McCann <[email protected]> * remove ssr config from svelte.config.cjs * changeset Co-authored-by: Ben McCann <[email protected]>
1 parent abf0248 commit 4645ad5

File tree

9 files changed

+63
-83
lines changed

9 files changed

+63
-83
lines changed

.changeset/few-points-taste.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
Force Vite to bundle Svelte component libraries in SSR

.changeset/nervous-steaks-add.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'create-svelte': patch
3+
---
4+
5+
Remove obsolete vite.ssr config from template

documentation/faq/70-packages.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
question: How do I fix the error I'm getting trying to include a package?
33
---
44

5-
Most of these issues come from Vite trying to deal with non-ESM libraries. You may find it helpful to search for your error message in [the Vite issue tracker](https://github.com./vitejs/vite/issues).
5+
Most of these issues come from Vite trying to deal with non-ESM libraries. You may find it helpful to search for your error message in [the Vite issue tracker](https://github.com./vitejs/vite/issues).
66

77
There are a number of known Vite issues, which cause errors in the following circumstances:
8-
- [packages which use `exports` instead of `module.exports`](https://github.com./vitejs/vite/issues/2579).
8+
9+
- [CommonJS packages](https://github.com./vitejs/vite/issues/2579).
910
- [ESM library that imports a CJS library](https://github.com./vitejs/vite/issues/3024)
1011
- [some UMD libraries](https://github.com./vitejs/vite/issues/2679)
1112

1213
Vite 2 is a relatively new library and over time we expect it to become easier to use non-ESM libraries with Vite. However, you might also consider asking the library author to distribute an ESM version of their package or even converting the source for the package entirely to ESM. ESM is now the standard way to write JavaScript libraries and while there are a lot of legacy packages out there the ecosystem will become much easier to work with as more libraries convert to ESM.
1314

14-
The most common workarounds would be to try moving the package between `dependencies` and `devDependencies` or trying to `include` or `exclude` it in `optimizeDeps`. SvelteKit currently asks Vite to bundle all your `dependencies` for easier deployment to serverless environment. This means that by moving a dependency to `devDependencies` Vite is no longer asked to bundle it. This may sidestep issues Vite encounters in trying to bundle certain libraries. Avoiding Vite bundling especially works for `adapter-node` and `adapter-static` where the bundling isn't necessary since you're not running in a serverless environment. We are considering [better alternatives](https://github.com./sveltejs/kit/issues/1016) to make this setup easier. You should also add any Svelte components to `ssr.noExternal`. [We hope to do this automatically in the future](https://github.com./sveltejs/kit/issues/904).
15+
The most common workarounds would be to `include` or `exclude` the offending package in [`optimizeDeps`](https://vitejs.dev/config/#dep-optimization-options), or to add it to [`ssr.external` or `ssr.noExternal`](https://vitejs.dev/config/#ssr-options).

packages/create-svelte/shared/+typescript/svelte.config.cjs

+1-7
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,6 @@ module.exports = {
1515
adapter: node(),
1616

1717
// hydrate the <div id="svelte"> element in src/app.html
18-
target: '#svelte',
19-
20-
vite: {
21-
ssr: {
22-
noExternal: Object.keys(pkg.dependencies || {})
23-
}
24-
}
18+
target: '#svelte'
2519
}
2620
};

packages/create-svelte/shared/-typescript/svelte.config.cjs

+1-7
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ module.exports = {
1010
adapter: node(),
1111

1212
// hydrate the <div id="svelte"> element in src/app.html
13-
target: '#svelte',
14-
15-
vite: {
16-
ssr: {
17-
noExternal: Object.keys(pkg.dependencies || {})
18-
}
19-
}
13+
target: '#svelte'
2014
}
2115
};

packages/kit/src/core/build/index.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import fs from 'fs';
22
import path from 'path';
33
import { rimraf } from '../filesystem/index.js';
44
import create_manifest_data from '../../core/create_manifest_data/index.js';
5-
import { copy_assets, posixify, resolve_entry } from '../utils.js';
5+
import { copy_assets, get_no_external, posixify, resolve_entry } from '../utils.js';
66
import { create_app } from '../../core/create_app/index.js';
77
import vite from 'vite';
88
import svelte from '@sveltejs/vite-plugin-svelte';
@@ -438,11 +438,9 @@ async function build_server(
438438
// @ts-ignore
439439
ssr: {
440440
...user_config.ssr,
441-
noExternal: [
442-
'svelte',
443-
'@sveltejs/kit',
444-
...((user_config.ssr && user_config.ssr.noExternal) || [])
445-
]
441+
// note to self: this _might_ need to be ['svelte', '@sveltejs/kit', ...get_no_external()]
442+
// but I'm honestly not sure. roll with this for now and see if it's ok
443+
noExternal: get_no_external(cwd, user_config.ssr && user_config.ssr.noExternal)
446444
},
447445
optimizeDeps: {
448446
entries: []

packages/kit/src/core/dev/index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { create_app } from '../../core/create_app/index.js';
1111
import { rimraf } from '../filesystem/index.js';
1212
import { ssr } from '../../runtime/server/index.js';
1313
import { getRawBody } from '../http/index.js';
14-
import { copy_assets } from '../utils.js';
14+
import { copy_assets, get_no_external } from '../utils.js';
1515
import svelte from '@sveltejs/vite-plugin-svelte';
1616
import { get_server } from '../server/index.js';
1717
import '../../install-fetch.js';
@@ -107,6 +107,10 @@ class Watcher extends EventEmitter {
107107
optimizeDeps: {
108108
...user_config.optimizeDeps,
109109
entries: []
110+
},
111+
ssr: {
112+
...user_config.ssr,
113+
noExternal: get_no_external(this.cwd, user_config.ssr && user_config.ssr.noExternal)
110114
}
111115
});
112116

packages/kit/src/core/utils.js

+32
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,35 @@ export function resolve_entry(entry) {
7474
export function posixify(str) {
7575
return str.replace(/\\/g, '/');
7676
}
77+
78+
/**
79+
* Get a list of packages that use pkg.svelte, so they can be added
80+
* to ssr.noExternal. This is done on a best-effort basis to reduce
81+
* the frequency of 'Must use import to load ES Module' and similar
82+
* @param {string} cwd
83+
* @returns {string[]}
84+
*/
85+
function find_svelte_packages(cwd) {
86+
const pkg_file = path.join(cwd, 'package.json');
87+
if (!fs.existsSync(pkg_file)) return [];
88+
89+
const pkg = JSON.parse(fs.readFileSync(pkg_file, 'utf8'));
90+
91+
const deps = [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.devDependencies || {})];
92+
93+
return deps.filter((dep) => {
94+
const dep_pkg_file = path.join(cwd, 'node_modules', dep, 'package.json');
95+
if (!fs.existsSync(dep_pkg_file)) return false;
96+
97+
const dep_pkg = JSON.parse(fs.readFileSync(dep_pkg_file, 'utf-8'));
98+
return !!dep_pkg.svelte;
99+
});
100+
}
101+
102+
/**
103+
* @param {string} cwd
104+
* @param {string[]} [user_specified_deps]
105+
*/
106+
export function get_no_external(cwd, user_specified_deps = []) {
107+
return [...user_specified_deps, ...find_svelte_packages(cwd)];
108+
}

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)