@sveltejs/vite-plugin-svelte 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/vite-plugin-svelte",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "license": "MIT",
5
5
  "author": "dominikg",
6
6
  "files": [
@@ -46,7 +46,8 @@
46
46
  "deepmerge": "^4.2.2",
47
47
  "kleur": "^4.1.5",
48
48
  "magic-string": "^0.26.7",
49
- "svelte-hmr": "^0.15.0"
49
+ "svelte-hmr": "^0.15.1",
50
+ "vitefu": "^0.2.1"
50
51
  },
51
52
  "peerDependencies": {
52
53
  "diff-match-patch": "^1.0.5",
@@ -62,10 +63,10 @@
62
63
  "@types/debug": "^4.1.7",
63
64
  "@types/diff-match-patch": "^1.0.32",
64
65
  "diff-match-patch": "^1.0.5",
65
- "esbuild": "^0.15.13",
66
+ "esbuild": "^0.15.14",
66
67
  "rollup": "^2.79.1",
67
- "svelte": "^3.52.0",
68
- "tsup": "^6.4.0",
68
+ "svelte": "3.53.1",
69
+ "tsup": "^6.5.0",
69
70
  "vite": "^3.2.3"
70
71
  },
71
72
  "scripts": {
package/src/index.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import { HmrContext, ModuleNode, Plugin, ResolvedConfig, UserConfig } from 'vite';
3
+ // eslint-disable-next-line node/no-missing-import
4
+ import { isDepExcluded } from 'vitefu';
3
5
  import { handleHotUpdate } from './handle-hot-update';
4
6
  import { log, logCompilerWarnings } from './utils/log';
5
7
  import { CompileData, createCompileSvelte } from './utils/compile';
@@ -68,7 +70,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
68
70
  // @ts-expect-error temporarily lend the options variable until fixed in configResolved
69
71
  options = await preResolveOptions(inlineOptions, config, configEnv);
70
72
  // extra vite config
71
- const extraViteConfig = buildExtraViteConfig(options, config);
73
+ const extraViteConfig = await buildExtraViteConfig(options, config);
72
74
  log.debug('additional vite config', extraViteConfig);
73
75
  return extraViteConfig;
74
76
  },
@@ -154,21 +156,32 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
154
156
  }
155
157
  return resolvedSvelteSSR;
156
158
  }
