How to deploy updates to service workers running on customers' sites?

感情迁移 提交于 2019-12-22 10:55:45

问题


Suppose I provide a push notification service used by different websites. This service requires a service worker to be installed on my customers' sites. I want the architecture to have a few properties:

  • Completely static resources. The process of installing the service worker files and configuring the JS snippet, etc. only needs to be done once.
  • The ability to update the service worker at any time. I want to be able to update the service worker at any time to fix bugs, deploy improvements, etc.

Satisfying both of these constraints is difficult because the browser only installs a new version of the service worker if the content of service worker script itself changes. (That is, without considering dependencies specified via importScripts().)


回答1:


If you can't change the contents of service worker itself, consider creating a "new" service worker by appending a hash to the service worker URL. This will cause the browser to install the "new" service worker every time the hash changes.

That is, replace code like

navigator.serviceWorker.register("/sw.js");

with

navigator.serviceWorker.register(`/sw.js?hash=${HASH}`);

When the "new" service worker is installed, the browser will re-check all imported scripts. (This applies even if the "new" service worker is byte-for-byte identical to the "old" one, because the URLs are different.)

How to generate the hash?

There's a few different ways to generate the hash. A completely random HASH will lead to the browser updating the service worker on every page load, which is unlikely to be what you want.

Two different approaches:

  • (Best) You know when the imported script changes. In this case, only change HASH when the imported script changes. Ideally, HASH would be a hash of the contents of the imported script itself.
  • (Okay) Derive the hash from the time. Math.floor(Date.now() / (3600 * 1000)) will cause a "new" service worker to be installed every hour, which will also result in the dependencies being checked. (You'll probably also want to apply some jitter to avoid all clients updating at the same time.)

Suggested architecture

If you provide a service-worker backed service to other websites (e.g. a push notification service), you can provide a completely static service worker and JS install snippet to your customers which allows you to control and trigger updates completely from your site.

Code for customer.com (all static):

JS snippet for customer to include on all HTML pages their site (static):

<script src="https://provider.com/register-sw.html?customer_id=8932e4288bc8">
</script>

Service worker for customer to install at https://example.com/sw.js (static):

importScripts("https://provider.com/imported-sw.js?customer_id=8932e4288bc8");

Code for your site (can be dynamic):

Service worker registration code on your site at https://provider.com/register-sw.html?customer_id=8932e4288bc8 (dynamic):

const HASH = hash_of_file("imported-sw.js");
navigator.serviceWorker.register(`/sw.js?hash=${HASH}`);

"Real" service worker on your site at https://provider.com/imported-sw.js?customer_id=8932e4288bc8 (dynamic):

// when service worker is updated, all clients receive
// update because service worker itself is "new"
self.addEventListener(...);

NOTE: The byte-for-byte requirement is in the process of being changed so that this check extends to imported scripts by default (not just the registered URL itself), but as of April 2017 no browser implements this behavior.



来源:https://stackoverflow.com/questions/43471530/how-to-deploy-updates-to-service-workers-running-on-customers-sites

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!