Native cross-platform Web Workers. Works in published npm modules.
In Node, it's a web-compatible Worker implementation atop Node's worker_threads.
In the browser (and when bundled for the browser), it's simply an alias of Worker
.
Here's how this is different from worker_threads:
- makes Worker code compatible across browser, Node and Deno
- only supports Module Workers (
{type:'module'}
) - uses DOM-style events (
Event.data
,Event.type
,MessageEvent
, etc) - supports event handler properties (
worker.onmessage=..
) Worker()
accepts a URL, Blob URL or Data URL (via loaders)- emulates browser-style [WorkerGlobalScope] within the worker
- Worker thread can import
data:
,https:
,blob:
,file:
files just fine - Worker constructed also supports those too
new Worker('https://...')
In its simplest form:
import Worker from 'whatwg-worker'
const worker = new Worker('data:text/javascript,postMessage("hello")')
worker.onmessage = e => console.log(e.data) // "hello"
main.js | worker.js |
---|---|
import Worker from 'whatwg-worker'
const url = new URL('./worker.js', import.meta.url)
const worker = new Worker(url)
worker.addEventListener('message', e => {
console.log(e.data) // "hiya!"
})
worker.postMessage('hello') |
addEventListener('message', e => {
if (e.data === 'hello') {
postMessage('hiya!')
}
}) |
👉 Notice how new URL('./worker.js', import.meta.url)
is used above to load the worker relative to the current module instead of the application base URL. Without this, Worker URLs are relative to a document's URL, which in Node.js is interpreted to be process.cwd()
.
Support for this pattern in build tools and test frameworks is still limited. We are working on growing this.
Module Workers are supported in Node 12.8+ using this plugin, leveraging Node's native ES Modules support. In the browser, they can be used natively in Chrome 80+, or in all browsers via [worker-plugin] or [rollup-plugin-off-main-thread]. As with classic workers, there is no difference in usage between Node and the browser:
main.js | worker.js |
---|---|
import Worker from 'whatwg-worker'
const worker = new Worker(
new URL('./worker.js', import.meta.url),
{ type: 'module' }
)
worker.addEventListener('message', e => {
console.log(e.data) // "200 OK"
})
worker.postMessage('https://httpstat.us/200') |
addEventListener('message', async e => {
const url = e.data
const res = await fetch(url)
const text = await res.text()
postMessage(text)
}) |
Instantiating Worker using a Data URL is supported in both module and classic workers:
import Worker from 'whatwg-worker'
const worker = new Worker(`data:application/javascript,postMessage(42)`)
worker.addEventListener('message', e => {
console.log(e.data) // 42
})
Instantiating Worker using a Blob URL is supported
import Worker from 'whatwg-worker'
const code = 'import fs from "node:fs"'
const blob = new Blob([code], { type: 'text/javascript' })
const worker = new Worker(URL.createObjectURL(blob))
Worker gets added https- loader support via --loader
flag
import Worker from 'whatwg-worker'
const code = 'import xyz from "https://example.com/main.js"'
const blob = new Blob([code], { type: 'text/javascript' })
const worker = new Worker(URL.createObjectURL(blob))
import Worker from 'whatwg-worker'
const url = 'https://example.com/main.js'
const worker = new Worker(url)
Each time when creating a new Worker it will get assigned some new global variables including
- name
- Worker (to create worker within a worker)
- self
- postMessage
- and
globalThis
will be inheritEventTarget
(addEventListener, remove and dispatch)