summaryrefslogtreecommitdiff
path: root/src/hot_reload.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/hot_reload.js')
-rw-r--r--src/hot_reload.js81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/hot_reload.js b/src/hot_reload.js
new file mode 100644
index 0000000..0777380
--- /dev/null
+++ b/src/hot_reload.js
@@ -0,0 +1,81 @@
+const WS_RETRY_MS = 1_000;
+
+function refetchCSS(file) {
+ const node = Array.from(document.head.childNodes).find(
+ (n) => n.href && n.href.includes(file),
+ );
+ if (!node) {
+ console.warn("Could not find node", file);
+ console.log(Array.from(document.head.childNodes));
+ return;
+ }
+ const url = new URL(node.href);
+ url.searchParams.set("v", parseInt(url.searchParams.get("v") || "0") + 1);
+
+ const n2 = node.cloneNode();
+ n2.href = url.toString();
+ document.head.appendChild(n2);
+ setTimeout(() => {
+ document.head.removeChild(node);
+ }, 100);
+}
+
+let __file_to_module = {};
+function refetchJS(file) {
+ if (file in __file_to_module) {
+ const o = __file_to_module[file];
+ if ("__cleanup" in o) {
+ o.__cleanup();
+ } else {
+ console.warn("no cleanup");
+ }
+ }
+ import(`/static/${file}?v=${Date.now()}`)
+ .then((m) => {
+ __file_to_module[file] = m;
+ })
+ .catch((e) => {
+ console.error(e);
+ });
+ return;
+}
+
+function connect() {
+ console.log("try to connect through websocket");
+ const ws = new WebSocket(`ws://${window.location.host}/dev-hr/ws`);
+
+ const file2timeout = new Map();
+ ws.addEventListener("message", (msg) => {
+ const file = msg.data; // the path to a changed file relative to `static/`.
+ if (file2timeout.has(file)) clearTimeout(file2timeout.get(file));
+ file2timeout.set(
+ file,
+ setTimeout(() => {
+ if (file.slice(-4) === ".css") refetchCSS(file);
+ else if (file.slice(-3) === ".js") refetchJS(file);
+ else console.warn("unknown file extension", file);
+ }, 100),
+ );
+ });
+
+ ws.addEventListener("open", () => {
+ console.log("websocket connected");
+ });
+
+ ws.addEventListener("close", () => {
+ console.log("websocket disconnected");
+ setTimeout(() => {
+ try {
+ connect();
+ } catch (e) {
+ console.error(e);
+ }
+ }, WS_RETRY_MS);
+ });
+
+ ws.addEventListener("error", (e) => {
+ console.error(e);
+ ws.close();
+ });
+}
+setTimeout(() => connect(), WS_RETRY_MS);