hmr #1
@ -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
5
deno.map.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"react-original": "https://esm.sh/react@18.2.0"
|
||||||
|
}
|
||||||
|
}
|
65
lib/hmr.tsx
Normal file
65
lib/hmr.tsx
Normal 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;
|
||||||
|
};
|
@ -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);
|
||||||
|
|
||||||
|
30
server.tsx
30
server.tsx
@ -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});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user