@vertexvis/web-workers
TypeScript icon, indicating that this package has built-in type declarations

0.1.0 • Public • Published

@vertexvis/web-workers

A package for defining, bundling, and loading web workers. The Threads package is used internally to provide worker creation and pooling behavior. Transferables are automatically passed when sending data to and from web workers.

Use this package in combination with @vertexvis/rollup-plugin-web-workers to bundle your workers with Rollup.

Install

// Yarn
yarn add @vertexvis/web-workers

// NPM
npm install @vertexvis/web-workers

Usage

Defining a Web Worker

Create a JS/TS file and wrap your worker implementation with defineWorker.

// ./worker.ts
import { defineWorker } from '@vertexvis/web-workers';

export type AddFn = (a: number, b: number) => Promise<number>;

const add: AddFn = async (a, b) => {
  return a + b;
}

defineWorker(add);

Loading and Spawning a Web Worker

Use the worker: path prefix to bundle a web worker. The Rollup plugin will transform the import and expose a loadWorker function to load the bundled worker module. The worker module exports functions for spawning workers and worker pools.

See @vertexvis/rollup-plugin-web-workers to bundle workers with Rollup.

// ./main.ts
import type { AddFn } from './worker';
import { loadWorker } from 'worker:./worker';

async function main(): Promise<void> {
  const { spawnWorker, makeController } = await loadWorker<AddFn>();

  const controller = makeController(); // optional controller to stop worker.
  const add = await spawnWorker(controller);
  const sum = await add(1, 2)
  console.log('sum', sum); // 3

  controller.terminate();
}

Worker Pools

Spawn worker pools to create a set of workers that pull work from a queue.

import type { AddFn } from './worker';
import { loadWorker } from 'worker:./worker';

async function main(): Promise<void> {
  const { spawnPool, makeController } = await loadWorker<AddFn>();

  const controller = makeController();
  const pool = await spawnPool({ controller });
  pool
    .queue((sum) => add(1, 2))
    .then((sum) => console.log('sum', sum)); // 3

  controller.terminate();
}

pool.queue() will return a promise that will resolve with the task's result. Use Promise.then() to handle the result vs using await when scheduling work within a loop. This is because await will block until the task completes.

You can customize the number of workers spawned and concurrency by passing in options to spawnPool.

interface CreatePoolOptions {
  // The number of concurrent tasks to run per worker. Defaults to 1.
  concurrency?: number;

  // Max number of tasks to queue. If count is reached, an error is thrown.
  maxQueuedJobs?: number;

  // The name of the pool for debugging.
  name?: string;

  // The number of workers to spawn. Defaults to number of CPU cores.
  size?: number;

  // A controller to terminate the pool.
  controller?: WorkerController;
}

Worker Termination

A WorkerController is used to terminate a worker. A worker module exports a makeController function to create a controller. You can pass a controller to multiple workers and pools to terminate them together.

import type { Worker1Fn } from './worker1';
import { loadWorker as loadWorker1 } from 'worker:./worker1';

import type { Worker2Fn } from './worker1';
import { loadWorker as loadWorker2 } from 'worker:./worker2';

async function main(): Promise<void> {
  const { spawnWorker, makeController } = await loadWorker1<Worker1Fn>();
  const { spawnPool } = await loadWorker2<Worker2Fn>();

  const controller = makeController();

  const worker = await spawnWorker(controller);
  const pool = await spawnPool({ controller });

  // Terminate the worker and pool.
  await controller.terminate();
}

Bundling Workers

See @vertexvis/rollup-plugin-web-workers for more details.

import resolve from '@rollup/plugin-node-resolve';
import typescript2 from 'rollup-plugin-typescript2';
import { terser } from 'rollup-plugin-terser';
import workers from '@vertexvis/rollup-plugin-web-workers';

export default {
  input: 'src/main.ts',
  output: {
    dir: './dist',
    format: 'esm',
  },
  plugins: [
    resolve(),
    workers({
      // Workers are bundled separately. Pass a list of plugins to use when
      // bundling the worker.
      plugins: [resolve(), typescript(), terser()]
    }),
    typescript2(),
  ]
}

Package Sidebar

Install

npm i @vertexvis/web-workers

Weekly Downloads

277

Version

0.1.0

License

MIT

Unpacked Size

41.4 kB

Total Files

14

Last publish

Collaborators

  • danschultz-vertex
  • jdm717
  • joshskinner-vertex
  • ci-vertex