DEV Community

Koutaro Chikuba
Koutaro Chikuba

Posted on

redux-workerized - Redux in WebWorker for React and Vue

I made experimental modules to use redux in worker.

mizchi/redux-workerized

  • TypeScript Friendly API
  • Redux.Store in Worker
  • React Hooks API and Vue Plugin

Shared Store example

Code

full code is here https://github.com/mizchi/redux-workerized/tree/master/examples/microfront

import "@babel/polyfill";
import { RootState, increment, Increment, INCREMENT } from "./reducer";

const worker = new Worker("./worker.ts");

// React

import React, { useCallback } from "react";
import ReactDOM from "react-dom";
import { createWorkerContext } from "redux-workerize/react";

const { WorkerContext, useSnapshot, useDispatch, ready } = createWorkerContext<
  RootState,
  { value: number }
>(worker, async (state: RootState) => {
  return state.counter;
});

function CounterApp() {
  const value = useSnapshot(state => state.value);
  const dispatch = useDispatch<Increment>();

  const onClick = useCallback(() => {
    dispatch(increment());
  }, []);

  return <button onClick={onClick}>{value}</button>;
}

ready.then(() => {
  ReactDOM.render(
    <WorkerContext>
      <CounterApp />
    </WorkerContext>,
    document.querySelector(".react-root")
  );
});

// Vue
import Vue from "vue";
import Vuex from "vuex";
import App from "./App.vue";
import { workerPlugin, proxy, SYNC } from "redux-workerize/vue";

Vue.use(Vuex);

type CounterSnapshot = {
  value: number;
};

export type State = {
  remote: CounterSnapshot;
};

const store = new Vuex.Store<State>({
  state: {
    remote: {
      value: 0
    }
  },
  mutations: {
    [SYNC](state, payload: CounterSnapshot) {
      state.remote = { ...state.remote, ...payload };
    },
    ...proxy([INCREMENT])
  },
  plugins: [
    workerPlugin(
      worker,
      (state: RootState): CounterSnapshot => {
        return state.counter;
      }
    )
  ]
});

new Vue({
  store,
  el: ".vue-root",
  render(h) {
    return h(App);
  }
});

NOTE: You need react@16.7.0-alpha.0 react-dom@16.7.0-alpha.0

Vuex subscribe remote Redux.Store snapshot

Worker Side

import * as Comlink from "comlinkjs";
import { createStore } from "redux";
import reducer from "./reducer";
import { createWorkerizedStore } from "redux-workerized/worker";

const store = createStore(reducer);
const storeAPI = createWorkerizedStore(store);

Comlink.expose({ ...storeAPI }, self);

What I want to do

  • For performance by off-the-main-thread
  • Store in Woker is training wheels to write universal javascript.

Top comments (0)