Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# web-workers

This is a mono-repo that contains utilities to create and build web workers. It
uses the [Threads](https://threads.js.org/) internally to handle the management
uses [threadsx](https://github.com/jmaleonard/threadsx) internally to handle the management
of web workers and provide pooling behavior.

## Packages
Expand All @@ -11,6 +11,25 @@ of web workers and provide pooling behavior.
| [@vertexvis/web-workers] | ![npm](https://img.shields.io/npm/v/@vertexvis/web-workers) | Package for defining and loading web workers. |
| [@vertexvis/rollup-plugin-web-workers] | ![npm](https://img.shields.io/npm/v/@vertexvis/rollup-plugin-web-workers) | Package for building web workers with Rollup. |

## Migrating from `threads.js`

This major release replaces the unmaintained `threads` peer dependency with
`threadsx` v2. Install `threadsx` alongside these packages and remove `threads`:

```sh
yarn remove threads
yarn add threadsx@^2

# or
npm uninstall threads
npm install threadsx@^2
```

Update any direct imports from `threads` to `threadsx`, including worker entry
imports such as `threads/worker` to `threadsx/worker`. The APIs used by these
packages, including `defineWorker`, `loadWorker`, and worker pools, are
otherwise unchanged.

## Simple Usage

See [@vertexvis/web-workers](./packages/web-workers/README.md) for more advanced
Expand Down
16 changes: 14 additions & 2 deletions packages/rollup-plugin-web-workers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@
"main": "./dist/bundle.cjs",
"module": "./dist/bundle.esm.js",
"typings": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/bundle.esm.js",
"require": "./dist/bundle.cjs",
"default": "./dist/bundle.esm.js"
}
},
"engines": {
"node": ">=20"
},
"publishConfig": {
"registry": "https://registry.npmjs.org",
"access": "public"
Expand All @@ -48,7 +59,7 @@
},
"peerDependencies": {
"rollup": ">=2",
"threads": "^1"
"threadsx": "^2"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^29.0.3",
Expand All @@ -60,6 +71,7 @@
"http-server": "^13.1.0",
"jest-puppeteer": "^5.0.4",
"puppeteer": "^10.4.0",
"rollup-plugin-copy": "^3.5.0"
"rollup-plugin-copy": "^3.5.0",
"threadsx": "^2.1.0"
}
}
10 changes: 5 additions & 5 deletions packages/rollup-plugin-web-workers/rollup.testing.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import copy from 'rollup-plugin-copy';

import workers from './dist/bundle.esm.js';

function threadsBrowserEntry() {
function threadsxBrowserEntry() {
return {
name: 'threads-browser-entry',
name: 'threadsx-browser-entry',
resolveId(source) {
if (source === 'threads') {
return path.resolve('../../node_modules/threads/dist-esm/index.js');
if (source === 'threadsx') {
return path.resolve('../../node_modules/threadsx/dist-esm/index.js');
}

return null;
Expand All @@ -21,7 +21,7 @@ function threadsBrowserEntry() {
}

const browserPlugins = [
threadsBrowserEntry(),
threadsxBrowserEntry(),
commonjs(),
nodeResolve({ browser: true }),
];
Expand Down
14 changes: 9 additions & 5 deletions packages/rollup-plugin-web-workers/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import * as path from 'path';
import { Plugin, rollup } from 'rollup';

interface ThreadsPluginOptions {
interface WorkerPluginOptions {
plugins?: Plugin[];
}

const workerPrefix = 'worker:';
const workerModulePrefix = 'worker-module:';

export default function ({ plugins = [] }: ThreadsPluginOptions): Plugin {
export default function ({ plugins = [] }: WorkerPluginOptions): Plugin {
return {
name: 'web-workers-plugin',

Expand Down Expand Up @@ -86,7 +86,7 @@ export async function loadWorker() {

function getWorkerModule(workerName: string, workerCode: string): string {
return `
import { BlobWorker, spawn, Pool, Transfer } from 'threads';
import { BlobWorker, spawn, Pool, Transfer } from 'threadsx';
import { makeTransferable, TerminateController } from '@vertexvis/web-workers';

const workerName = "${workerName}.js";
Expand All @@ -110,8 +110,12 @@ export async function spawnWorker(terminate) {
};
}

export function spawnPool(options) {
return Pool(() => spawnWorker(options.terminate), options);
export function spawnPool({ terminate, ...options } = {}) {
const pool = Pool(() => spawnWorker(), options);
if (terminate != null) {
terminate.addPool(pool);
}
return pool;
}
`;
}
Expand Down
12 changes: 11 additions & 1 deletion packages/rollup-plugin-web-workers/test-src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,22 @@ async function testPool() {

const { spawnPool, makeController } = await loadWorker2();
const controller = makeController();
const pool = await spawnPool({ controller });
const pool = await spawnPool({ terminate: controller });
const result = await pool.queue((sum) => sum({ nums }));
await controller.terminate();

assert(9, result[0], 'testThread returns sum');
}

async function testPoolWithoutOptions() {
const { spawnPool } = await loadWorker2();
const pool = await spawnPool();
const result = await pool.queue((sum) => sum({ nums: Uint8Array.of(2, 3) }));
await pool.terminate();

assert(5, result[0], 'testPoolWithoutOptions returns sum');
}

async function assert(expected, actual, msg) {
if (expected !== actual) {
recordFailure(`${msg} [expected=${expected}, actual=${actual}]`);
Expand All @@ -60,6 +69,7 @@ export async function runSuite() {
await testThread();
await testTransferables();
await testPool();
await testPoolWithoutOptions();

window.__test__.done = true;
}
19 changes: 13 additions & 6 deletions packages/web-workers/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# @vertexvis/web-workers

A package for defining, bundling, and loading web workers. The [Threads] package
A package for defining, bundling, and loading web workers. The [threadsx] package
is used internally to provide worker creation and pooling behavior.
[Transferables] are automatically passed when sending data to and from web
workers.
Expand All @@ -18,6 +18,13 @@ yarn add @vertexvis/web-workers
npm install @vertexvis/web-workers
```

### Migrating from `threads.js`

This major release replaces the `threads` peer dependency with `threadsx` v2.
Remove `threads` and install `threadsx@^2`, then update direct imports such as
`threads/worker` to `threadsx/worker`. The APIs provided by this package are
otherwise unchanged.

## Usage

### Defining a Web Worker
Expand Down Expand Up @@ -75,7 +82,7 @@ async function main(): Promise<void> {
const { spawnPool, makeController } = await loadWorker<AddFn>();

const controller = makeController();
const pool = await spawnPool({ controller });
const pool = await spawnPool({ terminate: controller });
pool
.queue((sum) => add(1, 2))
.then((sum) => console.log('sum', sum)); // 3
Expand Down Expand Up @@ -106,13 +113,13 @@ interface CreatePoolOptions {
size?: number;

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

### Worker Termination

A `WorkerController` is used to terminate a worker. A worker module exports a
A `TerminateController` 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.

Expand All @@ -131,7 +138,7 @@ async function main(): Promise<void> {
const controller = makeController();

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

// Terminate the worker and pool.
await controller.terminate();
Expand Down Expand Up @@ -166,6 +173,6 @@ export default {
}
```

[Threads]: https://threads.js.org/
[threadsx]: https://github.com/jmaleonard/threadsx
[Transferables]: https://developer.mozilla.org/en-US/docs/Web/API/Transferable
[@vertexvis/rollup-plugin-web-workers]: https://www.npmjs.com/package/@vertexvis/rollup-plugin-web-workers
2 changes: 1 addition & 1 deletion packages/web-workers/extensions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Provides static analysis for import paths that are prefixed with `worker:`.
*/
declare module 'worker:*' {
import type { Worker } from 'threads';
import type { Worker } from 'threadsx';

interface SpawnPoolOptions {
/**
Expand Down
17 changes: 14 additions & 3 deletions packages/web-workers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.2.0",
"type": "module",
"license": "MIT",
"description": "A wrapper around ThreadsJS to make bundling and using web workers even simpler.",
"description": "A wrapper around threadsx to make bundling and using web workers even simpler.",
"keywords": [
"thread",
"worker",
Expand All @@ -22,6 +22,17 @@
"main": "./dist/bundle.cjs",
"module": "./dist/bundle.esm.js",
"typings": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/bundle.esm.js",
"require": "./dist/bundle.cjs",
"default": "./dist/bundle.esm.js"
}
},
"engines": {
"node": ">=20"
},
"publishConfig": {
"registry": "https://registry.npmjs.org",
"access": "public"
Expand All @@ -44,11 +55,11 @@
"devDependencies": {
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"threads": "^1.7.0",
"threadsx": "^2.1.0",
"tslib": "^2.8.1"
},
"peerDependencies": {
"threads": "^1",
"threadsx": "^2",
"tslib": "^2"
}
}
4 changes: 2 additions & 2 deletions packages/web-workers/src/__tests__/terminate.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
jest.mock('threads');
jest.mock('threadsx');

import { Thread } from 'threads';
import { Thread } from 'threadsx';

import { TerminateController } from '../terminate';

Expand Down
2 changes: 1 addition & 1 deletion packages/web-workers/src/__tests__/transferable.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '../__mocks__/browser';

import { TransferDescriptor } from 'threads';
import { TransferDescriptor } from 'threadsx';

import { makeTransferable } from '../transferable';

Expand Down
2 changes: 1 addition & 1 deletion packages/web-workers/src/terminate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Thread } from 'threads';
import { Thread } from 'threadsx';

interface WorkerPoolLike {
terminate(force?: boolean): Promise<void>;
Expand Down
6 changes: 3 additions & 3 deletions packages/web-workers/src/transferable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Transfer } from 'threads';
import { Transfer } from 'threadsx';

import globalThis from './globalThis';

Expand Down Expand Up @@ -47,11 +47,11 @@ function isTypedArray(obj: unknown): obj is TypedArray {
}

/**
* A function that will recursively inspect an object and return a Threads
* A function that will recursively inspect an object and return a threadsx
* `Transfer` that contains all the `Transferable`s in the given object.
*
* @param obj The object to make transferable.
* @returns A `Transfer` from Threads.
* @returns A `Transfer` from threadsx.
*/
export function makeTransferable<T>(obj: T): ReturnType<typeof Transfer> | T {
if (isTransferable(obj)) {
Expand Down
4 changes: 2 additions & 2 deletions packages/web-workers/src/worker.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expose as threadsExpose } from 'threads';
import { expose as threadsExpose } from 'threadsx';

import { makeTransferable } from './transferable';

Expand All @@ -12,7 +12,7 @@ interface DefineWorkerOptions {

/**
* Defines a web worker implementation. This function wraps the `expose` method
* of Threads and handles automatic conversion of Transferable types.
* of threadsx and handles automatic conversion of Transferable types.
*
* @param impl The worker implementation.
* @see https://developer.mozilla.org/en-US/docs/Web/API/Transferable
Expand Down
Loading
Loading