I'm using next js for my project and it uses Webpack 5 for bundling. according to this webworkers I can use the following syntax to load my web workers:
new Worker(new URL('./worker.js', import.meta.url));
but when I use the following:
new Worker(new URL('./worker.ts', import.meta.url));
it is loading as a media type file on the browser and not resolving imports and exports for typescript. any suggestions as to how I can resolve this issue on next js?
my tsconfig:
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"baseUrl": ".",
"paths": {
"@/*": ["./*"]
}
},
"exclude": ["node_modules", ".next", "out"],
"include": [
"next-env.d.ts",
"global.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.mdx",
"**/*.js",
"workers/**/*.ts"
]
}
CodePudding user response:
Not sure if this exactly answers your question, but here is an option I've used for a Typescript only web worker experience. I think it is pretty neat and enables a nice object based coding model, so perhaps it meets your requirements?
DEPENDENCIES
Run these commands:
npm install comlink --save
npm install worker-loader --save-dev
DEFINE THE WEB WORKER
Add this to a typings.d.ts
file:
declare module 'worker-loader!*' {
class WebpackWorker extends Worker {
constructor();
}
export default WebpackWorker;
}
CREATE THE WEB WORKER
import {expose} from 'comlink';
export class MyWebWorker {
private readonly name: string;
public constructor(name: string) {
this.name = name;
}
public async getData(input: string) : Promise<any> {
return {
message: `Hello from web worker, ${name}, ${input}`;
};
}
}
expose(MyWebWorker);
USE THE WEB WORKER
import {wrap, Remote} from 'comlink';
import Worker from 'worker-loader!./mywebworker';
import {MyWebWorker} from './mywebworker';
export class MyConsumingClass {
public async callWebWorker(): Promise<void> {
{
const RemoteChannel = wrap<typeof MyWebWorker>(new Worker());
const webWorker: Remote<MyWebWorker> = await new RemoteChannel("some name");
const data = await webWorker.getData("some input");
console.log(data.message);
}
}
WEBPACK BEHAVIOUR
The above typings.d.ts file and worker-loader plugin means webpack 5 will output a file called mywebworker.bundle.worker.js
, and note that this is lower cased. No reference to worker-loader is needed in the actual webpack file, though in my setup I used this output format, which may influence the name of the web worker bundle:
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].bundle.js'
}