@sveltejs/vite-plugin-svelte 1.0.0-next.9 → 1.0.2
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/README.md +16 -50
- package/dist/index.cjs +2014 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +231 -214
- package/dist/index.js +1522 -395
- package/dist/index.js.map +1 -0
- package/package.json +48 -33
- package/src/handle-hot-update.ts +117 -0
- package/src/index.ts +242 -0
- package/src/ui/inspector/Inspector.svelte +245 -0
- package/src/ui/inspector/load-inspector.js +15 -0
- package/src/ui/inspector/plugin.ts +106 -0
- package/src/utils/__tests__/dependencies.spec.ts +43 -0
- package/src/utils/__tests__/sourcemap.spec.ts +25 -0
- package/src/utils/compile.ts +159 -0
- package/src/utils/constants.ts +20 -0
- package/src/utils/dependencies.ts +241 -0
- package/src/utils/error.ts +95 -0
- package/src/utils/esbuild.ts +84 -0
- package/src/utils/hash.ts +32 -0
- package/src/utils/id.ts +135 -0
- package/src/utils/load-svelte-config.ts +115 -0
- package/src/utils/log.ts +211 -0
- package/src/utils/optimizer.ts +45 -0
- package/src/utils/options.ts +707 -0
- package/src/utils/preprocess.ts +252 -0
- package/src/utils/resolve.ts +57 -0
- package/src/utils/sourcemap.ts +58 -0
- package/src/utils/vite-plugin-svelte-cache.ts +127 -0
- package/src/utils/watch.ts +110 -0
- package/CHANGELOG.md +0 -44
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import {
|
|
2
|
+
transformWithEsbuild,
|
|
3
|
+
ESBuildOptions,
|
|
4
|
+
ResolvedConfig,
|
|
5
|
+
TransformResult,
|
|
6
|
+
Plugin
|
|
7
|
+
} from 'vite';
|
|
8
|
+
import MagicString from 'magic-string';
|
|
9
|
+
import { preprocess } from 'svelte/compiler';
|
|
10
|
+
import { Preprocessor, PreprocessorGroup, Processed, ResolvedOptions } from './options';
|
|
11
|
+
import { TransformPluginContext } from 'rollup';
|
|
12
|
+
import { log } from './log';
|
|
13
|
+
import { buildSourceMap } from './sourcemap';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
|
|
16
|
+
const supportedStyleLangs = ['css', 'less', 'sass', 'scss', 'styl', 'stylus', 'postcss'];
|
|
17
|
+
|
|
18
|
+
const supportedScriptLangs = ['ts'];
|
|
19
|
+
|
|
20
|
+
function createViteScriptPreprocessor(): Preprocessor {
|
|
21
|
+
return async ({ attributes, content, filename = '' }) => {
|
|
22
|
+
const lang = attributes.lang as string;
|
|
23
|
+
if (!supportedScriptLangs.includes(lang)) return;
|
|
24
|
+
const transformResult = await transformWithEsbuild(content, filename, {
|
|
25
|
+
loader: lang as ESBuildOptions['loader'],
|
|
26
|
+
tsconfigRaw: {
|
|
27
|
+
compilerOptions: {
|
|
28
|
+
// svelte typescript needs this flag to work with type imports
|
|
29
|
+
importsNotUsedAsValues: 'preserve',
|
|
30
|
+
preserveValueImports: true
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return {
|
|
35
|
+
code: transformResult.code,
|
|
36
|
+
map: transformResult.map
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function createViteStylePreprocessor(config: ResolvedConfig): Preprocessor {
|
|
42
|
+
const pluginName = 'vite:css';
|
|
43
|
+
const plugin = config.plugins.find((p) => p.name === pluginName);
|
|
44
|
+
if (!plugin) {
|
|
45
|
+
throw new Error(`failed to find plugin ${pluginName}`);
|
|
46
|
+
}
|
|
47
|
+
if (!plugin.transform) {
|
|
48
|
+
throw new Error(`plugin ${pluginName} has no transform`);
|
|
49
|
+
}
|
|
50
|
+
const pluginTransform = plugin.transform!.bind(null as unknown as TransformPluginContext);
|
|
51
|
+
return async ({ attributes, content, filename = '' }) => {
|
|
52
|
+
const lang = attributes.lang as string;
|
|
53
|
+
if (!supportedStyleLangs.includes(lang)) return;
|
|
54
|
+
const moduleId = `${filename}.${lang}`;
|
|
55
|
+
const transformResult: TransformResult = (await pluginTransform(
|
|
56
|
+
content,
|
|
57
|
+
moduleId
|
|
58
|
+
)) as TransformResult;
|
|
59
|
+
// patch sourcemap source to point back to original filename
|
|
60
|
+
if (transformResult.map?.sources?.[0] === moduleId) {
|
|
61
|
+
transformResult.map.sources[0] = path.basename(filename);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
code: transformResult.code,
|
|
65
|
+
map: transformResult.map ?? undefined
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function createVitePreprocessorGroup(config: ResolvedConfig): PreprocessorGroup {
|
|
71
|
+
return {
|
|
72
|
+
markup({ content, filename }) {
|
|
73
|
+
return preprocess(
|
|
74
|
+
content,
|
|
75
|
+
{
|
|
76
|
+
script: createViteScriptPreprocessor(),
|
|
77
|
+
style: createViteStylePreprocessor(config)
|
|
78
|
+
},
|
|
79
|
+
{ filename }
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
} as PreprocessorGroup;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* this appends a *{} rule to component styles to force the svelte compiler to add style classes to all nodes
|
|
87
|
+
* That means adding/removing class rules from <style> node won't trigger js updates as the scope classes are not changed
|
|
88
|
+
*
|
|
89
|
+
* only used during dev with enabled css hmr
|
|
90
|
+
*/
|
|
91
|
+
function createInjectScopeEverythingRulePreprocessorGroup(): PreprocessorGroup {
|
|
92
|
+
return {
|
|
93
|
+
style({ content, filename }) {
|
|
94
|
+
const s = new MagicString(content);
|
|
95
|
+
s.append(' *{}');
|
|
96
|
+
return {
|
|
97
|
+
code: s.toString(),
|
|
98
|
+
map: s.generateDecodedMap({
|
|
99
|
+
source: filename ? path.basename(filename) : undefined,
|
|
100
|
+
hires: true
|
|
101
|
+
})
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function buildExtraPreprocessors(options: ResolvedOptions, config: ResolvedConfig) {
|
|
108
|
+
const prependPreprocessors: PreprocessorGroup[] = [];
|
|
109
|
+
const appendPreprocessors: PreprocessorGroup[] = [];
|
|
110
|
+
|
|
111
|
+
if (options.experimental?.useVitePreprocess) {
|
|
112
|
+
log.debug('adding vite preprocessor');
|
|
113
|
+
prependPreprocessors.push(createVitePreprocessorGroup(config));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// @ts-ignore
|
|
117
|
+
const pluginsWithPreprocessorsDeprecated = config.plugins.filter((p) => p?.sveltePreprocess);
|
|
118
|
+
if (pluginsWithPreprocessorsDeprecated.length > 0) {
|
|
119
|
+
log.warn(
|
|
120
|
+
`The following plugins use the deprecated 'plugin.sveltePreprocess' field. Please contact their maintainers and ask them to move it to 'plugin.api.sveltePreprocess': ${pluginsWithPreprocessorsDeprecated
|
|
121
|
+
.map((p) => p.name)
|
|
122
|
+
.join(', ')}`
|
|
123
|
+
);
|
|
124
|
+
// patch plugin to avoid breaking
|
|
125
|
+
pluginsWithPreprocessorsDeprecated.forEach((p) => {
|
|
126
|
+
if (!p.api) {
|
|
127
|
+
p.api = {};
|
|
128
|
+
}
|
|
129
|
+
if (p.api.sveltePreprocess === undefined) {
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
p.api.sveltePreprocess = p.sveltePreprocess;
|
|
132
|
+
} else {
|
|
133
|
+
log.error(
|
|
134
|
+
`ignoring plugin.sveltePreprocess of ${p.name} because it already defined plugin.api.sveltePreprocess.`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const pluginsWithPreprocessors: Plugin[] = config.plugins.filter((p) => p?.api?.sveltePreprocess);
|
|
141
|
+
const ignored: Plugin[] = [],
|
|
142
|
+
included: Plugin[] = [];
|
|
143
|
+
for (const p of pluginsWithPreprocessors) {
|
|
144
|
+
if (
|
|
145
|
+
options.ignorePluginPreprocessors === true ||
|
|
146
|
+
(Array.isArray(options.ignorePluginPreprocessors) &&
|
|
147
|
+
options.ignorePluginPreprocessors?.includes(p.name))
|
|
148
|
+
) {
|
|
149
|
+
ignored.push(p);
|
|
150
|
+
} else {
|
|
151
|
+
included.push(p);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (ignored.length > 0) {
|
|
155
|
+
log.debug(
|
|
156
|
+
`Ignoring svelte preprocessors defined by these vite plugins: ${ignored
|
|
157
|
+
.map((p) => p.name)
|
|
158
|
+
.join(', ')}`
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
if (included.length > 0) {
|
|
162
|
+
log.debug(
|
|
163
|
+
`Adding svelte preprocessors defined by these vite plugins: ${included
|
|
164
|
+
.map((p) => p.name)
|
|
165
|
+
.join(', ')}`
|
|
166
|
+
);
|
|
167
|
+
appendPreprocessors.push(...pluginsWithPreprocessors.map((p) => p.api.sveltePreprocess));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (options.hot && options.emitCss) {
|
|
171
|
+
appendPreprocessors.push(createInjectScopeEverythingRulePreprocessorGroup());
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return { prependPreprocessors, appendPreprocessors };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function addExtraPreprocessors(options: ResolvedOptions, config: ResolvedConfig) {
|
|
178
|
+
const { prependPreprocessors, appendPreprocessors } = buildExtraPreprocessors(options, config);
|
|
179
|
+
if (prependPreprocessors.length > 0 || appendPreprocessors.length > 0) {
|
|
180
|
+
if (!options.preprocess) {
|
|
181
|
+
options.preprocess = [...prependPreprocessors, ...appendPreprocessors];
|
|
182
|
+
} else if (Array.isArray(options.preprocess)) {
|
|
183
|
+
options.preprocess.unshift(...prependPreprocessors);
|
|
184
|
+
options.preprocess.push(...appendPreprocessors);
|
|
185
|
+
} else {
|
|
186
|
+
options.preprocess = [...prependPreprocessors, options.preprocess, ...appendPreprocessors];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const generateMissingSourceMaps = !!options.experimental?.generateMissingPreprocessorSourcemaps;
|
|
190
|
+
if (options.preprocess && generateMissingSourceMaps) {
|
|
191
|
+
options.preprocess = Array.isArray(options.preprocess)
|
|
192
|
+
? options.preprocess.map((p, i) => validateSourceMapOutputWrapper(p, i))
|
|
193
|
+
: validateSourceMapOutputWrapper(options.preprocess, 0);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function validateSourceMapOutputWrapper(group: PreprocessorGroup, i: number): PreprocessorGroup {
|
|
198
|
+
const wrapper: PreprocessorGroup = {};
|
|
199
|
+
|
|
200
|
+
for (const [processorType, processorFn] of Object.entries(group) as Array<
|
|
201
|
+
// eslint-disable-next-line no-unused-vars
|
|
202
|
+
[keyof PreprocessorGroup, (options: { filename?: string; content: string }) => Processed]
|
|
203
|
+
>) {
|
|
204
|
+
wrapper[processorType] = async (options) => {
|
|
205
|
+
const result = await processorFn(options);
|
|
206
|
+
|
|
207
|
+
if (result && result.code !== options.content) {
|
|
208
|
+
let invalidMap = false;
|
|
209
|
+
if (!result.map) {
|
|
210
|
+
invalidMap = true;
|
|
211
|
+
log.warn.enabled &&
|
|
212
|
+
log.warn.once(
|
|
213
|
+
`preprocessor at index ${i} did not return a sourcemap for ${processorType} transform`,
|
|
214
|
+
{
|
|
215
|
+
filename: options.filename,
|
|
216
|
+
type: processorType,
|
|
217
|
+
processor: processorFn.toString()
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
} else if ((result.map as any)?.mappings === '') {
|
|
221
|
+
invalidMap = true;
|
|
222
|
+
log.warn.enabled &&
|
|
223
|
+
log.warn.once(
|
|
224
|
+
`preprocessor at index ${i} returned an invalid empty sourcemap for ${processorType} transform`,
|
|
225
|
+
{
|
|
226
|
+
filename: options.filename,
|
|
227
|
+
type: processorType,
|
|
228
|
+
processor: processorFn.toString()
|
|
229
|
+
}
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
if (invalidMap) {
|
|
233
|
+
try {
|
|
234
|
+
const map = await buildSourceMap(options.content, result.code, options.filename);
|
|
235
|
+
if (map) {
|
|
236
|
+
log.debug.enabled &&
|
|
237
|
+
log.debug(
|
|
238
|
+
`adding generated sourcemap to preprocesor result for ${options.filename}`
|
|
239
|
+
);
|
|
240
|
+
result.map = map;
|
|
241
|
+
}
|
|
242
|
+
} catch (e) {
|
|
243
|
+
log.error(`failed to build sourcemap`, e);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return result;
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return wrapper;
|
|
252
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { builtinModules, createRequire } from 'module';
|
|
3
|
+
import { is_common_without_svelte_field, resolveDependencyData } from './dependencies';
|
|
4
|
+
import { VitePluginSvelteCache } from './vite-plugin-svelte-cache';
|
|
5
|
+
|
|
6
|
+
export function resolveViaPackageJsonSvelte(
|
|
7
|
+
importee: string,
|
|
8
|
+
importer: string | undefined,
|
|
9
|
+
cache: VitePluginSvelteCache
|
|
10
|
+
): string | void {
|
|
11
|
+
if (
|
|
12
|
+
importer &&
|
|
13
|
+
isBareImport(importee) &&
|
|
14
|
+
!isNodeInternal(importee) &&
|
|
15
|
+
!is_common_without_svelte_field(importee)
|
|
16
|
+
) {
|
|
17
|
+
const cached = cache.getResolvedSvelteField(importee, importer);
|
|
18
|
+
if (cached) {
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
const localRequire = createRequire(importer);
|
|
22
|
+
const pkgData = resolveDependencyData(importee, localRequire);
|
|
23
|
+
if (pkgData) {
|
|
24
|
+
const { pkg, dir } = pkgData;
|
|
25
|
+
if (pkg.svelte) {
|
|
26
|
+
const result = path.resolve(dir, pkg.svelte);
|
|
27
|
+
cache.setResolvedSvelteField(importee, importer, result);
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isNodeInternal(importee: string) {
|
|
35
|
+
return importee.startsWith('node:') || builtinModules.includes(importee);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isBareImport(importee: string): boolean {
|
|
39
|
+
if (
|
|
40
|
+
!importee ||
|
|
41
|
+
importee[0] === '.' ||
|
|
42
|
+
importee[0] === '\0' ||
|
|
43
|
+
importee.includes(':') ||
|
|
44
|
+
path.isAbsolute(importee)
|
|
45
|
+
) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const parts = importee.split('/');
|
|
49
|
+
switch (parts.length) {
|
|
50
|
+
case 1:
|
|
51
|
+
return true;
|
|
52
|
+
case 2:
|
|
53
|
+
return parts[0].startsWith('@');
|
|
54
|
+
default:
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import MagicString, { MagicStringOptions } from 'magic-string';
|
|
2
|
+
import { log } from './log';
|
|
3
|
+
|
|
4
|
+
export async function buildMagicString(
|
|
5
|
+
from: string,
|
|
6
|
+
to: string,
|
|
7
|
+
options?: MagicStringOptions
|
|
8
|
+
): Promise<MagicString | null> {
|
|
9
|
+
let diff_match_patch, DIFF_DELETE: number, DIFF_INSERT: number;
|
|
10
|
+
try {
|
|
11
|
+
const dmpPkg = await import('diff-match-patch');
|
|
12
|
+
diff_match_patch = dmpPkg.diff_match_patch;
|
|
13
|
+
DIFF_INSERT = dmpPkg.DIFF_INSERT;
|
|
14
|
+
DIFF_DELETE = dmpPkg.DIFF_DELETE;
|
|
15
|
+
} catch (e) {
|
|
16
|
+
log.error.once(
|
|
17
|
+
'Failed to import optional dependency "diff-match-patch". Please install it to enable generated sourcemaps.'
|
|
18
|
+
);
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const dmp = new diff_match_patch();
|
|
23
|
+
const diffs = dmp.diff_main(from, to);
|
|
24
|
+
dmp.diff_cleanupSemantic(diffs);
|
|
25
|
+
const m = new MagicString(from, options);
|
|
26
|
+
let pos = 0;
|
|
27
|
+
for (let i = 0; i < diffs.length; i++) {
|
|
28
|
+
const diff = diffs[i];
|
|
29
|
+
const nextDiff = diffs[i + 1];
|
|
30
|
+
if (diff[0] === DIFF_DELETE) {
|
|
31
|
+
if (nextDiff?.[0] === DIFF_INSERT) {
|
|
32
|
+
// delete followed by insert, use overwrite and skip ahead
|
|
33
|
+
m.overwrite(pos, pos + diff[1].length, nextDiff[1]);
|
|
34
|
+
i++;
|
|
35
|
+
} else {
|
|
36
|
+
m.remove(pos, pos + diff[1].length);
|
|
37
|
+
}
|
|
38
|
+
pos += diff[1].length;
|
|
39
|
+
} else if (diff[0] === DIFF_INSERT) {
|
|
40
|
+
if (nextDiff) {
|
|
41
|
+
m.appendRight(pos, diff[1]);
|
|
42
|
+
} else {
|
|
43
|
+
m.append(diff[1]);
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
// unchanged block, advance pos
|
|
47
|
+
pos += diff[1].length;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// at this point m.toString() === to
|
|
51
|
+
return m;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function buildSourceMap(from: string, to: string, filename?: string) {
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
const m = await buildMagicString(from, to, { filename });
|
|
57
|
+
return m ? m.generateDecodedMap({ source: filename, hires: true, includeContent: false }) : null;
|
|
58
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { SvelteRequest } from './id';
|
|
2
|
+
import { Code, CompileData } from './compile';
|
|
3
|
+
|
|
4
|
+
export class VitePluginSvelteCache {
|
|
5
|
+
private _css = new Map<string, Code>();
|
|
6
|
+
private _js = new Map<string, Code>();
|
|
7
|
+
private _dependencies = new Map<string, string[]>();
|
|
8
|
+
private _dependants = new Map<string, Set<string>>();
|
|
9
|
+
private _resolvedSvelteFields = new Map<string, string>();
|
|
10
|
+
private _errors = new Map<string, any>();
|
|
11
|
+
|
|
12
|
+
public update(compileData: CompileData) {
|
|
13
|
+
this._errors.delete(compileData.normalizedFilename);
|
|
14
|
+
this.updateCSS(compileData);
|
|
15
|
+
this.updateJS(compileData);
|
|
16
|
+
this.updateDependencies(compileData);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public has(svelteRequest: SvelteRequest) {
|
|
20
|
+
const id = svelteRequest.normalizedFilename;
|
|
21
|
+
return this._errors.has(id) || this._js.has(id) || this._css.has(id);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public setError(svelteRequest: SvelteRequest, error: any) {
|
|
25
|
+
// keep dependency info, otherwise errors in dependants would not trigger an update after fixing
|
|
26
|
+
// because they are no longer watched
|
|
27
|
+
this.remove(svelteRequest, true);
|
|
28
|
+
this._errors.set(svelteRequest.normalizedFilename, error);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private updateCSS(compileData: CompileData) {
|
|
32
|
+
this._css.set(compileData.normalizedFilename, compileData.compiled.css);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private updateJS(compileData: CompileData) {
|
|
36
|
+
if (!compileData.ssr) {
|
|
37
|
+
// do not cache SSR js
|
|
38
|
+
this._js.set(compileData.normalizedFilename, compileData.compiled.js);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private updateDependencies(compileData: CompileData) {
|
|
43
|
+
const id = compileData.normalizedFilename;
|
|
44
|
+
const prevDependencies = this._dependencies.get(id) || [];
|
|
45
|
+
const dependencies = compileData.dependencies;
|
|
46
|
+
this._dependencies.set(id, dependencies);
|
|
47
|
+
const removed = prevDependencies.filter((d) => !dependencies.includes(d));
|
|
48
|
+
const added = dependencies.filter((d) => !prevDependencies.includes(d));
|
|
49
|
+
added.forEach((d) => {
|
|
50
|
+
if (!this._dependants.has(d)) {
|
|
51
|
+
this._dependants.set(d, new Set<string>());
|
|
52
|
+
}
|
|
53
|
+
this._dependants.get(d)!.add(compileData.filename);
|
|
54
|
+
});
|
|
55
|
+
removed.forEach((d) => {
|
|
56
|
+
this._dependants.get(d)!.delete(compileData.filename);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public remove(svelteRequest: SvelteRequest, keepDependencies: boolean = false): boolean {
|
|
61
|
+
const id = svelteRequest.normalizedFilename;
|
|
62
|
+
let removed = false;
|
|
63
|
+
if (this._errors.delete(id)) {
|
|
64
|
+
removed = true;
|
|
65
|
+
}
|
|
66
|
+
if (this._js.delete(id)) {
|
|
67
|
+
removed = true;
|
|
68
|
+
}
|
|
69
|
+
if (this._css.delete(id)) {
|
|
70
|
+
removed = true;
|
|
71
|
+
}
|
|
72
|
+
if (!keepDependencies) {
|
|
73
|
+
const dependencies = this._dependencies.get(id);
|
|
74
|
+
if (dependencies) {
|
|
75
|
+
removed = true;
|
|
76
|
+
dependencies.forEach((d) => {
|
|
77
|
+
const dependants = this._dependants.get(d);
|
|
78
|
+
if (dependants && dependants.has(svelteRequest.filename)) {
|
|
79
|
+
dependants.delete(svelteRequest.filename);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
this._dependencies.delete(id);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return removed;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public getCSS(svelteRequest: SvelteRequest) {
|
|
90
|
+
return this._css.get(svelteRequest.normalizedFilename);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public getJS(svelteRequest: SvelteRequest) {
|
|
94
|
+
if (!svelteRequest.ssr) {
|
|
95
|
+
// SSR js isn't cached
|
|
96
|
+
return this._js.get(svelteRequest.normalizedFilename);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public getError(svelteRequest: SvelteRequest) {
|
|
101
|
+
return this._errors.get(svelteRequest.normalizedFilename);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public getDependants(path: string): string[] {
|
|
105
|
+
const dependants = this._dependants.get(path);
|
|
106
|
+
return dependants ? [...dependants] : [];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public getResolvedSvelteField(name: string, importer?: string): string | void {
|
|
110
|
+
return this._resolvedSvelteFields.get(this._getResolvedSvelteFieldKey(name, importer));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public setResolvedSvelteField(
|
|
114
|
+
importee: string,
|
|
115
|
+
importer: string | undefined = undefined,
|
|
116
|
+
resolvedSvelte: string
|
|
117
|
+
) {
|
|
118
|
+
this._resolvedSvelteFields.set(
|
|
119
|
+
this._getResolvedSvelteFieldKey(importee, importer),
|
|
120
|
+
resolvedSvelte
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private _getResolvedSvelteFieldKey(importee: string, importer?: string): string {
|
|
125
|
+
return importer ? `${importer} > ${importee}` : importee;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { VitePluginSvelteCache } from './vite-plugin-svelte-cache';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { log } from './log';
|
|
4
|
+
import { IdParser } from './id';
|
|
5
|
+
import { ResolvedOptions } from './options';
|
|
6
|
+
import { knownSvelteConfigNames } from './load-svelte-config';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { FSWatcher } from 'vite';
|
|
9
|
+
|
|
10
|
+
export function setupWatchers(
|
|
11
|
+
options: ResolvedOptions,
|
|
12
|
+
cache: VitePluginSvelteCache,
|
|
13
|
+
requestParser: IdParser
|
|
14
|
+
) {
|
|
15
|
+
const { server, configFile: svelteConfigFile } = options;
|
|
16
|
+
if (!server) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const { watcher, ws } = server;
|
|
20
|
+
const { root, server: serverConfig } = server.config;
|
|
21
|
+
|
|
22
|
+
const emitChangeEventOnDependants = (filename: string) => {
|
|
23
|
+
const dependants = cache.getDependants(filename);
|
|
24
|
+
dependants.forEach((dependant) => {
|
|
25
|
+
if (fs.existsSync(dependant)) {
|
|
26
|
+
log.debug(
|
|
27
|
+
`emitting virtual change event for "${dependant}" because depdendency "${filename}" changed`
|
|
28
|
+
);
|
|
29
|
+
watcher.emit('change', dependant);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const removeUnlinkedFromCache = (filename: string) => {
|
|
35
|
+
const svelteRequest = requestParser(filename, false);
|
|
36
|
+
if (svelteRequest) {
|
|
37
|
+
const removedFromCache = cache.remove(svelteRequest);
|
|
38
|
+
if (removedFromCache) {
|
|
39
|
+
log.debug(`cleared VitePluginSvelteCache for deleted file ${filename}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const triggerViteRestart = (filename: string) => {
|
|
45
|
+
if (serverConfig.middlewareMode) {
|
|
46
|
+
// in middlewareMode we can't restart the server automatically
|
|
47
|
+
// show the user an overlay instead
|
|
48
|
+
const message =
|
|
49
|
+
'Svelte config change detected, restart your dev process to apply the changes.';
|
|
50
|
+
log.info(message, filename);
|
|
51
|
+
ws.send({
|
|
52
|
+
type: 'error',
|
|
53
|
+
err: { message, stack: '', plugin: 'vite-plugin-svelte', id: filename }
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
log.info(`svelte config changed: restarting vite server. - file: ${filename}`);
|
|
57
|
+
server.restart();
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// collection of watcher listeners by event
|
|
62
|
+
const listenerCollection = {
|
|
63
|
+
add: [] as Array<Function>,
|
|
64
|
+
change: [emitChangeEventOnDependants],
|
|
65
|
+
unlink: [removeUnlinkedFromCache, emitChangeEventOnDependants]
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
if (svelteConfigFile !== false) {
|
|
69
|
+
// configFile false means we ignore the file and external process is responsible
|
|
70
|
+
const possibleSvelteConfigs = knownSvelteConfigNames.map((cfg) => path.join(root, cfg));
|
|
71
|
+
const restartOnConfigAdd = (filename: string) => {
|
|
72
|
+
if (possibleSvelteConfigs.includes(filename)) {
|
|
73
|
+
triggerViteRestart(filename);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const restartOnConfigChange = (filename: string) => {
|
|
78
|
+
if (filename === svelteConfigFile) {
|
|
79
|
+
triggerViteRestart(filename);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
if (svelteConfigFile) {
|
|
84
|
+
listenerCollection.change.push(restartOnConfigChange);
|
|
85
|
+
listenerCollection.unlink.push(restartOnConfigChange);
|
|
86
|
+
} else {
|
|
87
|
+
listenerCollection.add.push(restartOnConfigAdd);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
Object.entries(listenerCollection).forEach(([evt, listeners]) => {
|
|
92
|
+
if (listeners.length > 0) {
|
|
93
|
+
watcher.on(evt, (filename) => listeners.forEach((listener) => listener(filename)));
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// taken from vite utils
|
|
98
|
+
export function ensureWatchedFile(watcher: FSWatcher, file: string | null, root: string): void {
|
|
99
|
+
if (
|
|
100
|
+
file &&
|
|
101
|
+
// only need to watch if out of root
|
|
102
|
+
!file.startsWith(root + '/') &&
|
|
103
|
+
// some rollup plugins use null bytes for private resolved Ids
|
|
104
|
+
!file.includes('\0') &&
|
|
105
|
+
fs.existsSync(file)
|
|
106
|
+
) {
|
|
107
|
+
// resolve file to normalized system path
|
|
108
|
+
watcher.add(path.resolve(file));
|
|
109
|
+
}
|
|
110
|
+
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# @sveltejs/vite-plugin-svelte
|
|
2
|
-
|
|
3
|
-
## 1.0.0-next.9
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- [#38](https://github.com/sveltejs/vite-plugin-svelte/pull/38) [`5aef91c`](https://github.com/sveltejs/vite-plugin-svelte/commit/5aef91c8752c8de94a1f1fcb28618606b7c44670) fix: ensure esm config loading works on windows
|
|
8
|
-
|
|
9
|
-
## 1.0.0-next.8
|
|
10
|
-
|
|
11
|
-
### Minor Changes
|
|
12
|
-
|
|
13
|
-
- [#35](https://github.com/sveltejs/vite-plugin-svelte/pull/35) [`4018ce6`](https://github.com/sveltejs/vite-plugin-svelte/commit/4018ce621b4df75877e0e18057c332f27158d42b) Feature: Support esm in svelte.config.js and svelte.config.mjs
|
|
14
|
-
|
|
15
|
-
* [#35](https://github.com/sveltejs/vite-plugin-svelte/pull/35) [`4018ce6`](https://github.com/sveltejs/vite-plugin-svelte/commit/4018ce621b4df75877e0e18057c332f27158d42b) Feature: add configFile option
|
|
16
|
-
|
|
17
|
-
### Patch Changes
|
|
18
|
-
|
|
19
|
-
- [#34](https://github.com/sveltejs/vite-plugin-svelte/pull/34) [`e5d4749`](https://github.com/sveltejs/vite-plugin-svelte/commit/e5d4749c0850260a295daab9cb15866fe58ee709) fix: watch preprocessor dependencies and trigger hmr on change
|
|
20
|
-
|
|
21
|
-
## 1.0.0-next.7
|
|
22
|
-
|
|
23
|
-
### Minor Changes
|
|
24
|
-
|
|
25
|
-
- [#32](https://github.com/sveltejs/vite-plugin-svelte/pull/32) [`113bb7d`](https://github.com/sveltejs/vite-plugin-svelte/commit/113bb7dc330a7517085d12d1d0758a376a12253f) Reduced cache usage, share css cache between SSR and client
|
|
26
|
-
|
|
27
|
-
## 1.0.0-next.6
|
|
28
|
-
|
|
29
|
-
### Minor Changes
|
|
30
|
-
|
|
31
|
-
- 1be46f1: improved css hmr
|
|
32
|
-
- a0f5a65: Allow other vite plugins to define preprocessors
|
|
33
|
-
|
|
34
|
-
### Patch Changes
|
|
35
|
-
|
|
36
|
-
- 8d9ef96: fix: do not preserve types unless useVitePreprocess option is true
|
|
37
|
-
- 6f4a253: disable svelte-hmr overlay by default
|
|
38
|
-
- 18647aa: improve virtual css module path (fixes #14)
|
|
39
|
-
|
|
40
|
-
## 1.0.0-next.5
|
|
41
|
-
|
|
42
|
-
### Patch Changes
|
|
43
|
-
|
|
44
|
-
- 61439ae: initial release
|