hmr #1

Merged
SethTrowbridge merged 9 commits from hmr into master 2023-04-01 11:13:22 -04:00
6 changed files with 80 additions and 88 deletions
Showing only changes of commit 68b747c9ff - Show all commits

View File

View File

@ -1,7 +1,11 @@
{ {
"compilerOptions": {"lib": [
"deno.window", "DOM"
]},
"importMap": "deno.map.json",
"tasks": "tasks":
{ {
"install": "deno install -f -A --unstable --no-lock -n tsx server.tsx", "install": "deno install -f -A --unstable --no-lock -n eno server.tsx",
"run": "deno run -A --unstable --no-lock server.tsx" "run": "deno run -A --unstable --no-lock server.tsx"
} }
} }

5
deno.map.json Normal file
View File

@ -0,0 +1,5 @@
{
"imports": {
"react-original": "https://esm.sh/react@18.2.0"
}
}

65
lib/hmr.tsx Normal file
View File

@ -0,0 +1,65 @@
let reloads = 0;
const listeners = new Map();
new WebSocket("ws://"+document.location.host).addEventListener('message', (event) =>
{
let handlers = listeners.get(event.data)??[];
reloads++;
Promise.all(
handlers.map(handler=>
{
return import(event.data+"?reload="+reloads)
.then(updatedModule=>handler(updatedModule));
})
).then(HMR.update);
});
export const HMR = {
registered: new Map() as Map<string, ()=>void>,
states: new Map(),
statesOld: new Map(),
reloads: 0,
wireframe: false,
onChange(key:string, value:()=>void):void
{
this.registered.set(key, value);
},
update()
{
this.reloads++;
this.registered.forEach(handler=>handler());
this.registered.clear();
this.statesOld = this.states;
this.states = new Map();
this.echoState();
},
echoState()
{
let output = [];
for(const[key, val] of HMR.statesOld)
{
output[key] = val.state+"--"+val.reload;
}
console.log(output);
output = [];
for(const[key, val] of HMR.states)
{
output[key] = val.state+"--"+val.reload;
}
console.log(output);
}
};
export const MapAt =(inMap, inIndex)=>
{
let index = 0;
for(const kvp of inMap)
{
if(index == inIndex)
{
return kvp;
}
index++;
}
return false;
};

View File

@ -1,69 +1,13 @@
import * as ReactParts from "react-original"; import * as ReactParts from "react-original";
import { HMR, MapAt } from "./hmr.tsx";
const H = ReactParts.createElement; const H = ReactParts.createElement;
const HMR = {
registered: new Map(),
states: new Map(),
statesOld: new Map(),
reloads: 0,
wireframe: false
};
HMR.onChange =(key, value)=>
{
HMR.registered.set(key, value);
};
HMR.update =()=>
{
HMR.reloads++;
const keys = [];
for(const [key, value] of HMR.registered){ keys.push(key); }
HMR.registered.clear();
HMR.statesOld = HMR.states;
HMR.states = new Map();
keys.forEach(k=>k());
HMR.echoState();
};
HMR.echoState =()=>
{
let output = [];
for(const[key, val] of HMR.statesOld)
{
output[key] = val.state+"--"+val.reload;
}
console.log(output);
output = [];
for(const[key, val] of HMR.states)
{
output[key] = val.state+"--"+val.reload;
}
console.log(output);
};
HMR.wipe =()=>
{
HMR.statesOld = new Map();
};
const MapAt =(inMap, inIndex)=>
{
let index = 0;
for(const kvp of inMap)
{
if(index == inIndex)
{
return kvp;
}
index++;
}
return false;
}
window.HMR = HMR;
const ProxyElement = (props)=> const ProxyElement = (props)=>
{ {
const id = ReactParts.useId();
const [stateGet, stateSet] = ReactParts.useState(0); const [stateGet, stateSet] = ReactParts.useState(0);
ReactParts.useEffect(()=>HMR.onChange( ()=>stateSet(stateGet+1), "ProxyElement" )); ReactParts.useEffect(()=>HMR.onChange(id, ()=>stateSet(stateGet+1)));
const child = H(...props.__args); const child = H(...props.__args);

View File

@ -102,7 +102,7 @@ try
if(importReact) if(importReact)
{ {
ImportObject.imports["react-original"] = importReact; ImportObject.imports["react-original"] = importReact;
ImportObject.imports["react"] = "/hmr/react.tsx"; ImportObject.imports["react"] = "/lib/react.tsx";
ImportString = JSON.stringify(ImportObject); ImportString = JSON.stringify(ImportObject);
} }
else else
@ -128,33 +128,7 @@ const Index = `
<head> <head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<script> <script>
let reloads = 0;
const listeners = new Map();
const socket = new WebSocket("ws://"+document.location.host);
socket.addEventListener('message', (event) =>
{
let handlers = listeners.get(event.data)??[];
reloads++;
Promise.all(
handlers.map(handler=>
{
return import(event.data+"?reload="+reloads)
.then(updatedModule=>handler(updatedModule));
})
).then(()=>
{
handlers = listeners.get("reload-complete")??[];
handlers.forEach(handler=>handler());
});
});
window.HMR = (path, handler)=>
{
const members = listeners.get(path)??[];
members.push(handler);
listeners.set(path, members);
};
</script> </script>
</head> </head>
<body> <body>
@ -271,7 +245,7 @@ window.HMR("${url.pathname}", reloadHandler);`;
} }
catch(error) catch(error)
{ {
console.log(` ...404`); console.log(error);
return new Response(error, {status:404}); return new Response(error, {status:404});
} }
}); });