Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ryan-williams/scalajs-worker-example
Proof of concept using web workers with scalajs (in particular, with scalajs-bundler)
https://github.com/ryan-williams/scalajs-worker-example
Last synced: about 2 months ago
JSON representation
Proof of concept using web workers with scalajs (in particular, with scalajs-bundler)
- Host: GitHub
- URL: https://github.com/ryan-williams/scalajs-worker-example
- Owner: ryan-williams
- Created: 2019-01-01T20:42:08.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2019-01-01T22:34:54.000Z (about 6 years ago)
- Last Synced: 2024-10-20T07:45:26.568Z (3 months ago)
- Language: Scala
- Size: 9.77 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# scalajs-worker-example
Proof of concept using web workers with scalajs (in particular, with scalajs-bundler), and discussion of some issues.## Setup
```
# clone
git clone [email protected]:ryan-williams/scalajs-worker-example.git
cd scalajs-worker-example# build
sbt worker/fastOptJS app/fastOptJS::webpack# serve
cd app # index.html and worker.js live here
python -m http.server
```The app is then running at http://localhost:8000/
## Serializing Scala objects over the Worker API
[The `Serde` object](app/src/main/scala/App.scala#L26-38) shows a way of sending Scala objects over the Worker API by serializing to bytes using [boopickle](https://github.com/suzaku-io/boopickle), and dealing with JS byte-arrays using [the example of suzaku](https://github.com/suzaku-io/suzaku/blob/c1de595f5dba3277e3847837b719cfda5c1d6e0e/platform/web/core-shared/src/main/scala/suzaku/platform/web/WebWorkerTransport.scala#L27-L34).
[The main `App`'s send and receive code](app/src/main/scala/App.scala#L16-22) is then straightforward:
```scala
worker.onmessage = (msg: dom.MessageEvent) ⇒ {
val foo = Serde[Foo](msg)
println(s"received foo: $foo")
}val foo = Foo(123, "abc")
worker.postMessage(Serde(foo))
```and [the `Worker`'s](app/worker/src/main/scala/Worker.scala#L19-23) is similar:
```scala
def onMessage(msg: dom.MessageEvent) = {
val foo = Serde[Foo](msg)
val doubled = foo.copy(n = 2*foo.n)
WorkerGlobal.postMessage(Serde(doubled))
}
```## Separate SBT module for worker app
[Existing scalajs web-worker references I found](https://gist.github.com/ochrons/e4df27f1e6a56912471db163ef8eff73) don't account for problems that scalajs-bundler introduces.
For example, the worker must run from a separate "`worker.js`" script without a `window` object, and that goes through a different top-level entry-point than your main app, but [scalajs-bundler removes top-level exports](https://scalacenter.github.io/scalajs-bundler/cookbook.html#several-entry-points).
I worked around this by making the worker "application" its own SBT module (`worker`, in [the `app/worker` directory](app/worker)).
Nesting it under the main `app` module's directory made it easier for relevant scripts to see each other; for example, [`app`'s main object](app/src/main/scala/App.scala#L8) needs to run [`worker.js`](app/worker.js), which in turn needs to import [the `worker`'s generated JS application](app/worker/src/main/scala/Worker.scala) (`app/worker/target/scala-2.12/worker-fastopt.js`).
### Using scalajs-bundler in the worker module?
In this example, `worker` doesn't use scalajs-bundler, but in principle it might be able to, if you wanted it to use some NPM dependencies. However, that might usually fail; I think the worker's global scope doesn't include e.g. `require`, which is needed to load such dependencies