Page MenuHomePhabricator

[web] Add support for web workers to webpack
ClosedPublic

Authored by michal on Feb 13 2023, 6:54 AM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Dec 24, 3:40 PM
Unknown Object (File)
Tue, Dec 24, 3:40 PM
Unknown Object (File)
Tue, Dec 24, 3:40 PM
Unknown Object (File)
Mon, Dec 23, 6:35 PM
Unknown Object (File)
Mon, Dec 23, 6:35 PM
Unknown Object (File)
Sat, Dec 21, 8:17 PM
Unknown Object (File)
Sat, Dec 21, 8:07 PM
Unknown Object (File)
Sat, Dec 21, 7:47 PM
Subscribers

Details

Summary

Part of ENG-2826

This diff adds a new webpack configuration for generating web/service worker files. It should be easily extensible for future service workers (just add a new field in entry config). It also includes a basic service worker that logs when it installs and activates.

Test Plan

Run yarn dev and yarn prod in comm/web and check if the service worker file is correctly generated.

Diff Detail

Repository
rCOMM Comm
Lint
No Lint Coverage
Unit
No Test Coverage

Event Timeline

ashoat requested changes to this revision.Feb 13 2023, 3:33 PM

Questions – how will this WebWorker code be loaded, and when will it be re-downloaded from the server? Is it a SharedWorker or not? Does it run "in the background", eg. when 0 tabs are open? Or does it only run when at least 1 tab is open? Does it redownload / re-run only when all tabs are closed?

web/package.json
9 ↗(On Diff #22425)
  1. Red seems scary, can we find a more neutral color?
  2. Is there a way to make Web Workers "hot reload" with webpack-dev-server?
web/webpack.config.cjs
91 ↗(On Diff #22425)

What's sw stand for? Might be better to be more verbose

113 ↗(On Diff #22425)

You'll need to rebase on my Webpack 5 diffs that just got landed

This revision now requires changes to proceed.Feb 13 2023, 3:33 PM

We should make sure the file is named differently every time it is generated in prod mode, so it doesn't get cached. We can use assets.json and the associated Webpack module for this, but only need to do that in prod mode – can use the same file every time on dev, but we should consider if we should be serving dev with webpack-dev-server

Rename sw.js -> service-worker.js, change color, use env.prod.

Answers to questions:

  1. How will this WebWorker code be loaded, and when will it be re-downloaded from the server? Does it redownload only when all tabs are closed?

The service worker will be downloaded during every page load with navigator.serviceWorker.register('<url to this file>'). If it's different (by comparing bytes) than the previously active service worker (from the same url) it will replace it when all of the tabs are closed (so there's always only one active service worker for all tabs), although this can be overridden.

  1. Is it a SharedWorker or not?

It's a ServiceWorker which is a separate thing from SharedWorkers. But it's shared between all tabs.

  1. Does it run "in the background", eg. when 0 tabs are open? Or does it only run when at least 1 tab is open?

Service workers are event-driven. The browser wakes them up to handle a specific event and then they go to sleep. These events can be for example:

  • install - when the service worker is installed
  • push - when we get a push notif from the push service
  • when we send a message to the service worker from the web app

But yes, it can handle events even if no tabs are open.

  1. Caching

This shouldn't be a problem: (link)

Most browsers, including Chrome 68 and later, default to ignoring caching headers when checking for updates of the registered service worker script. They still respect caching headers when fetching resources loaded inside a service worker via importScripts(). You can override this default behavior by setting the updateViaCache option when registering your service worker.

We could set max-age header to deal with the older browsers.
When it comes to the filenames, in D6716 the files are served through /workers/notif so the filename isn't exposed. But even if we would expose it's not recommended to change it: (link)

you may consider giving each version of your service worker a unique URL. Don't do this! This is usually bad practice for service workers, just update the script at its current location.

(Although the problem explained in the link shouldn't happen to us because we aren't using the service worker for caching, only for push api)

  1. Hot reloading

I don't think webpack supports hot reloading service workers, I couldn't find any examples of it on the internet. Additionally, I tried using webpack-dev-server but I had problems because service workers should be served from the same origin as the website.

Thanks for explaining everything! (Make sure to wait on CI before landing)

This revision is now accepted and ready to land.Feb 14 2023, 7:15 AM
  • Changed suffix from .cjs to .js
  • Added babel config to strip flow types

I just exported the browser babel rules and used the default web babel config. We could make a new createWorkerConfig function in shared.cjs but web workers aren't shared between web and landing so I don't think that's that's needed.

Please rebase on master, re-run yarn cleaninstall, update this diff, and confirm all CI gates are passing before landing!

Added webpack.DefinePlugin with some constants (NODE_ENV, BROWSER). Moved part of the configuration to the shared.cjs so it's together with similar comfigurations for web webpack.