react-worker-dom moves React's reconciliation into a Web Worker
Experiments to see the advantages of using Web Workers to Render React Virtual DOM
At a glance
- What is it?
- react-worker-dom is a custom React renderer that runs the virtual DOM diffing on a worker thread and sends only node updates to the page, so the main thread stays responsive during heavy renders. The mechanism is a two-file split of an existing application, and the caveats are equally concrete: React 0.14, webpack 1, and a roadmap where form elements and event semantics are still listed as work to do.
- Who is it for?
- Adopt react-worker-dom only as an experiment or reference implementation, or if you are maintaining an application pinned to React 0.14 whose render cost visibly blocks the main thread. Do not adopt it for a current React application, because the package depends on react ^0.14.3 and on webpack 1, and it was never released beyond 2.0.0 alphas.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 95 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The diffing runs off the main thread, the DOM writes stay on it
The premise is one sentence in the README: a React custom renderer using Web Workers, where all the virtual DOM reconciliations happen in a WebWorker thread and only node updates are sent over to the UI thread, which results in a much more responsive UI.
That split matters because of where the cost sits. A React render is not one operation but three: producing the element tree, diffing it against the previous tree, and applying the differences to real DOM nodes. The first two are pure computation and can happen anywhere; the third touches the document and can only happen on the page. A renderer that keeps all three on the main thread blocks input, scrolling and animation for the whole duration of the render. This renderer moves the expensive part into a worker and leaves the cheap part behind.
The interface between the two is a worker instance. The README states that an existing React application can leverage Web Workers using this library with minimal change, and the change is small in line count but structural in kind: the application is split into a file on the page and a file that becomes the worker.
The repository describes itself as experiments to see the advantages of using Web Workers to render React Virtual DOM, and the source layout, with a src/ directory and a test/ directory holding the demo applications, matches that framing. It is a research prototype with a working implementation, not a framework.
Adopting it means splitting one render call across two files
The typical application renders straight into the page:
// File: main.jsx
import React from 'react';
import reactDOM from 'react-dom';
reactDOM.render(<Component/>, document.getElementById('container'));With this renderer, the page file keeps the same shape but points at a worker instead of a component, and imports from react-worker-dom instead of react-dom:
// File: main.js - included using a script tag in index.html
import React from 'react';
import reactDOM from 'react-worker-dom'; // Instead of using react-dom
reactDOM.render(new Worker('worker.js'), document.getElementById('container'));The component itself moves into the worker file, which imports the worker-side entry point and renders there:
// File: worker.jsx - loaded in index.html using new Worker('worker.jsx') in the file script above;
import React from 'react';
import ReactWorkerDOM from 'react-worker-dom-worker';
ReactWorkerDOM.render(<Component/>);Two files and one new Worker call is the whole integration, and the README points at the test\dbmonster and test\todoapp directories for the worked examples. The cost of that simplicity shows up in the edges rather than the middle. A worker has no access to the document, so anything a component reaches for directly, from a DOM ref to a layout read, has to cross the thread boundary, and the roadmap admits that the event side of this is unfinished.
The demo pages and a frame meter are how you judge it
The project ships two demo applications and a measurement workflow, which is the right way to evaluate a rendering change. To run a local copy you clone the repo, install the dependencies and build the app:
npm install
npm run demoThe dev server then serves the pages at localhost:8080, with the dbmonster app at http://localhost:8080/test/dbmonster/ and the todo app at http://localhost:8080/test/todo. The README notes that you can tweak the params in the URL to change whether web workers are used and to increase the number of components, which is how the two modes are compared under identical conditions.
For measurement there are two approaches. The manual one is to load the dbmonster demo in Chrome and look at the frame meter in the devtools rendering settings. The automatic one runs a script:
npm run perf chrome workerThe two arguments are the two axes of the comparison. The first is the browser, chrome or android. The second is the rendering mode, worker or normal. The results are written to a _dbmonster.json file, one entry per row count, so the two configurations can be compared across sizes rather than at a single point.
That file is the honest way to evaluate this project for your own use, and it is also the way to see the limits of the approach, because the same harness will show you where moving work off the main thread stops paying.
The roadmap is the limitation list, and it is short
The README ends with a roadmap of things that need to be done next, and it is worth quoting the three items because they define the boundary of the implementation. Add support for form elements like input and select. Support event utilities that enable things like autofocus. Enable preventDefault semantics in events.
All three are ordinary React features, and all three are missing. The first means a form-heavy application cannot be migrated as it stands. The second means focus management and similar helpers are unavailable. The third is the subtlest and the most consequential: without preventDefault semantics, the event model in the worker is not equivalent to the browser's, so code that relies on cancelling the default behaviour of an event has to be rewritten rather than ported.
This is the reason to treat the project as an experiment rather than a dependency. A renderer that drops three well known behaviours of the platform it replaces is not interchangeable with react-dom, no matter how small the diff in your entry file looks. The library takes on the hard problem of keeping the UI responsive and leaves the compatibility work, which in practice is the part that consumes the most engineering time.
React 0.14 and webpack 1 date the code to 2016
The manifest is where the age shows. The package is named react-worker-dom at version 0.0.1, licensed BSD-3-Clause, authored by Parashuram, with a runtime dependency on react at ^0.14.3 and on invariant at ^2.2.0.
The development stack is from the same era. babel-core 6, babel-loader 6, babel-preset-es2015, babel-preset-react and babel-preset-stage-0, react-dom at ^0.14.3, webpack at ^1.12.8, webpack-dev-server at ^1.14.1, and browser-perf at ^1.4.3 for the frame rate collection. The build scripts match: build-demo and demo both drive webpack through test/webpack.config.js, perf runs node test/perf.js, and the test script is npm run build-demo, which means the test suite is the demo build itself.
For anyone evaluating this today, that dependency set is the binding constraint rather than the design. React 0.14 predates the modern reconciler and the hooks model, and webpack 1 predates the current loader and plugin ecosystem. Porting the idea to a current stack is a rewrite, not an upgrade, and the value of this repository is as a working reference for the approach rather than as a package to install.
Two alphas in 2016, and a push in the middle of 2026
The release history is thin. The most recent releases are v2.0.0-alpha.4, titled Basic touch event support, published on 2016-10-19, and v2.0.0-alpha.3, titled Implement className and classList properties, published on 2016-10-12. Two alphas, eight days apart, both naming a small capability rather than a milestone. The manifest version is 0.0.1, which is a different numbering line again and suggests the published artefacts and the source tree are not on a single version scheme.
The repository is not archived, and the last push was on 2026-07-22, so something moved in the tree long after the last tag. The home page is the GitHub pages demo at web-perf.github.io/react-worker-dom, and there is a LICENSE file alongside the source, with the BSD-3-Clause identifier also declared in the manifest.
Two observations follow for a reader deciding whether to invest time here. First, there is no versioned artefact to pin, so any experiment has to be run from source, which means the dependency set above is the real entry cost. Second, a project whose last named release describes touch event support in a 2016 alpha is a long way from covering the forms, focus management and event cancellation that a production application would need, whatever state the current tree is in.
Editorial conclusion
Adopt react-worker-dom only as an experiment or reference implementation, or if you are maintaining an application pinned to React 0.14 whose render cost visibly blocks the main thread. Do not adopt it for a current React application, because the package depends on react ^0.14.3 and on webpack 1, and it was never released beyond 2.0.0 alphas. Verify first that your own build can run the demo, since the repository ships a dbmonster page and a todo page under test/, and measure the frame rate in the same Chrome frame meter the project points to before and after moving the renderer.
Frequently asked questions
How does react-worker-dom keep the UI responsive?
All the virtual DOM reconciliations run in a Web Worker thread, and only node updates are sent over to the UI thread, so the main thread is not blocked by the diffing work.
How much change does react-worker-dom need in an existing React app?
The entry file changes to import from react-worker-dom instead of react-dom and to render a new Worker, and the component moves into a second file that imports react-worker-dom-worker. The README describes the examples in the test\dbmonster and test\todoapp directories.
How do I measure whether the worker renderer is faster?
Run npm run perf chrome worker, which is the browser and rendering mode combination, with the results written to a _dbmonster.json file per row count. The README also points to the Chrome frame meter for a manual check on the dbmonster demo page.
What does react-worker-dom not support yet?
The roadmap lists support for form elements such as input and select, event utilities such as autofocus, and preventDefault semantics in events. The most recent named release, v2.0.0-alpha.4 from 2016-10-19, covered basic touch event support.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/web-perf-react-worker-dom)Was this useful?