Implement elm-hot for HMR
I'm not sure if this is even possible but it would be sick to not need to rely on browser reload to reload the entire page every time there is a change. In fact if we could tell Django to not even look inside the app static files after initial load. Perhaps there is some sort of middleware hook we can give the django file watcher.
We could set up an endpoint (much like browser reload) and send server events to the client to fetch the new assets as string the eval it in the client.
Resources: elm-hot
Pretty pumped to start work on this.
Here's a very shitty implementation idea:
import defo from "@icelab/defo";
const views = {
djelmDropzone: async (el: HTMLElement, data: any) => {
let currentApp;
// Load and initialize the Elm program
const loadElm = async () => {
//@ts-ignore
const { Elm } = await import("../../../src/DropZone.elm");
currentApp = Elm.DropZone.init({
node: el,
flags: data,
});
};
await loadElm();
return {
update: (newData, oldData) => {
// Update flags if the data changes
if (JSON.stringify(newData) !== JSON.stringify(oldData)) {
data = newData;
currentApp.ports?.updateFlags?.send(newData); // Optional: if you add a port
}
},
destroy: () => {
currentApp = null; // Cleanup
},
// New method for hot reloading
hotReload: async () => {
if (currentApp) {
// Destroy the old instance
currentApp = null;
// Reload the updated module
await loadElm();
}
},
};
},
};
const instance = defo({ views, prefix: "elmprogramsdropzone" });
// WebSocket listener for hot reloads (example)
const ws = new WebSocket("ws://localhost:3000");
ws.onmessage = (event) => {
const { program } = JSON.parse(event.data);
if (program === "DropZone") {
instance.views.djelmDropzone.hotReload();
}
};
Because djelm controls the generation of this entrypoint file it's very easy to add the websocket code.
When djelm is run with watch --hot it could spin up the websocket server at the same time and also generate the ws code in the entrypoint.
The really nice thing is djelm has access to the running elm programs init model, so its easy to instantiate it when programs change, no refresh required. However, the trick will be to get access to the internal model so that it can persist between refreshes.
This current implementation solves the refresh issue, but not the preserved model issue. It's a start though.