UNPKG

rwsdk

Version:

Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime

69 lines (68 loc) 2.59 kB
import debug from "debug"; const log = debug("rws-vite-plugin:hmr-stability"); let stabilityPromise = null; let stabilityResolver = null; let debounceTimer = null; const DEBOUNCE_MS = 500; function startWaitingForStability() { if (!stabilityPromise) { log("Starting to wait for server stability..."); stabilityPromise = new Promise((resolve) => { stabilityResolver = resolve; }); // Start the timer. If it fires, we're stable. debounceTimer = setTimeout(finishWaiting, DEBOUNCE_MS); } } function activityDetected() { if (stabilityPromise) { // If we're waiting for stability, reset the timer. log("Activity detected, resetting stability timer."); if (debounceTimer) clearTimeout(debounceTimer); debounceTimer = setTimeout(finishWaiting, DEBOUNCE_MS); } } function finishWaiting() { if (stabilityResolver) { log("Server appears stable. Resolving promise."); stabilityResolver(); } stabilityPromise = null; stabilityResolver = null; debounceTimer = null; } export function hmrStabilityPlugin() { return { name: "rws-vite-plugin:hmr-stability", // Monitor server activity transform() { activityDetected(); return null; }, configureServer(server) { // Return a function to ensure our middleware is placed after internal middlewares return () => { server.middlewares.use(async function rwsdkStaleBundleErrorHandler(err, req, res, next) { if (err && typeof err.message === "string" && err.message.includes("new version of the pre-bundle")) { log("Caught stale pre-bundle error. Waiting for server to stabilize..."); startWaitingForStability(); await stabilityPromise; log("Server stabilized. Sending full-reload and redirecting."); // Signal the client to do a full page reload. server.environments.client.hot.send({ type: "full-reload", }); // No need to wait further here, the stability promise handled it. res.writeHead(307, { Location: req.url }); res.end(); return; } next(err); }); }; }, }; }