Automates reloading a website during development; served using vanilla Deno server using a websocket.
Created
December 15, 2024 08:06
-
-
Save thehappycheese/c2500bd9c601bb10e2777a20b55c2786 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function createHotReloadMiddleware(watchPath: string, script_route = "/hmr.js", socket_route="/hmrws") { | |
const clients = new Set<WebSocket>(); | |
// File watcher for HMR | |
const watcher = Deno.watchFs(watchPath); | |
const debounceTime = 100; // Debounce time in milliseconds | |
let lastEventTime = 0; | |
(async (clients) => { | |
for await (const event of watcher) { | |
const currentTime = Date.now(); | |
if (currentTime - lastEventTime < debounceTime) { | |
continue; // Debounce the events | |
} | |
lastEventTime = currentTime; | |
if (event.kind === "modify") { | |
console.log("File modified:", event.paths); | |
for (const client of clients) { | |
client.send("reload"); | |
} | |
} | |
} | |
})(clients); | |
return function hmrMiddleware(request: Request): Response | null { | |
const { pathname } = new URL(request.url); | |
// WebSocket connection | |
if (pathname === socket_route) { | |
const { socket, response } = Deno.upgradeWebSocket(request); | |
socket.onopen = () => clients.add(socket); | |
socket.onclose = () => clients.delete(socket); | |
socket.onerror = () => clients.delete(socket); | |
return response; | |
} | |
// HMR client script | |
if (pathname === `${script_route}`) { | |
return new Response( | |
`const ws = new WebSocket("ws:/"+location.host+"${socket_route}"); | |
ws.onmessage = (event) => { | |
if (event.data === "reload") { | |
location.reload(); | |
} | |
};`, | |
{ | |
headers: { "content-type": "application/javascript" }, | |
} | |
); | |
} | |
// Not handled by HMR | |
return null; | |
}; | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<titleHt Reload Test</title> | |
<script src="hmr.js" defer></script> | |
</head> | |
<body> | |
<h1>Edit and save to see reload</h1> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createHotReloadMiddleware } from "./hot_reload.ts"; | |
const hrm = createHotReloadMiddleware("./index.html") | |
async function server(request: Request): Promise<Response> { | |
// HOT RELOAD MIDDLEWARE | |
const hrm_response = hrm(request); | |
if (hrm_response) return hrm_response; | |
// Serve the HTML file with the injected HMR client script | |
return new Response( | |
await Deno.readTextFile("./index.html"), | |
{ | |
headers: { | |
"content-type": "text/html; charset=utf-8", | |
}, | |
}, | |
); | |
} | |
Deno.serve(server); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment