A lightweight, zero-boilerplate reactive bridge for Angular and React that makes Web Workers (Dedicated and Shared) as simple as calling a regular method.
Web Workers have a verbose API (postMessage, onmessage, manual serialization). This library removes all of that. Just decorate a method with @RunInWorker — the rest is handled for you.
Angular (RxJS is already included in Angular projects):
npm i ngx-worker-bridgeReact (RxJS must be installed separately since React doesn't include it):
npm i ngx-worker-bridge rxjsReact only: Add these to your
tsconfig.app.jsonfor decorator support:{ "experimentalDecorators": true, "useDefineForClassFields": false }
| Thread | Your Code |
|---|---|
| Worker thread | A plain TypeScript class (Module) with your business logic |
| Main thread | A service/component that calls methods as if they're local |
The library handles the postMessage bridge between them invisibly.
import { startWorker } from 'ngx-worker-bridge';
import { DataModule } from './data.module';
startWorker([DataModule]);import { provideWorkerBridge } from 'ngx-worker-bridge/angular';
bootstrapApplication(AppComponent, {
providers: [
provideWorkerBridge({
instance: new Worker(new URL('./app.worker', import.meta.url), { type: 'module' }),
modules: [DataModule]
}),
// Optional: add a SharedWorker for multi-tab state
provideWorkerBridge({
name: 'shared',
instance: new SharedWorker(new URL('./app.worker', import.meta.url), { name: 'shared', type: 'module' }),
modules: [DataModule]
})
]
});import { Injectable } from '@angular/core';
import { RunInWorker, workerStore } from 'ngx-worker-bridge';
@Injectable({ providedIn: 'root' })
export class DataService {
// Reactive state — updates automatically when the worker calls setState()
count$ = workerStore<number>('counter', 'shared');
// This runs in the worker — UI thread is never blocked
@RunInWorker({ bridge: 'shared', namespace: 'data' })
processData(payload: any): Promise<any> { return null as any; }
}import { startWorker } from 'ngx-worker-bridge';
import { DataModule } from './data.module';
startWorker([DataModule]);import { bootstrapWorker } from 'ngx-worker-bridge';
import { DataModule } from './data.module';
bootstrapWorker({
worker: new SharedWorker(new URL('./app.worker', import.meta.url), { name: 'shared', type: 'module' }),
name: 'shared',
modules: [DataModule]
});import { useWorkerStore } from 'ngx-worker-bridge/react';
import { RunInWorker } from 'ngx-worker-bridge';
class DataService {
@RunInWorker({ bridge: 'shared', namespace: 'data' })
processData(payload: any): Promise<any> { return null as any; }
}
const service = new DataService();
function App() {
const count = useWorkerStore<number>('counter', 'shared');
return <button onClick={() => service.processData({})}>Count: {count}</button>;
}Your background logic lives in a plain TypeScript class. Use setState to push reactive updates to all connected tabs.
import { setState } from 'ngx-worker-bridge';
export class DataModule {
private count = 0;
// Namespace matches the class name: "DataModule" → "data"
increment() {
this.count++;
setState('counter', this.count); // broadcasts to all tabs
return this.count;
}
}- Multi-Tab State Sync — Use a
SharedWorkerto keep counters, notifications, or live data in sync across all open tabs without any server involvement. - CPU Offloading — Move heavy computation (large JSON processing, sorting, math) off the UI thread so your app stays interactive.
- Shared Connections — Maintain a single WebSocket or polling interval in a SharedWorker and broadcast to all connected tabs.
All console.log, console.warn, and console.error calls made inside your worker modules are automatically forwarded to the main browser console, prefixed with [Worker]. No setup required.
Demo Repository (Angular) [Demo Repository (React)] (https://github.com/yashwantyashu/worker-react-demo)