157
- try {
158
- const resolved = resolveViaPackageJsonSvelte(importee, importer, cache);
159
- if (resolved) {
160
- log.debug(
161
- `resolveId resolved ${resolved} via package.json svelte field of ${importee}`
159
+ //@ts-expect-error scan
160
+ const scan = !!opts?.scan; // scanner phase of optimizeDeps
161
+ const isPrebundled =
162
+ options.prebundleSvelteLibraries &&
163
+ viteConfig.optimizeDeps?.disabled !== true &&
164
+ viteConfig.optimizeDeps?.disabled !== (options.isBuild ? 'build' : 'dev') &&
165
+ !isDepExcluded(importee, viteConfig.optimizeDeps?.exclude ?? []);
166
+ // for prebundled libraries we let vite resolve the prebundling result
167
+ // for ssr, during scanning and non-prebundled, we do it
168
+ if (ssr || scan || !isPrebundled) {
169
+ try {
170
+ const resolved = await resolveViaPackageJsonSvelte(importee, importer, cache);
171
+ if (resolved) {
172
+ log.debug(
173
+ `resolveId resolved ${resolved} via package.json svelte field of ${importee}`
174
+ );
175
+ return resolved;
176
+ }
177
+ } catch (e) {
178
+ log.debug.once(
179
+ `error trying to resolve ${importee} from ${importer} via package.json svelte field `,
180
+ e
162
181
  );
163
- return resolved;
182
+ // this error most likely happens due to non-svelte related importee/importers so swallow it here
183
+ // in case it really way a svelte library, users will notice anyway. (lib not working due to failed resolve)
164
184
  }
165
- } catch (e) {
166
- log.debug.once(
167
- `error trying to resolve ${importee} from ${importer} via package.json svelte field `,
168
- e
169
- );
170
- // this error most likely happens due to non-svelte related importee/importers so swallow it here
171
- // in case it really way a svelte library, users will notice anyway. (lib not working due to failed resolve)
172
185
  }
173
186
  },
174
187
 
@@ -0,0 +1,102 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { compareToSvelte, atLeastSvelte, parseVersion } from '../svelte-version';
3
+ import { VERSION } from 'svelte/compiler';
4
+ const svelteVersion = parseVersion(VERSION);
5
+ describe('svelte-version', () => {
6
+ describe('parseVersion', () => {
7
+ it('should fill major,minor,patch', () => {
8
+ expect(parseVersion('3')).toEqual([3, 0, 0]);
9
+ expect(parseVersion('3.1')).toEqual([3, 1, 0]);
10
+ });
11
+ it('should ignore additional segments', () => {
12
+ expect(parseVersion('1.2.3.4')).toEqual([1, 2, 3]);
13
+ });
14
+ });
15
+ describe('compareToSvelte', () => {
16
+ it('should return 0 for current', async () => {
17
+ expect(compareToSvelte(VERSION)).toBe(0);
18
+ });
19
+
20
+ it('should return 1 for patch bump', async () => {
21
+ const patch = svelteVersion.concat();
22
+ patch[2] += 1;
23
+ const patchBump = patch.join('.');
24
+ expect(compareToSvelte(patchBump)).toBe(1);
25
+ });
26
+ it('should return 1 for minor bump', async () => {
27
+ const minor = svelteVersion.concat();
28
+ minor[1] += 1;
29
+ const minorBump = minor.join('.');
30
+ expect(compareToSvelte(minorBump)).toBe(1);
31
+ });
32
+ it('should return 1 for major bump', async () => {
33
+ const major = svelteVersion.concat();
34
+ major[0] += 1;
35
+ const majorBump = major.join('.');
36
+ expect(compareToSvelte(majorBump)).toBe(1);
37
+ });
38
+
39
+ it('should return -1 for lower patch', async () => {
40
+ const patch = svelteVersion.concat();
41
+ patch[2] -= 1;
42
+ const lowerPatch = patch.join('.');
43
+ expect(compareToSvelte(lowerPatch)).toBe(-1);
44
+ });
45
+ it('should return -1 for lower minor', async () => {
46
+ const minor = svelteVersion.concat();
47
+ minor[1] -= 1;
48
+ const lowerMinor = minor.join('.');
49
+ expect(compareToSvelte(lowerMinor)).toBe(-1);
50
+ });
51
+ it('should return -1 for lower major', async () => {
52
+ const major = svelteVersion.concat();
53
+ major[0] -= 1;
54
+ const lowerMajor = major.join('.');
55
+ expect(compareToSvelte(lowerMajor)).toBe(-1);
56
+ });
57
+ });
58
+
59
+ describe('atLeastSvelte', () => {
60
+ it('should return true for current', async () => {
61
+ expect(atLeastSvelte(VERSION)).toBe(true);
62
+ });
63
+
64
+ it('should return false for higher patch', async () => {
65
+ const patch = svelteVersion.concat();
66
+ patch[2] += 1;
67
+ const patchBump = patch.join('.');
68
+ expect(atLeastSvelte(patchBump)).toBe(false);
69
+ });
70
+ it('should return false for higher minor', async () => {
71
+ const minor = svelteVersion.concat();
72
+ minor[1] += 1;
73
+ const minorBump = minor.join('.');
74
+ expect(atLeastSvelte(minorBump)).toBe(false);
75
+ });
76
+ it('should return false for higher major', async () => {
77
+ const major = svelteVersion.concat();
78
+ major[0] += 1;
79
+ const majorBump = major.join('.');
80
+ expect(atLeastSvelte(majorBump)).toBe(false);
81
+ });
82
+
83
+ it('should return true for lower patch', async () => {
84
+ const patch = svelteVersion.concat();
85
+ patch[2] -= 1;
86
+ const lowerPatch = patch.join('.');
87
+ expect(atLeastSvelte(lowerPatch)).toBe(true);
88
+ });
89
+ it('should return true for lower minor', async () => {
90
+ const minor = svelteVersion.concat();
91
+ minor[1] -= 1;
92
+ const lowerMinor = minor.join('.');
93
+ expect(atLeastSvelte(lowerMinor)).toBe(true);
94
+ });
95
+ it('should return true for lower major', async () => {
96
+ const major = svelteVersion.concat();
97
+ major[0] -= 1;
98
+ const lowerMajor = major.join('.');
99
+ expect(atLeastSvelte(lowerMajor)).toBe(true);
100
+ });
101
+ });
102
+ });
@@ -68,8 +68,9 @@ const _createCompileSvelte = (makeHot: Function) =>
68
68
  }
69
69
  : compileOptions;
70
70
  const compiled = compile(finalCode, finalCompileOptions);
71
-
72
- if (emitCss && compiled.css.code) {
71
+ const hasCss = compiled.css?.code?.trim().length > 0;
72
+ // compiler might not emit css with mode none or it may be empty
73
+ if (emitCss && hasCss) {
73
74
  // TODO properly update sourcemap?
74
75
  compiled.js.code += `\nimport ${JSON.stringify(cssId)};\n`;
75
76
  }
@@ -79,7 +80,7 @@ const _createCompileSvelte = (makeHot: Function) =>
79
80
  compiled.js.code = makeHot({
80
81
  id: filename,
81
82
  compiledCode: compiled.js.code,
82
- hotOptions: options.hot,
83
+ hotOptions: { ...options.hot, injectCss: options.hot?.injectCss === true && hasCss },
83
84
  compiled,
84
85
  originalCode: code,
85
86
  compileOptions: finalCompileOptions
@@ -1,130 +1,29 @@
1
- import { log } from './log';
2
1
  import path from 'path';
3
- import fs from 'fs';
4
- import { createRequire } from 'module';
2
+ import fs from 'fs/promises';
3
+ // eslint-disable-next-line node/no-missing-import
4
+ import { findDepPkgJsonPath } from 'vitefu';
5
5
 
6
- export function findRootSvelteDependencies(root: string, cwdFallback = true): SvelteDependency[] {
7
- log.debug(`findSvelteDependencies: searching svelte dependencies in ${root}`);
8
- const pkgFile = path.join(root, 'package.json');
9
- if (!fs.existsSync(pkgFile)) {
10
- if (cwdFallback) {
11
- const cwd = process.cwd();
12
- if (root !== cwd) {
13
- log.debug(`no package.json found in vite root ${root}`);
14
- return findRootSvelteDependencies(cwd, false);
15
- }
16
- }
17
- log.warn(`no package.json found, findRootSvelteDependencies failed`);
18
- return [];
19
- }
20
-
21
- const pkg = parsePkg(root);
22
- if (!pkg) {
23
- return [];
24
- }
25
-
26
- const deps = [
27
- ...Object.keys(pkg.dependencies || {}),
28
- ...Object.keys(pkg.devDependencies || {})
29
- ].filter((dep) => !is_common_without_svelte_field(dep));
30
-
31
- return getSvelteDependencies(deps, root);
32
- }
33
-
34
- function getSvelteDependencies(
35
- deps: string[],
36
- pkgDir: string,
37
- path: string[] = []
38
- ): SvelteDependency[] {
39
- const result = [];
40
- const localRequire = createRequire(`${pkgDir}/package.json`);
41
- const resolvedDeps = deps
42
- .map((dep) => resolveDependencyData(dep, localRequire))
43
- .filter(Boolean) as DependencyData[];
44
- for (const { pkg, dir } of resolvedDeps) {
45
- const type = getSvelteDependencyType(pkg);
46
- if (!type) continue;
47
- result.push({ name: pkg.name, type, pkg, dir, path });
48
- // continue crawling for component libraries so we can optimize them, js libraries are fine
49
- if (type === 'component-library' && pkg.dependencies) {
50
- let dependencyNames = Object.keys(pkg.dependencies);
51
- const circular = dependencyNames.filter((name) => path.includes(name));
52
- if (circular.length > 0) {
53
- log.warn.enabled &&
54
- log.warn(
55
- `skipping circular svelte dependencies in automated vite optimizeDeps handling`,
56
- circular.map((x) => path.concat(x).join('>'))
57
- );
58
- dependencyNames = dependencyNames.filter((name) => !path.includes(name));
59
- }
60
- if (path.length === 3) {
61
- log.debug.once(`encountered deep svelte dependency tree: ${path.join('>')}`);
62
- }
63
- result.push(...getSvelteDependencies(dependencyNames, dir, path.concat(pkg.name)));
64
- }
65
- }
66
- return result;
6
+ interface DependencyData {
7
+ dir: string;
8
+ pkg: Record<string, any>;
67
9
  }
68
10
 
69
- export function resolveDependencyData(
11
+ export async function resolveDependencyData(
70
12
  dep: string,
71
- localRequire: NodeRequire
72
- ): DependencyData | void {
73
- try {
74
- const pkgJson = `${dep}/package.json`;
75
- const pkg = localRequire(pkgJson);
76
- const dir = path.dirname(localRequire.resolve(pkgJson));
77
- return { dir, pkg };
78
- } catch (e) {
79
- log.debug.once(`dependency ${dep} does not export package.json`, e);
80
- // walk up from default export until we find package.json with name=dep
81
- try {
82
- let dir = path.dirname(localRequire.resolve(dep));
83
- while (dir) {
84
- const pkg = parsePkg(dir, true);
85
- if (pkg && pkg.name === dep) {
86
- return { dir, pkg };
87
- }
88
- const parent = path.dirname(dir);
89
- if (parent === dir) {
90
- break;
91
- }
92
- dir = parent;
93
- }
94
- } catch (e) {
95
- log.debug.once(`error while trying to find package.json of ${dep}`, e);
96
- }
97
- }
98
- log.debug.once(`failed to resolve ${dep}`);
99
- }
100
-
101
- function parsePkg(dir: string, silent = false): Pkg | void {
102
- const pkgFile = path.join(dir, 'package.json');
13
+ parent: string
14
+ ): Promise<DependencyData | undefined> {
15
+ const depDataPath = await findDepPkgJsonPath(dep, parent);
16
+ if (!depDataPath) return undefined;
103
17
  try {
104
- return JSON.parse(fs.readFileSync(pkgFile, 'utf-8'));
105
- } catch (e) {
106
- !silent && log.warn.enabled && log.warn(`failed to parse ${pkgFile}`, e);
107
- }
108
- }
109
-
110
- function getSvelteDependencyType(pkg: Pkg): SvelteDependencyType | undefined {
111
- if (isSvelteComponentLib(pkg)) {
112
- return 'component-library';
113
- } else if (isSvelteLib(pkg)) {
114
- return 'js-library';
115
- } else {
18
+ return {
19
+ dir: path.dirname(depDataPath),
20
+ pkg: JSON.parse(await fs.readFile(depDataPath, 'utf-8'))
21
+ };
22
+ } catch {
116
23
  return undefined;
117
24
  }
118
25
  }
119
26
 
120
- function isSvelteComponentLib(pkg: Pkg) {
121
- return !!pkg.svelte;
122
- }
123
-
124
- function isSvelteLib(pkg: Pkg) {
125
- return !!pkg.dependencies?.svelte || !!pkg.peerDependencies?.svelte;
126
- }
127
-
128
27
  const COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD = [
129
28
  '@lukeed/uuid',
130
29
  '@playwright/test',
@@ -173,7 +72,7 @@ const COMMON_PREFIXES_WITHOUT_SVELTE_FIELD = [
173
72
  * @param dependency {string}
174
73
  * @returns {boolean} true if it is a dependency without a svelte field
175
74
  */
176
- export function is_common_without_svelte_field(dependency: string): boolean {
75
+ export function isCommonDepWithoutSvelteField(dependency: string): boolean {
177
76
  return (
178
77
  COMMON_DEPENDENCIES_WITHOUT_SVELTE_FIELD.includes(dependency) ||
179
78
  COMMON_PREFIXES_WITHOUT_SVELTE_FIELD.some(
@@ -184,58 +83,3 @@ export function is_common_without_svelte_field(dependency: string): boolean {
184
83
  )
185
84
  );
186
85
  }
187
-
188
- export function needsOptimization(dep: string, localRequire: NodeRequire): boolean {
189
- const depData = resolveDependencyData(dep, localRequire);
190
- if (!depData) return false;
191
- const pkg = depData.pkg;
192
- // only optimize if is cjs, using the below as heuristic
193
- // see https://github.com/sveltejs/vite-plugin-svelte/issues/162
194
- const hasEsmFields = pkg.module || pkg.exports;
195
- if (hasEsmFields) return false;
196
- if (pkg.main) {
197
- // ensure entry is js so vite can prebundle it
198
- // see https://github.com/sveltejs/vite-plugin-svelte/issues/233
199
- const entryExt = path.extname(pkg.main);
200
- return !entryExt || entryExt === '.js' || entryExt === '.cjs';
201
- } else {
202
- // check if has implicit index.js entrypoint
203
- // https://github.com/sveltejs/vite-plugin-svelte/issues/281
204
- try {
205
- localRequire.resolve(`${dep}/index.js`);
206
- return true;
207
- } catch {
208
- return false;
209
- }
210
- }
211
- }
212
-
213
- interface DependencyData {
214
- dir: string;
215
- pkg: Pkg;
216
- }
217
-
218
- export interface SvelteDependency {
219
- name: string;
220
- type: SvelteDependencyType;
221
- dir: string;
222
- pkg: Pkg;
223
- path: string[];
224
- }
225
-
226
- // component-library => exports svelte components
227
- // js-library => only uses svelte api, no components
228
- export type SvelteDependencyType = 'component-library' | 'js-library';
229
-
230
- export interface Pkg {
231
- name: string;
232
- svelte?: string;
233
- dependencies?: DependencyList;
234
- devDependencies?: DependencyList;
235
- peerDependencies?: DependencyList;
236
- [key: string]: any;
237
- }
238
-
239
- export interface DependencyList {
240
- [key: string]: string;
241
- }
@@ -5,9 +5,11 @@ import { Compiled } from './compile';
5
5
  import { log } from './log';
6
6
  import { CompileOptions, ResolvedOptions } from './options';
7
7
  import { toESBuildError } from './error';
8
+ import { atLeastSvelte } from './svelte-version';
8
9
 
9
10
  type EsbuildOptions = NonNullable<DepOptimizationOptions['esbuildOptions']>;
10
11
  type EsbuildPlugin = NonNullable<EsbuildOptions['plugins']>[number];
12
+ const isCssString = atLeastSvelte('3.53.0');
11
13
 
12
14
  export const facadeEsbuildSveltePluginName = 'vite-plugin-svelte:facade';
13
15
 
@@ -39,9 +41,13 @@ async function compileSvelte(
39
41
  options: ResolvedOptions,
40
42
  { filename, code }: { filename: string; code: string }
41
43
  ): Promise<string> {
44
+ let css = options.compilerOptions.css;
45
+ if (css !== 'none') {
46
+ css = isCssString ? 'injected' : true;
47
+ }
42
48
  const compileOptions: CompileOptions = {
43
49
  ...options.compilerOptions,
44
- css: true,
50
+ css,
45
51
  filename,
46
52
  format: 'esm',
47
53
  generate: 'dom'