Fix tsconfig.json
update causing the server to crash (#8736)
This commit is contained in:
parent
d125095d09
commit
cb62f02ea1
3 changed files with 52 additions and 16 deletions
5
.changeset/red-masks-drop.md
Normal file
5
.changeset/red-masks-drop.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix `tsconfig.json` update causing the server to crash
|
|
@ -148,9 +148,15 @@ export const _internal = {
|
|||
hasContentFlag(modUrl, DATA_FLAG) ||
|
||||
Boolean(getContentRendererByViteId(modUrl, settings))
|
||||
) {
|
||||
const mod = await viteServer.moduleGraph.getModuleByUrl(modUrl);
|
||||
if (mod) {
|
||||
viteServer.moduleGraph.invalidateModule(mod);
|
||||
try {
|
||||
const mod = await viteServer.moduleGraph.getModuleByUrl(modUrl);
|
||||
if (mod) {
|
||||
viteServer.moduleGraph.invalidateModule(mod);
|
||||
}
|
||||
} catch (e: any) {
|
||||
// The server may be closed due to a restart caused by this file change
|
||||
if (e.code === 'ERR_CLOSED_SERVER') break;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,52 @@
|
|||
import { EventEmitter } from 'node:events';
|
||||
import path from 'node:path';
|
||||
import type * as vite from 'vite';
|
||||
import type { ModuleLoader, ModuleLoaderEventEmitter } from './loader.js';
|
||||
|
||||
export function createViteLoader(viteServer: vite.ViteDevServer): ModuleLoader {
|
||||
const events = new EventEmitter() as ModuleLoaderEventEmitter;
|
||||
|
||||
viteServer.watcher.on('add', (...args) => events.emit('file-add', args));
|
||||
viteServer.watcher.on('unlink', (...args) => events.emit('file-unlink', args));
|
||||
viteServer.watcher.on('change', (...args) => events.emit('file-change', args));
|
||||
let isTsconfigUpdated = false;
|
||||
function isTsconfigUpdate(filePath: string) {
|
||||
const result = path.basename(filePath) === 'tsconfig.json';
|
||||
if (result) isTsconfigUpdated = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
wrapMethod(viteServer.ws, 'send', (msg) => {
|
||||
// Skip event emit on tsconfig change as Vite restarts the server, and we don't
|
||||
// want to trigger unnecessary work that will be invalidated shortly.
|
||||
viteServer.watcher.on('add', (...args) => {
|
||||
if (!isTsconfigUpdate(args[0])) {
|
||||
events.emit('file-add', args);
|
||||
}
|
||||
});
|
||||
viteServer.watcher.on('unlink', (...args) => {
|
||||
if (!isTsconfigUpdate(args[0])) {
|
||||
events.emit('file-unlink', args);
|
||||
}
|
||||
});
|
||||
viteServer.watcher.on('change', (...args) => {
|
||||
if (!isTsconfigUpdate(args[0])) {
|
||||
events.emit('file-change', args);
|
||||
}
|
||||
});
|
||||
|
||||
const _wsSend = viteServer.ws.send;
|
||||
viteServer.ws.send = function (...args: any) {
|
||||
// If the tsconfig changed, Vite will trigger a reload as it invalidates the module.
|
||||
// However in Astro, the whole server is restarted when the tsconfig changes. If we
|
||||
// do a restart and reload at the same time, the browser will refetch and the server
|
||||
// is not ready yet, causing a blank page. Here we block that reload from happening.
|
||||
if (isTsconfigUpdated) {
|
||||
isTsconfigUpdated = false;
|
||||
return;
|
||||
}
|
||||
const msg = args[0] as vite.HMRPayload;
|
||||
if (msg?.type === 'error') {
|
||||
events.emit('hmr-error', msg);
|
||||
}
|
||||
});
|
||||
_wsSend.apply(this, args);
|
||||
};
|
||||
|
||||
return {
|
||||
import(src) {
|
||||
|
@ -56,11 +89,3 @@ export function createViteLoader(viteServer: vite.ViteDevServer): ModuleLoader {
|
|||
events,
|
||||
};
|
||||
}
|
||||
|
||||
function wrapMethod(object: any, method: string, newFn: (...args: any[]) => void) {
|
||||
const orig = object[method];
|
||||
object[method] = function (...args: any[]) {
|
||||
newFn.apply(this, args);
|
||||
return orig.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue