Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial version of basic service worker #698

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Nooshu
Copy link

@Nooshu Nooshu commented Mar 27, 2019

Draft PR created for the initial work to add a service worker to the parliament petitions website.

User Need

As has been shown in the past couple of weeks, when a popular petition is live it can put the server and infrastructure under extreme load. Many times this could be because a user is revisiting the website to look at the updated number count. Under these conditions these users can be requesting assets from the server multiple times, effectively DDoSing the server. By using the service worker API we have very fine-grain control over the caching of assets.

If a CacheFirst strategy is used, once assets are cached the requests to the server will never be made. The service worker will intercept the request and serve it directly from the service worker cache. NOTE: This is different to a standard browser cache which will periodically purge itself (depending on many different factors).

The use of a service worker can also open up other areas of improvement for users including:

  • offline access
  • a fully fledged PWA with add to home screen functionality (A2HS)
  • background synchronisation of data
  • ability to subscribe to notifications when a petition is updated

All this functionality can be considered in the future.

The primary purpose for this PR is to improve web performance on both desktop and mobile devices. According to Caniuse 86.88% of users in the UK use a browser that supports for API. Since this is a progressive enhancement, those who don't will see no difference but will still have full access to the website.

Implementation

The main focus of this PR is to work on the workflow integration into a RoR application. The two key technologies used are:

The basic serviceworker-rails setup has been modified to allow the use of Workbox and all the fine-grain control it allows us. As workbox is an npm module the workflow has needed to be changed slightly to generate the initial serviceworker.js.erbfile. npm start is used to generate the service worker file (from the workbox-config.js), and then start the rails application. NOTE: The config only needs to be run once, the compiled service worker file can then be committed.

Caching strategies

The following caching strategies have been used for the initial version:

  • HTML files: NetworkOnly since we always want a user to have the freshest version of the HTML
  • Analytics JS: NetworkOnly to avoid issues if these 3rd party files were to be modified
  • count.json: NetworkOnly so a user will always receive the latest number count update from the server. StaleWhileRevalidate could be another option here, serve a cached version first then check with the server for an update (then update in the background).
  • CSS / JS: CacheFirst so the browser will always check the service worker cache first. If found, a request to the network isn't required. If not it will fallback to the network.
  • Image files: CacheFirst so the browser will always check the service worker cache first. If found, a request to the network isn't required. If not it will fallback to the network.

The exact strategies used and expiration times can be controlled. This seem like the safest setup for the initial implementation. CacheFirst works well in this instance because filenames are appended with a unique SHA. If a file changes the SHA will change and a new request will be created, (bypassing the service worker).

Screenshots (Chrome 73)

Service worker installed in DevTools application tab.
Service worker installed in Chrome

Cache used for CSS and JS.
Application cache

Cache used for images.
Graphics cache

Homepage assets being served from the service worker.
Screen Shot 2019-03-27 at 16 51 03

Potentail future plans

Create an offline version of the site

By caching the HTML it is possible to create a version of the site that will work offline. Should the server fail, a user that has previously visited the site will receive a cached version of the site (with an old submission count). In this case it would be worth telling a user they are viewing an offline version of the site and when the figure is from.

An advantage to this approach is all assets will be cached locally. A network request would only be required if the homepage is updated and when there is a request for a new count.json.

This would require a little bit of refactoring / design to include the offline notice and date.

TODO

  • Make sure the serviceworker.js isn't being cached max-age=0, no-cache
  • Is serving Workbox from the Google CDN cache an acceptable dependency? If not then Workbox can be served locally but would require RoR workflow updates.
  • Is the current workflow acceptable for the development / production process?
  • Question to only render application/service_worker in production (for easier development)?

@Nooshu
Copy link
Author

Nooshu commented Apr 2, 2019

Verified the serviceworker.js file is being served with the correct Cache-Control headers:

Screen Shot 2019-04-02 at 08 58 53

@pixeltrix
Copy link
Contributor

@Nooshu thanks for the PR, about your comment regarding fitting into the current workflow. We are looking at some point in the near future upgrading both the app and infrastructure and one thing we'll be doing is upgrading to Rails 6.0 to take advantage of the native multi-database support so that we can use an Aurora PostgreSQL cluster. As part of that we'll probably switch over to using webpack via the webpacker gem and I was thinking it may be better to integrate this as part of that work - what do you think?

@Nooshu
Copy link
Author

Nooshu commented Apr 3, 2019

Hi @pixeltrix, yes I think that is a great idea. The current implementation does feel a little clunky. Almost like npm / workbox-cli has been crowbarred into the build process. Workbox.js actually comes with 2 webpack plugins: one that generates a complete service worker for you and one that generates a list of assets to precache that is injected into a service worker file.

It would require some reconfiguring to get working but the base workbox-config.js can be used as a guide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants