threads.js
threads.js copied to clipboard
Typescript workers don't work with ESM
Thank you for this library!
Using Typescript Workers with "type": "module" in package.json produces an error:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/alexk/code/threads-ts-node-esm-issue/src/worker.ts
require() of ES modules is not supported.
See reproduction https://github.com/lynxtaa/threads-ts-node-esm-issue
Also here's the example how it works without threads.js using vanilla worker_threads: https://github.com/lynxtaa/threads-ts-node-esm-issue/tree/no-threads
same here
same problem with Vite bundler
I've omitted a threads.js dependency long time ago and wrote a simple helper for creating workers, which works in compiled code and in tests. Hope someone finds it helpful:
// runWorker.ts
import { cpus } from 'os'
import { Worker } from 'worker_threads'
import PQueue from 'p-queue'
const queue = new PQueue({ concurrency: cpus().length })
export function runWorker<T>(filenameWithoutExtension: URL, workerData?: unknown): Promise<T> {
return queue.add(async () => {
const worker =
process.env.NODE_ENV === 'test'
? new Worker(new URL(`${filenameWithoutExtension}.ts`), {
workerData,
execArgv: ['--loader', 'ts-node/esm/transpile-only'],
})
: new Worker(new URL(`${filenameWithoutExtension}.js`), { workerData })
const result = await new Promise<T>((resolve, reject) => {
worker.on('message', resolve)
worker.on('error', reject)
worker.on('exit', code => {
if (code !== 0) {
reject(new Error(`Worker stopped with exit code ${code}`))
}
})
})
return result
})
}
// worker.ts
import { workerData, parentPort } from 'worker_threads'
export type WorkerData = number[]
export type WorkerResult = number
const numbers = workerData as WorkerData
const result: WorkerResult = numbers.reduce((prev, curr) => prev + curr, 0)
parentPort!.postMessage(result)
// index.ts
import type { WorkerData, WorkerResult } from './worker.js'
import { runWorker } from './runWorker.js'
const workerData: WorkerData = [1, 2]
const result = await runWorker<WorkerResult>(
new URL('./worker', import.meta.url),
workerData,
)
If there's anyone else still having problems with this like I was, I made this to work for what I needed: https://github.com/jackcannon/threads-esm
If there's anyone else still having problems with this like I was, I made this to work for what I needed: https://github.com/jackcannon/threads-esm
I named mine thread-es, just to keep things confusing:
https://github.com/852Kerfunkle/threads-es
threads-es worked for me and has the worker pool feature that I rely on. This issue manifested differently for me than documented in the issue. I had an error from threads.js complaining about worker.addEventListener not being defined