Virtual JavaScript Modules

snippet

Given my penchant for minimal test cases and local applications, I sometimes run into situations where I can’t load external JavaScript files. Typically that’s because ESM is unsupported for file:// URIs or because I don’t wanna rely on additional assets for a Web Worker.

In such cases, we can resort to creating a Blob from the respective source code:

function code2uri(txt, type = "text/javascript") {
    let blob = new Blob([txt], { type });
    let uri = URL.createObjectURL(blob);
    return {
        uri,
        release: () => URL.revokeObjectURL(uri)
    };
}

(Remember that we should discard blobs after use. Nevertheless, they are preferable to data URIs in this particular context.)

I might then instantiate the aforementioned worker from within the same HTML document:

<script type="text/x-worker-module" id="my-worker">
self.addEventListener("message", ev => {
    self.postMessage(`pong ${ev.data}`);
});
</script>
<script type="module">
let worker = script2worker("#my-worker");
worker.addEventListener("message", ev => {
    console.log("received", ev.data);
});
worker.postMessage("ping");
</script>
function script2worker(selector) {
    let code = document.querySelector(selector).textContent;
    let { uri, release } = code2uri(code)
    let worker = new Worker(uri, { type: "module" });
    release();
    return worker;
}

For example, if you misguidedly employ WebSocket, you might wanna ridicule mock such connections for testing purposes: