From 3bcf621a1cce9fea6824574a4cbf83757516c5a5 Mon Sep 17 00:00:00 2001 From: Hornwitser Date: Mon, 3 Feb 2025 10:30:35 +0100 Subject: [PATCH] Reload page when watch restarts serve Host an EventSource server that notifies current open browser windows to reload the page when the watch mode has restarted the server. This is the last piece to making the page update live after editing and saving a source file. --- src/cli.ts | 18 ++++++++- src/components/BasePage.tsx | 9 +++++ src/utils/event-server.test.ts | 74 ++++++++++++++++++++++++++++++++++ src/utils/event-server.ts | 39 ++++++++++++++++++ src/utils/http-server.ts | 2 +- 5 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 src/utils/event-server.test.ts create mode 100644 src/utils/event-server.ts diff --git a/src/cli.ts b/src/cli.ts index 6da517f..dc20ac2 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -6,6 +6,7 @@ import { pages } from "./pages.js"; import type { Page } from "./types.js"; import { resolveRefs } from "./utils/resolve-refs.js"; import { createHttpServer } from "./utils/http-server.js"; +import { broadcastMessage, createEventServer } from "./utils/event-server.js"; const srcDir = "build/node"; const webDir = "web"; @@ -76,14 +77,27 @@ function serve() { } ); - server.listen(8080); + server.listen(8080, () => { process.send?.("listening"); }); console.log("Listening on http://localhost:8080"); } function watch(script: string) { + const eventServer = createEventServer(); + const eventPort = 8081; + eventServer.httpServer.listen(eventPort); + let child: ChildProcess; function start() { - child = fork(script, ["serve"]); + child = fork(script, ["serve"], { + env: { + DEV_EVENT_PORT: String(eventPort), + } + }); + child.on("message", message => { + if (message === "listening") { + broadcastMessage(eventServer, "reload"); + } + }) } function restart() { if (child.exitCode === null) { diff --git a/src/components/BasePage.tsx b/src/components/BasePage.tsx index 4994328..a50fc38 100644 --- a/src/components/BasePage.tsx +++ b/src/components/BasePage.tsx @@ -5,6 +5,14 @@ interface BaseProps { children: Node | Node[], } export default function BasePage(props: BaseProps) { + let reloadScript = null; + if (process.env.DEV_EVENT_PORT) { + const content = `const url = new URL("/events", location); +url.port = ${process.env.DEV_EVENT_PORT}; +const source = new EventSource(url); +source.addEventListener("reload", () => location.reload());`; + reloadScript = ; + } return @@ -12,6 +20,7 @@ export default function BasePage(props: BaseProps) {