Web Worker driven Classes and methods

He dropped 95% of a bundle size with a simple trick

self.addEventListener('message', event => {
switch(event.data.cmd) {
case 'initializeApp': ...
case 'firestore.col.add': ...
case 'firestore.col.onSnapshot': ...
  • the amount of cases grows with the complexity of the app
  • 3rd parts scripts might also use message events and interfere, break, or change, the result of your ad-hoc communication channel
  • there is no consistency between cases so that every operation might have less predictable results

workway: a general purpose Web Worker exporter

a @jonathan_klok walkway picture from @unsplash
// file /worker.js
// import anything else needed and initialize firestorm// expose remotely the following namespace
// either as object or Promise that will resolve one
utils: {
random: (size = 8) => String.fromCharCode(
...crypto.getRandomValues(new Uint8Array(size))
app: {
User: class User {
constructor() {
this.uid = firebase.auth().currentUser.uid;
getName() {
return firebase.database()
.ref('/users/' + this.uid)
.then(snapshot => ((
snapshot.val() && snapshot.val().username
) || 'Anonymous'));
// generic message listeners (addEventListener works too)
self.onmessage = event => console.log(event.data);
// file /bundle.js for the main thread
workway('/worker.js').then(async ({worker, namespace}) => {
const user = new namespace.app.User;
user.getName().then(name => {
worker.postMessage(`Thanks from ${name}!`);
const rand = await namespace.utils.random(16);

Offload as much as possible for a cost of 0.5K !

Key features

  • compatible with IE 10, without using Proxy or code evaluation, so actually compatible with iOS 8, Android 4.4, and pretty much every browser
  • worker events and messages do not interfere with each other. What’s destined to be handled by workway will, everything else won’t, leaving room to third parts Web Worker scripts to behave as expected.
  • The behavior is standardized per each remote invoke: every utility, callback, public static or instance method returns a promise that will resolve the returned value (that could be a promise too).
  • instances on the client are automatically reflected on the Worker, including runtime properties, if added, as long as these are serializable
  • arguments, serializable as well, are automatically handled too, so you just write regular JS and everything else is handled out of the box

As Summary




Web, Mobile, IoT, and all JS things since 00's. Formerly JS engineer at @nokia, @facebook, @twitter.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium


Using the filesystem for illustration purposes

Promises, promises….

So You Want to Use JavaScript in The Next Freelance Project — Prototype(2)

Test: docsify

Javascript ES6 — Exploring the New Built-In Methods

What Are React Hooks And How To Use Them?

How to use Axios with React

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Andrea Giammarchi

Andrea Giammarchi

Web, Mobile, IoT, and all JS things since 00's. Formerly JS engineer at @nokia, @facebook, @twitter.

More from Medium

Monorepo Setup with NPM and TypeScript

Choosing Package Managers: Yarn vs NPM

Migrating large codebase to TypeScript. Do it right from the beginning.

Capturing Your User’s Requests and Responses to Find Problems with your Application