Skip to content

Instantly share code, notes, and snippets.

@tbranyen
Last active Feb 9, 2022
Embed
What would you like to do?
Experimental Web Worker support in diffHTML (Minimal integration)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>diffHTML Web Worker Testing</title>
</head>
<body>
<main id="mount"></main>
<!-- Dependencies are installed via npm and aliased -->
<script type="importmap">
{
"imports": {
"diffhtml": "/node_modules/diffhtml/index.js",
"diffhtml-components": "/node_modules/diffhtml-components/index.js",
"diffhtml-middleware-worker": "/node_modules/diffhtml-middleware-worker/index.js"
}
}
</script>
<script type="module" src="index.js"></script>
</body>
</html>
import { use } from 'diffhtml';
import 'diffhtml-components';
import { mainTask, createWebWorker } from 'diffhtml-middleware-worker';
const mount = document.querySelector('main#mount');
// Create a worker to build your app in as if you were writing it in the
// main thread. The VDOM patches will be applied to the mount variable.
// You can use this worker for custom events, but be sure to always set
// a type.
// worker.postMessage({ type: 'my-custom-event', ...anyAdditionalData });
const worker = createWebWorker('/client-worker.js', { mount });
// Use the mainTask from the middleware worker to setup and handle the
// bi-directional communication with the threads.
use(mainTask({ worker }));
// importmaps don't work in web workers, so use full paths or use babel to convert globals to absolute paths
// https://github.com/WICG/import-maps/issues/2
import { innerHTML, createTree, use } from '/node_modules/diffhtml/index.js';
import '/node_modules/diffhtml-components/index.js';
import { workerTask } from '/node_modules/diffhtml-middleware-worker/index.js';
import App from '/app.js';
// Hook up the worker-side middleware to skip patching and only send deltas to the main
// thread.
use(workerTask());
// Create a Virtual DOM point to diff into.
const mount = createTree();
function render() {
// Render the App into the virtual mount, all changes are destined for the main thread
// mount element passed into the `createWebWorker` call.
innerHTML(mount, createTree(App));
}
// Initial render.
render();
import { html } from '/node_modules/diffhtml/index.js';
import { createState } from '/node_modules/diffhtml-components/index.js';
// Your sample app here rendering fully in a worker, with synchronous
// property and function access across threads. Not working perfectly
// yet, but is heavily inspired by partytown and may end up supporting
// this as a backend in the future.
export default function App() {
const [ windowStats, setWindowStats ] = createState(null);
function getWindowStats(ev) {
// Synchronous property calls are detected and communicated via a
// SharedArrayBuffer using Atomics.
setWindowStats({ width: window.innerWidth, height: window.innerHeight });
}
return html`
<div style=${{ display: 'inline-block' }}>
<form onsubmit=${getWindowStats}>
<button>Get Window Stats</button>
${windowStats && html`
Width: ${String(windowStats.width)}px
Height: ${String(windowStats.height)}px
`}
</form>
</div>
`;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment