My reference for this issue is Yew's multi_thread
example which requires two WASM binaries. One for the actual application and one for the Web Worker.
Up until now building applications with web workers has been a real pain but with trunk we have the chance to turn this around.
Requirements
The following is an objective list of problems that need to be solved to support Web Workers.
1. Multiple binary targets
Trunk should handle crates with multiple binary targets gracefully.
Currently, invoking trunk serve
on the aforementioned example results in this error:
could not read file `$TARGET/wasm32-unknown-unknown/debug/multi_thread.wasm`
📡 server running at http://127.0.0.1:8080/
❌ build finished with errors
The multi_thread.wasm
could not be found because there are two WASM binaries called app.wasm
and worker.wasm
.
While it isn't strictly related to this issue, I think this behaviour could be improved.
2. Letting the app know where to find the Web Worker
Because of how Web Worker are created[link] we need to know the URL of the worker's Javascript file while compiling the app.
3. Building Web Workers with the required Javascript code to start them
Trunk currently runs wasm-bindgen
with --target=web
. The generated js code exports an initializer function which needs to be called to start the program. This doesn't work for Web Workers as they need to be self-executing.
Proposal
This is just one potential way of solving the issues mentioned above to get the discussion started.
Since Trunk already has a config file, I think it makes perfect sense to use it for this.
We add a new section to [build]
, let's call it "targets", which is used to configure binary targets.
To take care of 3., we can simply build the WASM with --target=no-modules
.
Since we still want to have normal binaries, let's give each target a type
key with the following two values:
- "script" - The default value, this represents the current strategy.
Builds the binary with
--target=web
and includes it in index.html
.
- "worker" - The new strategy which builds the value with
--target=no-modules
.
The output is moved to dist/
but not added to index.html
For 2. we need to allow targets to side-step hashing so we can assign static URLs to them.
In the future this could use a similar approach to #9 so we don't miss out on caching, but for now we can just add a key "output" to the target which manually sets the output path.
This is what it would look like when applied to the multi_thread
example:
[build.targets.app]
type = "script"
[build.targets.worker]
type = "worker"
output = "worker.js"
Trunk should reject projects with multiple binaries (without appropriate configuration) outright and point the user to documentation on the subject.
It might be tempting to guess which binary is which based on certain keywords (like "app" and "worker") but this probably does more harm than good in the long run.
This satisfies 1..
This is quite a high priority feature for Yew and I would love to help out with this.
cli assets discussion needs design