question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow importing classic Web Workers (not Module Workers)

See original GitHub issue

Vite provides an easy way to import Web Workers, as described in the docs:

import MyWorker from './worker?worker'

const worker = new MyWorker()

This gets compiled into module worker initialization:

new Worker("/assets/index.ef0da162.js",{type:"module"})

Module workers are different from classic workers, and their support is very limited (Chrome 80+, no Safari, no Firefox), which means that shipping this code is not an option.

What’s more, module workers are not drop-in replacement for classic workers, as they don’t support importScripts, which existing implementations rely on to import scripts from CDN:

importScripts('https://unpkg.com/comlink/dist/umd/comlink.js')
importScripts('https://www.gstatic.com/firebasejs/8.3.0/firebase-app.js')

I would like to request support for classic workers by allowing to pass worker options to the worker constructor:

import MyWorker from './worker?worker'

const worker = new MyWorker() // classic worker
const worker = new MyWorker({type: 'classic'}) // classic worker
const worker = new MyWorker({type: 'module'}) // module worker

Worker constructor options should allow all of worker options, which look like this:

interface WorkerOptions {
    credentials?: RequestCredentials;
    name?: string;
    type?: WorkerType;
}

The alternative right now is to bundle worker code in a separate process and use the usual worker initialization:

const classicWorker = new Worker('./worker-built-separately.js')

This complicates the process and doesn’t provide out of the box file name hashing. To add file name hashing would require further complications.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:27
  • Comments:11 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
userquincommented, Mar 18, 2021

Is there a way to build with vite the worker with all its dependencies inside (no code splitting)?

I’m testing web workers and I can use { type: 'module'} (via esno + tsup with esm or cjs formats) on Safari and Firefox, the only restriction is to not have imports inside the worker (just plan javascript, es2017 or whatever we want) and building the worker with all dependencies inside requires to configure its dependencies as dev dependencies (in my case Comlink and dexiejs).

For example, I get my logic and put on new project, then I configure scripts directory with: scripts/build.ts

import { execSync } from 'child_process'
// @ts-ignore
import { commands } from './commands'

for (const command of commands)
  execSync(command, { stdio: 'inherit' })

where commands.ts is:

export const commands = [
  'npx tsup src/parse-file-worker.ts --no-splitting --sourcemap --format cjs -d dist/build',
  'npx tsup src/parse-file-worker-module.ts  --sourcemap --target esnext --format esm -d dist/build',
]

then I add a new script to my package.json:

"scripts": {
  "build": "esno scripts/build.ts"
},

My worker looks like this parse-file-worker-module.ts:

import { expose } from 'comlink/dist/esm/comlink' // <== for esm format, for cjs format just use `import { expose } from 'comlink'`
import type { ParseFileFn } from '~/types'
import { parseFileAsync } from '~/parse-file-async' // <== 128 module dependencies

const parseFile: ParseFileFn = async(
  file,
  onFileInfo,
  onControlParsed,
  onProgress,
  onProcessError,
  onFinished,
  canceled,
) => {
  await parseFileAsync(
    file,
    onFileInfo,
    onControlParsed,
    onProgress,
    onProcessError,
    onFinished,
    canceled,
  )
}
// SSR compatibility
typeof self !== 'undefined' && expose(parseFile)

and finally I can use it (just setting the output on public directory) and referencing it via:

const worker = new Worker('/parse-file-worker-module.mjs', { type: 'module' })
const parseFile = wrap<ParseFileFn>(worker)

1reaction
poyohocommented, Mar 26, 2022

yes, I add the options to show the classic word. hhh

Read more comments on GitHub >

github_iconTop Results From Across the Web

Web Workers - How To Import Modules - Stack Overflow
As I am exporting functions in my module 'abc.js', I am not sure how to use them using the old (& apparently on...
Read more >
Threading the web with module workers - web.dev
To ensure great performance, the old importScripts() method is not available within module workers. Switching workers to use JavaScript modules ...
Read more >
Using Pyodide in a service worker — Version 0.22.0.dev0
This document describes how to use Pyodide to execute Python scripts in a service worker. Compared to typical web workers, service workers are...
Read more >
Worker() - Web APIs - MDN Web Docs
A string specifying the type of worker to create. The value can be classic or module . If not specified, the default used...
Read more >
worker-loader - webpack - JS.ORG
Allow to set web worker constructor name and options. webpack.config.js module.exports = { module: { rules: ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found