Ts-node: How to use with WebWorkers

Created on 23 Oct 2018  路  10Comments  路  Source: TypeStrong/ts-node

Hello,

Is there any way to use ts-node with WebWorkers __but__ without using webpack?

When I do:

const worker = new Worker('path-to/workerFile.ts', { // ... });

I get:

TypeError [ERR_WORKER_UNSUPPORTED_EXTENSION]: The worker script extension must be ".js" or ".mjs". Received ".ts"
    at new Worker (internal/worker.js:272:15)
    // ....

Any ideas?

Tomer

enhancement external

Most helpful comment

The problem is the worker has a separate require() cache and require.extensions. ts-node is not installed in the worker, and node does not expose an API that would let us auto-install ourselves into all workers. Also, I'm not sure that would be a good idea. Third-party libraries using worker_threads shouldn't pay a performance hit just so we can install duplicate copies of ourselves into every worker.

Fortunately, I think the solution is simple: when you want to spawn a worker with ts-node, use our ts-node/register endpoint to install us.

new Worker(`
  require('ts-node/register');
  require(require('worker_threads').workerData.runThisFileInTheWorker);
`, {
  eval: true,
  workerData: {
    runThisFileInTheWorker: '/path/to/worker-script.ts'
  }
});

All 10 comments

This is a node.js error, it doesn鈥檛 look like it based on the error message.

@blakeembrey thanks for your quick reply :)
Not sure I fully understand what you mean by "it doesn鈥檛 look like it based on the error message".
I know it's a node.js error, but still, I think it's a ts-node related topic, cause correct me if I'm wrong but after stating a ts-node app, it compiles the ts and executing the js.
But with WebWorkers, it gets a bit more complicated cause web worker require a file path, so if I want to use a .ts as the worker input that's the exception node throws.
So, I can write all the worker code in js or compile ts file on my own.
Maybe it will be a good idea to somehow detect the worker's path and switch it with the compiled path?

@kutomer It might be possible as a plugin to ts-node, not sure it will belong here. It's a tricky task because you're suggesting changing compiled code which I haven't wanted to do so far. I do think, if someone were to do it, it should be implemented as a plugin like tsconfig-paths or a plugin to the compiler AST. I won't have the time to implement the change, but happy to link and improve the TypeScript plugin process in ts-node to support the use-case.

@blakeembrey thanks again,
Do you think I can somehow get the file's compiled path? something like require.resolve()?

There鈥檚 a couple of issues with that:

  1. This module doesn鈥檛 produce any real files (it鈥檚 all in memory)
  2. It wouldn鈥檛 have compiled any file it hasn鈥檛 seen via an import yet, so it won鈥檛 know about the web worker file

What we could do is expose the internal compiler/config at runtime and you could generate/write the file yourself. Perhaps with a little TsWorker wrapper? Would this be a good starting point?

that's definitely sound like a good starting point but unfortunately, I don't have the time right now to do that so I guess I'll just migrate to webpack :(
anyway, I really appreciate your help! thanks again

I have the same issue, is there any good solution for this?

The problem is the worker has a separate require() cache and require.extensions. ts-node is not installed in the worker, and node does not expose an API that would let us auto-install ourselves into all workers. Also, I'm not sure that would be a good idea. Third-party libraries using worker_threads shouldn't pay a performance hit just so we can install duplicate copies of ourselves into every worker.

Fortunately, I think the solution is simple: when you want to spawn a worker with ts-node, use our ts-node/register endpoint to install us.

new Worker(`
  require('ts-node/register');
  require(require('worker_threads').workerData.runThisFileInTheWorker);
`, {
  eval: true,
  workerData: {
    runThisFileInTheWorker: '/path/to/worker-script.ts'
  }
});

To add to the above, if you want non-relative paths to be resolved according to your tsconfig baseUrl and paths, you should install the tsconfig-paths module, and spawn the worker like so:

new Worker(`
  require('tsconfig-paths/register');
  require('ts-node/register');
  require(require('worker_threads').workerData.runThisFileInTheWorker);
`, {
  eval: true,
  workerData: {
    runThisFileInTheWorker: '/path/to/worker-script.ts'
  }
});

@cspotcode You saved my whole day!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mattdell picture mattdell  路  4Comments

huan picture huan  路  3Comments

OliverJAsh picture OliverJAsh  路  3Comments

Borewit picture Borewit  路  3Comments

remojansen picture remojansen  路  4Comments