Entire Redux in Web Worker
Inspired by React + Redux + Comlink = Off-main-thread.
This is still an experimental project. Please give us a feedback to make it stable.
Some key points are:
- It only sends "diffs" from the worker thread to the main thread.
- All Objects in a state tree keep the ref equality.
- It can run middleware in the worker thread. (only non-DOM middleware #2)
- No async functions are involved.
- No proxies are involved.
npm install redux-in-worker
store.worker.js:
import { createStore } from 'redux';
import { exposeStore } from 'redux-in-worker';
const initialState = { count: 0 };
const reducer = (state = initialState, action) => {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'decrement':
return { ...state, count: state.count - 1 };
default:
return state;
}
};
const store = createStore(reducer);
exposeStore(store);
app.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider, useDispatch, useSelector } from 'react-redux';
import { wrapStore } from 'redux-in-worker';
const initialState = { count: 0 };
const worker = new Worker(new URL('./store.worker', import.meta.url));
const store = wrapStore(worker, initialState);
const Counter = () => {
const dispatch = useDispatch();
const count = useSelector(state => state.count);
return (
<div>
count: {count}
<button type="button" onClick={() => dispatch({ type: 'increment' })}>+1</button>
<button type="button" onClick={() => dispatch({ type: 'decrement' })}>-1</button>
</div>
);
};
const App = () => (
<Provider store={store}>
<Counter />
<Counter />
</Provider>
);
ReactDOM.render(<App />, document.getElementById('app'));
The examples folder contains working examples. You can run one of them with
PORT=8080 npm run examples:01_minimal
and open http://localhost:8080 in your web browser.