假设我提供了不同网站使用的推送通知服务。此服务需要在我的客户站点上安装服务 worker 。我希望架构具有一些属性:
- 完全静态资源。安装service worker文件和配置JS片段等过程只需要完成一次。
- 随时更新 service worker 的能力。我希望能够随时更新 service worker 以修复错误、部署改进等。
同时满足这两个约束是困难的,因为如果服务 worker 脚本本身的内容发生变化,浏览器只会安装新版本的服务 worker 。 (也就是说,不考虑通过 importScripts()
指定的依赖项。)
最佳答案
如果您无法更改 service worker 本身的内容,请考虑通过将哈希附加到 service worker URL 来创建"new"service worker。这将导致浏览器在每次哈希更改时安装"new"服务 worker 。
也就是替换成这样的代码
navigator.serviceWorker.register("/sw.js");
与
navigator.serviceWorker.register(`/sw.js?hash=${HASH}`);
安装"new"服务工作线程时,浏览器将重新检查所有导入的脚本。 (即使"new"服务 worker 与“旧”服务 worker 逐字节相同,这也适用,因为 URL 不同。)
如何生成哈希?
有几种不同的方法可以生成哈希值。完全随机的 HASH
将导致浏览器在每次加载页面时更新 service worker,这不太可能是您想要的。
两种不同的方法:
- (最好)您知道导入的脚本何时更改。在这种情况下,仅在导入的脚本更改时更改
HASH
。理想情况下,HASH
应该是导入脚本本身内容的哈希值。 - (好的)从时间中导出哈希。
Math.floor(Date.now()/(3600 * 1000))
将导致"new"服务worker 每小时安装一次,这也会导致检查依赖项。 (您可能还想应用一些抖动来避免所有客户端同时更新。)
建议的架构
如果您向其他网站提供服务工作人员支持的服务(例如推送通知服务),您可以向您的客户提供完全静态的服务工作人员和 JS 安装片段,这允许您完全从您的网站控制和触发更新.
customer.com 的代码(全部静态):
供客户在其站点的所有 HTML 页面中包含的 JS 代码段(静态):
<script src="https://provider.com/register-sw.html?customer_id=8932e4288bc8">
</script>
服务人员在 https://example.com/sw.js 为客户安装(静态):
importScripts("https://provider.com/imported-sw.js?customer_id=8932e4288bc8");
您网站的代码(可以是动态的):
您网站上的 Service Worker 注册码 https://provider.com/register-sw.html?customer_id=8932e4288bc8 (动态):
const HASH = hash_of_file("imported-sw.js");
navigator.serviceWorker.register(`/sw.js?hash=${HASH}`);
您站点上的“真实”服务人员 https://provider.com/imported-sw.js?customer_id=8932e4288bc8 (动态):
// when service worker is updated, all clients receive
// update because service worker itself is "new"
self.addEventListener(...);
注意:字节对字节的要求是in the process of being changed因此默认情况下此检查扩展到导入的脚本(不仅仅是注册的 URL 本身),但截至 2017 年 4 月,没有浏览器实现此行为。
关于service-worker - 如何将更新部署到在客户站点上运行的服务 worker ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43471530/