summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Bjorn Lu <bjornlu.dev@gmail.com> 2023-10-03 21:36:38 +0800
committerGravatar GitHub <noreply@github.com> 2023-10-03 14:36:38 +0100
commitd1c75fe158839699c59728cf3a83888e8c72a459 (patch)
tree49e61a2c08f1d814e3ad6940bbc6e62f9501c803
parentf9477aade1648c7adbc1a69df4d3e09b145a14fc (diff)
downloadastro-d1c75fe158839699c59728cf3a83888e8c72a459.tar.gz
astro-d1c75fe158839699c59728cf3a83888e8c72a459.tar.zst
astro-d1c75fe158839699c59728cf3a83888e8c72a459.zip
Fix `tsconfig.json` update causing the server to crash (#8736)
-rw-r--r--.changeset/red-masks-drop.md5
-rw-r--r--packages/astro/src/content/vite-plugin-content-imports.ts12
-rw-r--r--packages/astro/src/core/module-loader/vite.ts51
3 files changed, 52 insertions, 16 deletions
diff --git a/.changeset/red-masks-drop.md b/.changeset/red-masks-drop.md
new file mode 100644
index 000000000..3564fa9e8
--- /dev/null
+++ b/.changeset/red-masks-drop.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fix `tsconfig.json` update causing the server to crash
diff --git a/packages/astro/src/content/vite-plugin-content-imports.ts b/packages/astro/src/content/vite-plugin-content-imports.ts
index 4643e0922..15ca6d956 100644
--- a/packages/astro/src/content/vite-plugin-content-imports.ts
+++ b/packages/astro/src/content/vite-plugin-content-imports.ts
@@ -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;
}
}
}
diff --git a/packages/astro/src/core/module-loader/vite.ts b/packages/astro/src/core/module-loader/vite.ts
index f58b2e720..48ec230f0 100644
--- a/packages/astro/src/core/module-loader/vite.ts
+++ b/packages/astro/src/core/module-loader/vite.ts
@@ -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);
- };
-}