Skip to content

Commit 696e2e1

Browse files
authored
fix: track compile errors in cache and send hmr update when returning to last working state (#371)
1 parent 1e55af3 commit 696e2e1

File tree

4 files changed

+61
-21
lines changed

4 files changed

+61
-21
lines changed

.changeset/nervous-jobs-remain.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/vite-plugin-svelte': patch
3+
---
4+
5+
fix hmr not updating a component when returning to the last working state from an error state

packages/vite-plugin-svelte/src/handle-hot-update.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,39 @@ export async function handleHotUpdate(
1515
cache: VitePluginSvelteCache,
1616
options: ResolvedOptions
1717
): Promise<ModuleNode[] | void> {
18-
const { read, server } = ctx;
19-
20-
const cachedJS = cache.getJS(svelteRequest);
21-
if (!cachedJS) {
18+
if (!cache.has(svelteRequest)) {
2219
// file hasn't been requested yet (e.g. async component)
23-
log.debug(`handleHotUpdate first call ${svelteRequest.id}`);
20+
log.debug(`handleHotUpdate called before initial transform for ${svelteRequest.id}`);
2421
return;
2522
}
23+
const { read, server } = ctx;
24+
25+
const cachedJS = cache.getJS(svelteRequest);
2626
const cachedCss = cache.getCSS(svelteRequest);
2727

2828
const content = await read();
29-
const compileData: CompileData = await compileSvelte(svelteRequest, content, options);
30-
cache.update(compileData);
29+
let compileData: CompileData;
30+
try {
31+
compileData = await compileSvelte(svelteRequest, content, options);
32+
cache.update(compileData);
33+
} catch (e) {
34+
cache.setError(svelteRequest, e);
35+
throw e;
36+
}
3137

3238
const affectedModules = new Set<ModuleNode | undefined>();
3339

3440
const cssModule = server.moduleGraph.getModuleById(svelteRequest.cssId);
3541
const mainModule = server.moduleGraph.getModuleById(svelteRequest.id);
3642
const cssUpdated = cssModule && cssChanged(cachedCss, compileData.compiled.css);
3743
if (cssUpdated) {
38-
log.debug('handleHotUpdate css changed');
44+
log.debug(`handleHotUpdate css changed for ${svelteRequest.cssId}`);
3945
affectedModules.add(cssModule);
4046
}
4147
const jsUpdated =
4248
mainModule && jsChanged(cachedJS, compileData.compiled.js, svelteRequest.filename);
4349
if (jsUpdated) {
44-
log.debug('handleHotUpdate js changed');
50+
log.debug(`handleHotUpdate js changed for ${svelteRequest.id}`);
4551
affectedModules.add(mainModule);
4652
}
4753

packages/vite-plugin-svelte/src/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
183183
try {
184184
compileData = await compileSvelte(svelteRequest, code, options);
185185
} catch (e) {
186+
cache.setError(svelteRequest, e);
186187
throw toRollupError(e, options);
187188
}
188189
logCompilerWarnings(compileData.compiled.warnings, options);
@@ -209,7 +210,11 @@ export function svelte(inlineOptions?: Partial<Options>): Plugin[] {
209210
}
210211
const svelteRequest = requestParser(ctx.file, false, ctx.timestamp);
211212
if (svelteRequest) {
212-
return handleHotUpdate(compileSvelte, ctx, svelteRequest, cache, options);
213+
try {
214+
return handleHotUpdate(compileSvelte, ctx, svelteRequest, cache, options);
215+
} catch (e) {
216+
throw toRollupError(e, options);
217+
}
213218
}
214219
}
215220
}

packages/vite-plugin-svelte/src/utils/vite-plugin-svelte-cache.ts

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,27 @@ export class VitePluginSvelteCache {
77
private _dependencies = new Map<string, string[]>();
88
private _dependants = new Map<string, Set<string>>();
99
private _resolvedSvelteFields = new Map<string, string>();
10+
private _errors = new Map<string, any>();
1011

1112
public update(compileData: CompileData) {
13+
this._errors.delete(compileData.normalizedFilename);
1214
this.updateCSS(compileData);
1315
this.updateJS(compileData);
1416
this.updateDependencies(compileData);
1517
}
1618

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+
1731
private updateCSS(compileData: CompileData) {
1832
this._css.set(compileData.normalizedFilename, compileData.compiled.css);
1933
}
@@ -43,26 +57,32 @@ export class VitePluginSvelteCache {
4357
});
4458
}
4559

46-
public remove(svelteRequest: SvelteRequest): boolean {
60+
public remove(svelteRequest: SvelteRequest, keepDependencies: boolean = false): boolean {
4761
const id = svelteRequest.normalizedFilename;
4862
let removed = false;
63+
if (this._errors.delete(id)) {
64+
removed = true;
65+
}
4966
if (this._js.delete(id)) {
5067
removed = true;
5168
}
5269
if (this._css.delete(id)) {
5370
removed = true;
5471
}
55-
const dependencies = this._dependencies.get(id);
56-
if (dependencies) {
57-
removed = true;
58-
dependencies.forEach((d) => {
59-
const dependants = this._dependants.get(d);
60-
if (dependants && dependants.has(svelteRequest.filename)) {
61-
dependants.delete(svelteRequest.filename);
62-
}
63-
});
64-
this._dependencies.delete(id);
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+
}
6584
}
85+
6686
return removed;
6787
}
6888

@@ -77,6 +97,10 @@ export class VitePluginSvelteCache {
7797
}
7898
}
7999

100+
public getError(svelteRequest: SvelteRequest) {
101+
return this._errors.get(svelteRequest.normalizedFilename);
102+
}
103+
80104
public getDependants(path: string): string[] {
81105
const dependants = this._dependants.get(path);
82106
return dependants ? [...dependants] : [];

0 commit comments

Comments
 (0)