Home > OS >  How to get transpiled code to run in a Worker (without Webpack)?
How to get transpiled code to run in a Worker (without Webpack)?

Time:10-01

I'm using a TypeScript project based on SystemJS, following this example whose code is at https://github.com/tekmi/blogging-typescript-with-bundlers/blob/master/systemjs/app.ts

I'm able to implement a simple Worker in TypeScript, e.g. from this example,

// src/worker/simulator.ts
const scope = (self as unknown) as Worker

scope.addEventListener('message', event => {
    console.log(event.data)
    scope.postMessage('pong')
})

It runs fine in the SystemJS environment - I make sure that its code is transpiled outside of SystemJS, with a separate tsconfig.json, following the advice at this blog.

But as soon as I try something more complex in the Worker code, i.e., a class that imports/exports something, I hit snags with the code that runs. Depending on the transpiled format ("module" in the tsconfig), I get the following problems:

  • "module": "ESNext" -> SyntaxError: Cannot use import statement outside a module
  • "module": "CommonJS" -> ReferenceError: exports is not defined
  • etc with System, AMD, there are errors relating to those contexts.

The transpiled code is loaded properly when invoked (I see it fine in the log for lite-server).

I invoke the worker inside the event code for a button on a web page:

export function start(this: GlobalEventHandlers, ev: MouseEvent) {
    let worker = new Worker("../worker/simulator.js");
//...

My conclusion is there's some context missing in the transpiled worker code, but I can't figure out what it is. It's the first time I'm trying Workers in TypeScript.

Here's my tsconfig.json for the src/worker sub-project (this one is configured for CommonJS module transpilation):

{
  "extends": "../generic-tsconfig.json",
  "compilerOptions": {
    "strict": true,
    "target": "ES6",
    "module": "CommonJS",
    // store the webworker transpiled files separately
    "outDir": "../../dist",
    "lib": [
      "ES6",
      "WebWorker"
    ],
  },
  "include": [
    "../worker/*",
    "../shared/*"
  ]
}

What is needed to allow a (complex) Worker to run in this configuration?

I want avoid Webpack if possible, mostly because I'm trying to understand what's happening.

CodePudding user response:

As mentioned in the comments, if you want to be able to use module syntax like import and export in a web worker, you need to define the worker with the type: module option, like this:

new Worker("worker.js", { type: "module" });

This is discussed further in the question Web Workers - How To Import Modules

  • Related