@sveltejs/vite-plugin-svelte 2.3.0 → 2.4.1
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 +9 -14
- package/src/{handle-hot-update.ts → handle-hot-update.js} +35 -20
- package/src/index.d.ts +215 -0
- package/src/{index.ts → index.js} +40 -69
- package/src/{preprocess.ts → preprocess.js} +37 -28
- package/src/types/compile.d.ts +48 -0
- package/src/types/id.d.ts +31 -0
- package/src/types/log.d.ts +24 -0
- package/src/types/options.d.ts +20 -0
- package/src/types/plugin-api.d.ts +11 -0
- package/src/types/vite-plugin-svelte-stats.d.ts +30 -0
- package/src/utils/{compile.ts → compile.js} +38 -64
- package/src/utils/{dependencies.ts → dependencies.js} +14 -11
- package/src/utils/{error.ts → error.js} +21 -14
- package/src/utils/{esbuild.ts → esbuild.js} +28 -19
- package/src/utils/{hash.ts → hash.js} +14 -3
- package/src/utils/{id.ts → id.js} +59 -60
- package/src/utils/{load-raw.ts → load-raw.js} +16 -16
- package/src/utils/{load-svelte-config.ts → load-svelte-config.js} +12 -10
- package/src/utils/{log.ts → log.js} +81 -48
- package/src/utils/{optimizer.ts → optimizer.js} +15 -7
- package/src/utils/{options.ts → options.js} +146 -296
- package/src/utils/{preprocess.ts → preprocess.js} +28 -12
- package/src/utils/{resolve.ts → resolve.js} +18 -9
- package/src/utils/{sourcemaps.ts → sourcemaps.js} +22 -14
- package/src/utils/svelte-version.js +6 -0
- package/src/utils/vite-plugin-svelte-cache.js +253 -0
- package/src/utils/{vite-plugin-svelte-stats.ts → vite-plugin-svelte-stats.js} +66 -62
- package/src/utils/{watch.ts → watch.js} +30 -22
- package/dist/index.d.ts +0 -193
- package/dist/index.js +0 -2272
- package/dist/index.js.map +0 -1
- package/src/__tests__/fixtures/preprocess/foo.scss +0 -3
- package/src/__tests__/preprocess.spec.ts +0 -51
- package/src/utils/__tests__/compile.spec.ts +0 -49
- package/src/utils/__tests__/sourcemaps.spec.ts +0 -79
- package/src/utils/__tests__/svelte-version.spec.ts +0 -102
- package/src/utils/svelte-version.ts +0 -37
- package/src/utils/vite-plugin-svelte-cache.ts +0 -182
- /package/src/utils/{constants.ts → constants.js} +0 -0
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import type { ResolvedConfig, Plugin } from 'vite';
|
|
2
1
|
import MagicString from 'magic-string';
|
|
3
|
-
import {
|
|
4
|
-
import { log } from './log';
|
|
2
|
+
import { log } from './log.js';
|
|
5
3
|
import path from 'path';
|
|
6
4
|
|
|
7
5
|
/**
|
|
@@ -9,8 +7,10 @@ import path from 'path';
|
|
|
9
7
|
* That means adding/removing class rules from <style> node won't trigger js updates as the scope classes are not changed
|
|
10
8
|
*
|
|
11
9
|
* only used during dev with enabled css hmr
|
|
10
|
+
*
|
|
11
|
+
* @returns {import('svelte/types/compiler/preprocess').PreprocessorGroup}
|
|
12
12
|
*/
|
|
13
|
-
export function createInjectScopeEverythingRulePreprocessorGroup()
|
|
13
|
+
export function createInjectScopeEverythingRulePreprocessorGroup() {
|
|
14
14
|
return {
|
|
15
15
|
style({ content, filename }) {
|
|
16
16
|
const s = new MagicString(content);
|
|
@@ -26,9 +26,19 @@ export function createInjectScopeEverythingRulePreprocessorGroup(): Preprocessor
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
/**
|
|
30
|
+
* @param {import('../types/options.d.ts').ResolvedOptions} options
|
|
31
|
+
* @param {import('vite').ResolvedConfig} config
|
|
32
|
+
* @returns {{
|
|
33
|
+
* prependPreprocessors: import('svelte/types/compiler/preprocess').PreprocessorGroup[],
|
|
34
|
+
* appendPreprocessors: import('svelte/types/compiler/preprocess').PreprocessorGroup[]
|
|
35
|
+
* }}
|
|
36
|
+
*/
|
|
37
|
+
function buildExtraPreprocessors(options, config) {
|
|
38
|
+
/** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup[]} */
|
|
39
|
+
const prependPreprocessors = [];
|
|
40
|
+
/** @type {import('svelte/types/compiler/preprocess').PreprocessorGroup[]} */
|
|
41
|
+
const appendPreprocessors = [];
|
|
32
42
|
|
|
33
43
|
// @ts-ignore
|
|
34
44
|
const pluginsWithPreprocessorsDeprecated = config.plugins.filter((p) => p?.sveltePreprocess);
|
|
@@ -53,10 +63,12 @@ function buildExtraPreprocessors(options: ResolvedOptions, config: ResolvedConfi
|
|
|
53
63
|
}
|
|
54
64
|
});
|
|
55
65
|
}
|
|
56
|
-
|
|
57
|
-
const pluginsWithPreprocessors
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
/** @type {import('vite').Plugin[]} */
|
|
67
|
+
const pluginsWithPreprocessors = config.plugins.filter((p) => p?.api?.sveltePreprocess);
|
|
68
|
+
/** @type {import('vite').Plugin[]} */
|
|
69
|
+
const ignored = [];
|
|
70
|
+
/** @type {import('vite').Plugin[]} */
|
|
71
|
+
const included = [];
|
|
60
72
|
for (const p of pluginsWithPreprocessors) {
|
|
61
73
|
if (
|
|
62
74
|
options.ignorePluginPreprocessors === true ||
|
|
@@ -87,7 +99,11 @@ function buildExtraPreprocessors(options: ResolvedOptions, config: ResolvedConfi
|
|
|
87
99
|
return { prependPreprocessors, appendPreprocessors };
|
|
88
100
|
}
|
|
89
101
|
|
|
90
|
-
|
|
102
|
+
/**
|
|
103
|
+
* @param {import('../types/options.d.ts').ResolvedOptions} options
|
|
104
|
+
* @param {import('vite').ResolvedConfig} config
|
|
105
|
+
*/
|
|
106
|
+
export function addExtraPreprocessors(options, config) {
|
|
91
107
|
const { prependPreprocessors, appendPreprocessors } = buildExtraPreprocessors(options, config);
|
|
92
108
|
if (prependPreprocessors.length > 0 || appendPreprocessors.length > 0) {
|
|
93
109
|
if (!options.preprocess) {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { builtinModules } from 'module';
|
|
3
|
-
import { resolveDependencyData, isCommonDepWithoutSvelteField } from './dependencies';
|
|
4
|
-
import { VitePluginSvelteCache } from './vite-plugin-svelte-cache';
|
|
3
|
+
import { resolveDependencyData, isCommonDepWithoutSvelteField } from './dependencies.js';
|
|
5
4
|
import { normalizePath } from 'vite';
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} importee
|
|
8
|
+
* @param {string | undefined} importer
|
|
9
|
+
* @param {import('./vite-plugin-svelte-cache').VitePluginSvelteCache} cache
|
|
10
|
+
* @returns {Promise<string | void>}
|
|
11
|
+
*/
|
|
12
|
+
export async function resolveViaPackageJsonSvelte(importee, importer, cache) {
|
|
12
13
|
if (
|
|
13
14
|
importer &&
|
|
14
15
|
isBareImport(importee) &&
|
|
@@ -31,11 +32,19 @@ export async function resolveViaPackageJsonSvelte(
|
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
/**
|
|
36
|
+
* @param {string} importee
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
function isNodeInternal(importee) {
|
|
35
40
|
return importee.startsWith('node:') || builtinModules.includes(importee);
|
|
36
41
|
}
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
/**
|
|
44
|
+
* @param {string} importee
|
|
45
|
+
* @returns {boolean}
|
|
46
|
+
*/
|
|
47
|
+
function isBareImport(importee) {
|
|
39
48
|
if (
|
|
40
49
|
!importee ||
|
|
41
50
|
importee[0] === '.' ||
|
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
+
|
|
2
3
|
const IS_WINDOWS = process.platform === 'win32';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {{
|
|
7
|
+
* file?: string;
|
|
8
|
+
* sources?: string[];
|
|
9
|
+
* sourceRoot?: string;
|
|
10
|
+
* }} SourceMapFileRefs
|
|
11
|
+
*/
|
|
8
12
|
|
|
9
13
|
/**
|
|
10
14
|
* convert absolute paths in sourcemap file refs to their relative equivalents to avoid leaking fs info
|
|
11
15
|
*
|
|
12
16
|
* map is modified in place.
|
|
13
17
|
*
|
|
14
|
-
* @param map sourcemap
|
|
15
|
-
* @param filename absolute path to file the sourcemap is for
|
|
18
|
+
* @param {SourceMapFileRefs | undefined} map sourcemap
|
|
19
|
+
* @param {string} filename absolute path to file the sourcemap is for
|
|
16
20
|
*/
|
|
17
|
-
export function mapToRelative(map
|
|
21
|
+
export function mapToRelative(map, filename) {
|
|
18
22
|
if (!map) {
|
|
19
23
|
return;
|
|
20
24
|
}
|
|
21
25
|
const sourceRoot = map.sourceRoot;
|
|
22
26
|
const dirname = path.dirname(filename);
|
|
23
|
-
|
|
27
|
+
|
|
28
|
+
/** @type {(s: string) => string} */
|
|
29
|
+
const toRelative = (s) => {
|
|
24
30
|
if (!s) {
|
|
25
31
|
return s;
|
|
26
32
|
}
|
|
27
|
-
|
|
33
|
+
/** @type {string} */
|
|
34
|
+
let sourcePath;
|
|
28
35
|
if (s.startsWith('file:///')) {
|
|
29
36
|
// windows has file:///C:/foo and posix has file:///foo, so we have to remove one extra on windows
|
|
30
37
|
sourcePath = s.slice(IS_WINDOWS ? 8 : 7);
|
|
@@ -56,14 +63,15 @@ export function mapToRelative(map: SourceMapFileRefs | undefined, filename: stri
|
|
|
56
63
|
*
|
|
57
64
|
* map is modified in place.
|
|
58
65
|
*
|
|
59
|
-
* @param map the output sourcemap
|
|
60
|
-
* @param suffix the suffix to remove
|
|
66
|
+
* @param {SourceMapFileRefs | undefined} map the output sourcemap
|
|
67
|
+
* @param {string} suffix the suffix to remove
|
|
61
68
|
*/
|
|
62
|
-
export function removeLangSuffix(map
|
|
69
|
+
export function removeLangSuffix(map, suffix) {
|
|
63
70
|
if (!map) {
|
|
64
71
|
return;
|
|
65
72
|
}
|
|
66
|
-
|
|
73
|
+
/** @type {(s:string)=> string} */
|
|
74
|
+
const removeSuffix = (s) => (s?.endsWith(suffix) ? s.slice(0, -1 * suffix.length) : s);
|
|
67
75
|
if (map.file) {
|
|
68
76
|
map.file = removeSuffix(map.file);
|
|
69
77
|
}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { findClosestPkgJsonPath } from 'vitefu';
|
|
4
|
+
import { normalizePath } from 'vite';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {{
|
|
8
|
+
* name: string;
|
|
9
|
+
* version: string;
|
|
10
|
+
* svelte?: string;
|
|
11
|
+
* path: string;
|
|
12
|
+
* }} PackageInfo
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @class
|
|
17
|
+
*/
|
|
18
|
+
export class VitePluginSvelteCache {
|
|
19
|
+
/** @type {Map<string, import('../types/compile.d.ts').Code>} */
|
|
20
|
+
#css = new Map();
|
|
21
|
+
/** @type {Map<string, import('../types/compile.d.ts').Code>} */
|
|
22
|
+
#js = new Map();
|
|
23
|
+
/** @type {Map<string, string[]>} */
|
|
24
|
+
#dependencies = new Map();
|
|
25
|
+
/** @type {Map<string, Set<string>>} */
|
|
26
|
+
#dependants = new Map();
|
|
27
|
+
/** @type {Map<string, string>} */
|
|
28
|
+
#resolvedSvelteFields = new Map();
|
|
29
|
+
/** @type {Map<string, any>} */
|
|
30
|
+
#errors = new Map();
|
|
31
|
+
/** @type {PackageInfo[]} */
|
|
32
|
+
#packageInfos = [];
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {import('../types/compile.d.ts').CompileData} compileData
|
|
36
|
+
*/
|
|
37
|
+
update(compileData) {
|
|
38
|
+
this.#errors.delete(compileData.normalizedFilename);
|
|
39
|
+
this.#updateCSS(compileData);
|
|
40
|
+
this.#updateJS(compileData);
|
|
41
|
+
this.#updateDependencies(compileData);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
|
|
46
|
+
* @returns {boolean}
|
|
47
|
+
*/
|
|
48
|
+
has(svelteRequest) {
|
|
49
|
+
const id = svelteRequest.normalizedFilename;
|
|
50
|
+
return this.#errors.has(id) || this.#js.has(id) || this.#css.has(id);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
|
|
55
|
+
* @param {any} error
|
|
56
|
+
*/
|
|
57
|
+
setError(svelteRequest, error) {
|
|
58
|
+
// keep dependency info, otherwise errors in dependants would not trigger an update after fixing
|
|
59
|
+
// because they are no longer watched
|
|
60
|
+
this.remove(svelteRequest, true);
|
|
61
|
+
this.#errors.set(svelteRequest.normalizedFilename, error);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {import('../types/compile.d.ts').CompileData} compileData
|
|
66
|
+
*/
|
|
67
|
+
#updateCSS(compileData) {
|
|
68
|
+
this.#css.set(compileData.normalizedFilename, compileData.compiled.css);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @param {import('../types/compile.d.ts').CompileData} compileData
|
|
73
|
+
*/
|
|
74
|
+
#updateJS(compileData) {
|
|
75
|
+
if (!compileData.ssr) {
|
|
76
|
+
// do not cache SSR js
|
|
77
|
+
this.#js.set(compileData.normalizedFilename, compileData.compiled.js);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {import('../types/compile.d.ts').CompileData} compileData
|
|
83
|
+
*/
|
|
84
|
+
#updateDependencies(compileData) {
|
|
85
|
+
const id = compileData.normalizedFilename;
|
|
86
|
+
const prevDependencies = this.#dependencies.get(id) || [];
|
|
87
|
+
const dependencies = compileData.dependencies;
|
|
88
|
+
this.#dependencies.set(id, dependencies);
|
|
89
|
+
const removed = prevDependencies.filter((d) => !dependencies.includes(d));
|
|
90
|
+
const added = dependencies.filter((d) => !prevDependencies.includes(d));
|
|
91
|
+
added.forEach((d) => {
|
|
92
|
+
if (!this.#dependants.has(d)) {
|
|
93
|
+
this.#dependants.set(d, new Set());
|
|
94
|
+
}
|
|
95
|
+
/** @type {Set<string>} */ (this.#dependants.get(d)).add(compileData.filename);
|
|
96
|
+
});
|
|
97
|
+
removed.forEach((d) => {
|
|
98
|
+
/** @type {Set<string>} */ (this.#dependants.get(d)).delete(compileData.filename);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
|
|
104
|
+
* @param {boolean} [keepDependencies]
|
|
105
|
+
* @returns {boolean}
|
|
106
|
+
*/
|
|
107
|
+
remove(svelteRequest, keepDependencies = false) {
|
|
108
|
+
const id = svelteRequest.normalizedFilename;
|
|
109
|
+
let removed = false;
|
|
110
|
+
if (this.#errors.delete(id)) {
|
|
111
|
+
removed = true;
|
|
112
|
+
}
|
|
113
|
+
if (this.#js.delete(id)) {
|
|
114
|
+
removed = true;
|
|
115
|
+
}
|
|
116
|
+
if (this.#css.delete(id)) {
|
|
117
|
+
removed = true;
|
|
118
|
+
}
|
|
119
|
+
if (!keepDependencies) {
|
|
120
|
+
const dependencies = this.#dependencies.get(id);
|
|
121
|
+
if (dependencies) {
|
|
122
|
+
removed = true;
|
|
123
|
+
dependencies.forEach((d) => {
|
|
124
|
+
const dependants = this.#dependants.get(d);
|
|
125
|
+
if (dependants && dependants.has(svelteRequest.filename)) {
|
|
126
|
+
dependants.delete(svelteRequest.filename);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
this.#dependencies.delete(id);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return removed;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
|
|
138
|
+
* @returns {import('../types/compile.d.ts').Code | undefined}
|
|
139
|
+
*/
|
|
140
|
+
getCSS(svelteRequest) {
|
|
141
|
+
return this.#css.get(svelteRequest.normalizedFilename);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
|
|
146
|
+
* @returns {import('../types/compile.d.ts').Code | undefined}
|
|
147
|
+
*/
|
|
148
|
+
getJS(svelteRequest) {
|
|
149
|
+
if (!svelteRequest.ssr) {
|
|
150
|
+
// SSR js isn't cached
|
|
151
|
+
return this.#js.get(svelteRequest.normalizedFilename);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* @param {import('../types/id.d.ts').SvelteRequest} svelteRequest
|
|
156
|
+
* @returns {any}
|
|
157
|
+
*/
|
|
158
|
+
getError(svelteRequest) {
|
|
159
|
+
return this.#errors.get(svelteRequest.normalizedFilename);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* @param {string} path
|
|
164
|
+
* @returns {string[]}
|
|
165
|
+
*/
|
|
166
|
+
getDependants(path) {
|
|
167
|
+
const dependants = this.#dependants.get(path);
|
|
168
|
+
return dependants ? [...dependants] : [];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @param {string} name
|
|
173
|
+
* @param {string} [importer]
|
|
174
|
+
* @returns {string|void}
|
|
175
|
+
*/
|
|
176
|
+
getResolvedSvelteField(name, importer) {
|
|
177
|
+
return this.#resolvedSvelteFields.get(this.#getResolvedSvelteFieldKey(name, importer));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @param {string} name
|
|
182
|
+
* @param {string} [importer]
|
|
183
|
+
* @returns {boolean}
|
|
184
|
+
*/
|
|
185
|
+
hasResolvedSvelteField(name, importer) {
|
|
186
|
+
return this.#resolvedSvelteFields.has(this.#getResolvedSvelteFieldKey(name, importer));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
*
|
|
190
|
+
* @param {string} importee
|
|
191
|
+
* @param {string | undefined} importer
|
|
192
|
+
* @param {string} resolvedSvelte
|
|
193
|
+
*/
|
|
194
|
+
setResolvedSvelteField(importee, importer, resolvedSvelte) {
|
|
195
|
+
this.#resolvedSvelteFields.set(
|
|
196
|
+
this.#getResolvedSvelteFieldKey(importee, importer),
|
|
197
|
+
resolvedSvelte
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @param {string} importee
|
|
203
|
+
* @param {string | undefined} importer
|
|
204
|
+
* @returns {string}
|
|
205
|
+
*/
|
|
206
|
+
#getResolvedSvelteFieldKey(importee, importer) {
|
|
207
|
+
return importer ? `${importer} > ${importee}` : importee;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @param {string} file
|
|
212
|
+
* @returns {Promise<PackageInfo>}
|
|
213
|
+
*/
|
|
214
|
+
async getPackageInfo(file) {
|
|
215
|
+
let info = this.#packageInfos.find((pi) => file.startsWith(pi.path));
|
|
216
|
+
if (!info) {
|
|
217
|
+
info = await findPackageInfo(file);
|
|
218
|
+
this.#packageInfos.push(info);
|
|
219
|
+
}
|
|
220
|
+
return info;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* utility to get some info from the closest package.json with a "name" set
|
|
226
|
+
*
|
|
227
|
+
* @param {string} file to find info for
|
|
228
|
+
* @returns {Promise<PackageInfo>}
|
|
229
|
+
*/
|
|
230
|
+
async function findPackageInfo(file) {
|
|
231
|
+
/** @type {PackageInfo} */
|
|
232
|
+
const info = {
|
|
233
|
+
name: '$unknown',
|
|
234
|
+
version: '0.0.0-unknown',
|
|
235
|
+
path: '$unknown'
|
|
236
|
+
};
|
|
237
|
+
let path = await findClosestPkgJsonPath(file, (pkgPath) => {
|
|
238
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
239
|
+
if (pkg.name != null) {
|
|
240
|
+
info.name = pkg.name;
|
|
241
|
+
if (pkg.version != null) {
|
|
242
|
+
info.version = pkg.version;
|
|
243
|
+
}
|
|
244
|
+
info.svelte = pkg.svelte;
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
return false;
|
|
248
|
+
});
|
|
249
|
+
// return normalized path with appended '/' so .startsWith works for future file checks
|
|
250
|
+
path = normalizePath(dirname(path ?? file)) + '/';
|
|
251
|
+
info.path = path;
|
|
252
|
+
return info;
|
|
253
|
+
}
|
|
@@ -1,54 +1,29 @@
|
|
|
1
|
-
import { log } from './log';
|
|
1
|
+
import { log } from './log.js';
|
|
2
2
|
import { performance } from 'perf_hooks';
|
|
3
3
|
import { normalizePath } from 'vite';
|
|
4
|
-
import { VitePluginSvelteCache } from './vite-plugin-svelte-cache';
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
pkg?: string;
|
|
9
|
-
start: number;
|
|
10
|
-
end: number;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface StatCollection {
|
|
14
|
-
name: string;
|
|
15
|
-
options: CollectionOptions;
|
|
16
|
-
//eslint-disable-next-line no-unused-vars
|
|
17
|
-
start: (file: string) => () => void;
|
|
18
|
-
stats: Stat[];
|
|
19
|
-
packageStats?: PackageStats[];
|
|
20
|
-
collectionStart: number;
|
|
21
|
-
duration?: number;
|
|
22
|
-
finish: () => Promise<void> | void;
|
|
23
|
-
finished: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
interface PackageStats {
|
|
27
|
-
pkg: string;
|
|
28
|
-
files: number;
|
|
29
|
-
duration: number;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface CollectionOptions {
|
|
33
|
-
//eslint-disable-next-line no-unused-vars
|
|
34
|
-
logInProgress: (collection: StatCollection, now: number) => boolean;
|
|
35
|
-
//eslint-disable-next-line no-unused-vars
|
|
36
|
-
logResult: (collection: StatCollection) => boolean;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const defaultCollectionOptions: CollectionOptions = {
|
|
5
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').CollectionOptions} */
|
|
6
|
+
const defaultCollectionOptions = {
|
|
40
7
|
// log after 500ms and more than one file processed
|
|
41
8
|
logInProgress: (c, now) => now - c.collectionStart > 500 && c.stats.length > 1,
|
|
42
9
|
// always log results
|
|
43
10
|
logResult: () => true
|
|
44
11
|
};
|
|
45
12
|
|
|
46
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @param {number} n
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
function humanDuration(n) {
|
|
47
18
|
// 99.9ms 0.10s
|
|
48
19
|
return n < 100 ? `${n.toFixed(1)}ms` : `${(n / 1000).toFixed(2)}s`;
|
|
49
20
|
}
|
|
50
21
|
|
|
51
|
-
|
|
22
|
+
/**
|
|
23
|
+
* @param {import('../types/vite-plugin-svelte-stats.d.ts').PackageStats[]} pkgStats
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
function formatPackageStats(pkgStats) {
|
|
52
27
|
const statLines = pkgStats.map((pkgStat) => {
|
|
53
28
|
const duration = pkgStat.duration;
|
|
54
29
|
const avg = duration / pkgStat.files;
|
|
@@ -56,7 +31,7 @@ function formatPackageStats(pkgStats: PackageStats[]) {
|
|
|
56
31
|
});
|
|
57
32
|
statLines.unshift(['package', 'files', 'time', 'avg']);
|
|
58
33
|
const columnWidths = statLines.reduce(
|
|
59
|
-
(widths
|
|
34
|
+
(widths, row) => {
|
|
60
35
|
for (let i = 0; i < row.length; i++) {
|
|
61
36
|
const cell = row[i];
|
|
62
37
|
if (widths[i] < cell.length) {
|
|
@@ -69,9 +44,9 @@ function formatPackageStats(pkgStats: PackageStats[]) {
|
|
|
69
44
|
);
|
|
70
45
|
|
|
71
46
|
const table = statLines
|
|
72
|
-
.map((row
|
|
47
|
+
.map((row) =>
|
|
73
48
|
row
|
|
74
|
-
.map((cell
|
|
49
|
+
.map((cell, i) => {
|
|
75
50
|
if (i === 0) {
|
|
76
51
|
return cell.padEnd(columnWidths[i], ' ');
|
|
77
52
|
} else {
|
|
@@ -84,23 +59,40 @@ function formatPackageStats(pkgStats: PackageStats[]) {
|
|
|
84
59
|
return table;
|
|
85
60
|
}
|
|
86
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @class
|
|
64
|
+
*/
|
|
87
65
|
export class VitePluginSvelteStats {
|
|
88
66
|
// package directory -> package name
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
67
|
+
/** @type {import('./vite-plugin-svelte-cache.js').VitePluginSvelteCache} */
|
|
68
|
+
#cache;
|
|
69
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection[]} */
|
|
70
|
+
#collections = [];
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @param {import('./vite-plugin-svelte-cache.js').VitePluginSvelteCache} cache
|
|
74
|
+
*/
|
|
75
|
+
constructor(cache) {
|
|
76
|
+
this.#cache = cache;
|
|
93
77
|
}
|
|
94
|
-
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {string} name
|
|
81
|
+
* @param {Partial<import('../types/vite-plugin-svelte-stats.d.ts').CollectionOptions>} [opts]
|
|
82
|
+
* @returns {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection}
|
|
83
|
+
*/
|
|
84
|
+
startCollection(name, opts) {
|
|
95
85
|
const options = {
|
|
96
86
|
...defaultCollectionOptions,
|
|
97
87
|
...opts
|
|
98
88
|
};
|
|
99
|
-
|
|
89
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').Stat[]} */
|
|
90
|
+
const stats = [];
|
|
100
91
|
const collectionStart = performance.now();
|
|
101
92
|
const _this = this;
|
|
102
93
|
let hasLoggedProgress = false;
|
|
103
|
-
|
|
94
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} */
|
|
95
|
+
const collection = {
|
|
104
96
|
name,
|
|
105
97
|
options,
|
|
106
98
|
stats,
|
|
@@ -112,7 +104,8 @@ export class VitePluginSvelteStats {
|
|
|
112
104
|
}
|
|
113
105
|
file = normalizePath(file);
|
|
114
106
|
const start = performance.now();
|
|
115
|
-
|
|
107
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').Stat} */
|
|
108
|
+
const stat = { file, start, end: start };
|
|
116
109
|
return () => {
|
|
117
110
|
const now = performance.now();
|
|
118
111
|
stat.end = now;
|
|
@@ -124,34 +117,41 @@ export class VitePluginSvelteStats {
|
|
|
124
117
|
};
|
|
125
118
|
},
|
|
126
119
|
async finish() {
|
|
127
|
-
await _this
|
|
120
|
+
await _this.#finish(collection);
|
|
128
121
|
}
|
|
129
122
|
};
|
|
130
|
-
_this.
|
|
123
|
+
_this.#collections.push(collection);
|
|
131
124
|
return collection;
|
|
132
125
|
}
|
|
133
126
|
|
|
134
|
-
|
|
135
|
-
await Promise.all(this.
|
|
127
|
+
async finishAll() {
|
|
128
|
+
await Promise.all(this.#collections.map((c) => c.finish()));
|
|
136
129
|
}
|
|
137
130
|
|
|
138
|
-
|
|
131
|
+
/**
|
|
132
|
+
* @param {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} collection
|
|
133
|
+
*/
|
|
134
|
+
async #finish(collection) {
|
|
139
135
|
try {
|
|
140
136
|
collection.finished = true;
|
|
141
137
|
const now = performance.now();
|
|
142
138
|
collection.duration = now - collection.collectionStart;
|
|
143
139
|
const logResult = collection.options.logResult(collection);
|
|
144
140
|
if (logResult) {
|
|
145
|
-
await this
|
|
141
|
+
await this.#aggregateStatsResult(collection);
|
|
146
142
|
log.debug(
|
|
147
|
-
`${collection.name} done.\n${formatPackageStats(
|
|
143
|
+
`${collection.name} done.\n${formatPackageStats(
|
|
144
|
+
/** @type {import('../types/vite-plugin-svelte-stats.d.ts').PackageStats[]}*/ (
|
|
145
|
+
collection.packageStats
|
|
146
|
+
)
|
|
147
|
+
)}`,
|
|
148
148
|
undefined,
|
|
149
149
|
'stats'
|
|
150
150
|
);
|
|
151
151
|
}
|
|
152
152
|
// cut some ties to free it for garbage collection
|
|
153
|
-
const index = this.
|
|
154
|
-
this.
|
|
153
|
+
const index = this.#collections.indexOf(collection);
|
|
154
|
+
this.#collections.splice(index, 1);
|
|
155
155
|
collection.stats.length = 0;
|
|
156
156
|
collection.stats = [];
|
|
157
157
|
if (collection.packageStats) {
|
|
@@ -166,16 +166,20 @@ export class VitePluginSvelteStats {
|
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
/**
|
|
170
|
+
* @param {import('../types/vite-plugin-svelte-stats.d.ts').StatCollection} collection
|
|
171
|
+
*/
|
|
172
|
+
async #aggregateStatsResult(collection) {
|
|
170
173
|
const stats = collection.stats;
|
|
171
174
|
for (const stat of stats) {
|
|
172
|
-
stat.pkg = (await this.
|
|
175
|
+
stat.pkg = (await this.#cache.getPackageInfo(stat.file)).name;
|
|
173
176
|
}
|
|
174
177
|
|
|
175
178
|
// group stats
|
|
176
|
-
|
|
179
|
+
/** @type {Record<string, import('../types/vite-plugin-svelte-stats.d.ts').PackageStats>} */
|
|
180
|
+
const grouped = {};
|
|
177
181
|
stats.forEach((stat) => {
|
|
178
|
-
const pkg = stat.pkg
|
|
182
|
+
const pkg = /** @type {string} */ (stat.pkg);
|
|
179
183
|
let group = grouped[pkg];
|
|
180
184
|
if (!group) {
|
|
181
185
|
group = grouped[pkg] = {
|