In a LiveView project I'm working on, I had to add a web worker. I was a bit unsure of how to do this, and was worried I'd have to do some esbuild
config manipulation, but it turned out to be quite simple.
For readers reading in the far future, these are the relevant versions with which I'm working in this post:
{:phoenix_live_view, "~> 0.20.1"},
{:esbuild, "~> 0.7", runtime: Mix.env() == :dev},
Add the worker file
Here's a simple worker.js
// assets/js/worker.js
self.onmessage = function(e) {
// Worker logic here
const result = e.data * 2; // Example: double the input
self.postMessage(result);
};
Pass the worker file to esbuild
In config.exs
, update the :esbuild
config to
config :esbuild,
version: "0.17.11",
default: [
args:
~w(js/app.ts js/worker.js --bundle --target=es2020 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
]
Use it from app.js
or a hook
Depending on what your use case, you might want to load the worker immediately, or load it in the mounted
step of a JS hook. For example, if you want to load the worker after the Liveview is loaded, you can do:
window.addEventListener("phx:page-loading-stop", async _info => {
topbar.hide()
// this is the path where the compiled JS file will be placed
const worker = new Worker('/assets/worker.js');
worker.onmessage = function (e) {
console.log('Received from worker:', e.data);
};
worker.postMessage(10);
})