Skip to content
easy-web-worker

Creating workers

Every source createWorker accepts, and the setup for Vite, webpack, Parcel and files you serve yourself.

GuideTypeScriptTry an example

Every source

createWorker, createEasyWebWorker and new EasyWebWorker(...) accept the same sources. Pick the one that fits how your project builds and serves its workers.

SourceBest forPool with maxWorkersreboot / force
URL or stringWorker files built by your bundlerYesYes
Existing WorkerBundlers that detect new Worker(new URL(...))One WorkerNo
Existing Worker[]Bringing your own poolThe array is the poolNo
FunctionWorkers with no file at allYesYes
Function arrayWorkers composed from reusable piecesYesYes

Vite

Import the worker with ?worker&url. Vite builds the file and gives you its URL, in development and in production.

main.ts
import { createWorker } from 'easy-web-worker/createWorker';
import workerUrl from '../getting-started/math.worker?worker&url';
import type { MathWorker } from '../getting-started/math.worker';

// `?worker&url` asks Vite to build the worker and hand back its URL
export const math = createWorker<MathWorker>(workerUrl, {
  workerOptions: { type: 'module' },
});

type: 'module' is required when the worker file uses import or export, which every defineWorker file does.

A native Worker you create

webpack 5, Parcel and Vite all detect the expression new Worker(new URL(...)) and bundle the file. Create the Worker that way and hand it over.

main.ts
import { createWorker } from 'easy-web-worker/createWorker';
import type { MathWorker } from '../getting-started/math.worker';

// webpack 5, Parcel and Vite detect this expression and bundle the file
const nativeWorker = new Worker(new URL('../getting-started/math.worker.ts', import.meta.url), {
  type: 'module',
});

export const math = createWorker<MathWorker>(nativeWorker);

The library cannot create that Worker again, so reboot and force are not available. Leave keepAlive at its default, so the Worker is not terminated when idle.

Your own pool

Pass an array of native Workers and the calls are distributed across them.

main.ts
import { createWorker } from 'easy-web-worker/createWorker';
import type { MathWorker } from '../getting-started/math.worker';

const createMathWorker = () =>
  new Worker(new URL('../getting-started/math.worker.ts', import.meta.url), { type: 'module' });

// the array is the pool: calls are distributed across these Workers
export const math = createWorker<MathWorker>([
  createMathWorker(),
  createMathWorker(),
  createMathWorker(),
]);

A file you serve yourself

main.ts
import { createWorker } from 'easy-web-worker/createWorker';
import type { MathWorker } from '../getting-started/math.worker';

// a worker script that is already built and public only needs its path
export const math = createWorker<MathWorker>('/workers/math.worker.js');

A function, with no file at all

main.ts
import { createWorker } from 'easy-web-worker/createWorker';

export const math = createWorker(({ onMessage }) => {
  const fibonacci = (n: number): number =>
    n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);

  return {
    fibonacci,

    countTo: onMessage(async (limit: number, message) => {
      for (let step = 1; step <= limit; step++) {
        message.reportProgress((step * 100) / limit);
      }

      return limit;
    }),
  };
});

// both sides are in the same file, so there is no type to import
export const result = math.fibonacci(40); // CancelablePromise<number>

The function is the worker. Runtime workers covers its rules.

Cleanup

Dispose the worker when the feature that owns it goes away:

ts
await unwrap(math).dispose();

dispose cancels the pending calls, revokes the generated worker URL when there is one, and terminates the Workers.

Documentation
↑↓ Navigate ↵ Open Esc Closeeasy-web-worker docs
Get started

Real Web Workers. Typed methods.
Cancelable promises.