We can work it out

From Web Workers to Service Workers

@nolanlawson

hype train

@nolanlawson

photo of Nolan Lawson

http://edge.ms

edge.ms website
Edge Site Scan page
Edge Site Scan page results

Why Web Workers?

Every line of frontend JS you've ever written has (momentarily) stopped your page from working.

60 frames per second (FPS)

1000ms / 60 frames = 16.7ms

Isn't asynchronicity enough?

// Everything between here...
$.getJSON('/payload.json', function (response) {
  // ... and here is free, right?
});

IndexedDB

(Yes, even though it's async)

AJAX

(Yes, even async XHR)

fetch

(Yes, even though it has response.json())

Stuff that can block the DOM

  • IndexedDB
  • AJAX
  • fetch
  • Garbage collection
  • JavaScript!

WEB WORKERS!

// index.js

var worker = new Worker('worker.js');
worker.postMessage('ping');
worker.onmessage = function (e) {
  console.log(e.data); // 'pong'
};
// worker.js

self.onmessage = function (e) {
  console.log(e.data); // 'ping'
  self.postMessage('pong');
};
caniuse page for Web Workers

Who's using Web Workers?

Pokedex.org

pokedex.org virtual dom architecture

Why Service Workers?

// index.js

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register(
            '/service-worker.js');
}
// service-worker.js

self.addEventListener('fetch',
    function (e) {
      e.respondWith(fetch(e.request));
    }
);
caniuse page for Service Workers
is service worker ready page
Web WorkersService Workers
Tab controlMany per tabOne for all tabs*
LifespanSame as tabIndependent
Good forParallelismOffline

Pokedex.org bundle sizes

main.js24.1kB
worker.js90.9kB
serviceWorker.js15.8kB

Protips

Beware of API support

  • No LocalStorage
  • No XHR in SW, only fetch()
  • No FileReader in Firefox <46
  • No IndexedDB in Safari <10
  • No console in Android <5
Functions and classes available to workers
html5workertest.com

html5workertest.com

promise-worker

// index.js
var pw = new PromiseWorker(
  new Worker('worker.js'));
pw.postMessage('yo').then(supports => {
  if (!supports) {
    // fall back to worker polyfill
  }
});
// worker.js
registerPromiseWorker(msg => {
  return !!self.indexedDB;
});

pseudo-worker

// index.js
var worker = new PseudoWorker(
  'worker.js');
var pm = new PromiseWorker(worker);
pm.postMessage('yo').then(msg => {
  // ...
});
// worker.js
registerPromiseWorker(msg => {
  // This will run on the main thread!
});

Powerful concepts for the web

  • Parallelism (Web Workers)
  • Offline (Service Workers)

Thank you!

@nolanlawson

nolanlawson.github.io/braziljs-2016