[翻译]生产环境中的Service Worker

原文

这一页是关于部署和支持使用Angular service worker的生产版本应用。解析了Angular service worker怎么适应更大的生产环境、在各种环境下service worker的行为表现以及可用的资源和保险措施。

前期准备

如下的基础知识:

Service worker 和 缓存app资源

在概念上,你可以想象Angular service worker为是已经在客户端的浏览器安装好的一个前端缓存或者一个CDN节点。service worker的工作就是满足Angular应用程序不需要等待网络的情况下完成对本地缓存资源或数据的请求。像任何缓存一样,它也有内容如何过期和更新的规则。

App版本

在Angular service worker的上下文环境内,一个版本就是构建app的资源集合。只要新的版本被部署了,service worker就会将其作为一个新的app版本。即使只有单个文件被修改,也是当成一个新版。有些时候,service worker可能有多个app的版本缓存并有可能同时使用他们。想了解更多请到本页下面的 App tabs 部分.

为了保持应用程序的完整性,Angular service worker将所有文件组合成一个版本。这样的版本通常包括了 HTML, JS, 和 CSS文件。这些文件经常互相引用并依赖特定的上下文。例如,index.html 可能有<script>标签,标签引用了bundle.js,html内尝试调用这脚本内的startApp()方法。任何时候这版本的index.html被启动了,同样的bundle.js必须被提供。假设在两个文件中 startApp()方法重命名为runApp()。在这种情况下,使用旧的index.html和新的bundle.js的话,就会报错。

文件的完整性十分重要,特别在懒加载模块时。一个 js代码块可能引入许多懒加载的代码块,这些懒加载代码块是对应于某个特别的app版本。如果运行一个版本为 X的app,并尝试加载一个已经被服务更新到X + 1 版本的懒加载代码块。这个懒加载操作就会失败。

app版本的识别码是由所有资源的内容决定的,牵一发而动全身。实际,ngsw.json文件的内容决定版本,包含了所有已知内容的hashes码。如果缓存里的某个文件更改了,对应ngsw.json的hash也会被修改。这样Angular service worker就会把新的文件集合当成一个新版本。

通过这样Angular service worker的版本控制,应用服务器可以确保Angular应用程序始终拥有一组一致的文件。

更新检查

每次用户打开或刷新应用,Angular service worker会去查看ngsw.json去检查app的更新。如果找到的更新,它就会下载好并缓存资源,并在下次app加载时使用。

资源的完整性

长时间缓存的潜在副作用之一是无意中缓存无效资源。在正常的HTTP缓存中,深度刷新或缓存过期降低了缓存无效文件的负面影响。service worker忽略这样的约束,并有效地缓存整个应用程序。因此,service worker获得正确的内容至关重要。

为了保证资源的完整性,Angular service worker验证所有资源的hashe码。通常,对于CLI应用程序,用户的src / ngsw-config.json配置涵盖了dist目录中的所有内容。

如果某个特定的文件未通过验证,那么Angular服务工作人员将尝试使用“cache-busting”URL参数重新获取内容,以消除浏览器或中间缓存的影响。如果该内容也未通过验证,则service worker认为该应用的整个版本无效,并停止为该应用提供服务。如有必要,service worker进入安全模式,请求回退到网络上,如果服务无效,损坏或内容过期的风险较高,则选择不使用其缓存。

哈希不匹配可能由于各种原因而发生:

  • 在源服务器和最终用户之间缓存层可能会提供陈旧的内容。
  • 非原子部署可能会导致 Angular service worker看到部分更新的内容。
  • 构建过程中的错误可能会导致更新资源,但没有更新ngsw.json。反过来也有可能,没有更新的资源,但更新了ngsw.json。

没有hash的内容

在ngsw.json有hash的资源是在构建后在dist文件夹里的文件。其它资源,特别是name从CDN是获得的资源,在构建时内容是未知的,或者比app的部署更新更加频繁,是没有hash的。

如果Angular service worker没有一个hash码去验证获得的资源,它会仍然缓存这内容,不过是根据HTTP缓存头的内容使用“stale while revalidate”策略去判断。这样,当HTTP缓存头表面资源已过期,Angular service worker继续提供内容并尝试在后台刷新资源。通过这样的办法,无效的过期的没有hash资源不会保留在缓存中

app部分

如果应用程序接收到的资源版本突然更改或没有警告,则可能会造成问题。有关这些问题的描述,请参阅上面的版本部分。

Angular service worker提供了一个保证:正在运行的应用程序将继续运行相同版本的应用程序。如果在新的Web浏览器选项卡中打开了同一个应用程序实例,则会提供该应用程序的最新版本。因此,新选项卡可以运行与原始选项卡不同的应用程序版本。

有一个重要的注意项,这个保证是比普通的web的部署要强。没有service worker,无法保证正在运行的应用程序中懒加载的代码与应用程序的初始代码的版本相同。

Angular service worker可能会更改正在运行的应用程序的版本有几个有限的原因。其中一些是错误状态:

  • 当前版本由于hash验证错误变为无效。
  • 无关的错误导致service worker进入安全模式;即暂时停用。

任何时候Angular service worker知道哪个版本正在被使用。它会清空那些没有页面使用的版本。

其它导致 Angular service worker可能更新正在运行的app版本的原因是以下常规事件:

  • 页面重新载入或刷新。
  • 页面自己请求更新到最新版(参考service worker的交互)

Service worker的更新

Angular service worker是一个运行再浏览器里的小脚本。随着事件推移,service worker会被修复错误和改进功能。

Angular service worke的下载是在app第一次打开时和app在一段时间后被访问时。如果service worker被修改了,它的更新会在后台进行。

Angular service worker的大部分更新对应用程序都是透明的 - 旧缓存仍然有效,内容仍然正常使用。可是,有时Angular service worker的错误修改或功能需要引入无效的旧缓存。这种情况下,app会直接通过网络刷新加载。

调试 Angular service worker

偶尔,可能需要检查处于运行状态的 Angular service worker,以调查问题或确保其按设计运行。浏览器提供了用于调试service workers的内置工具,而且Angular service worker本身也包含有用的调试功能

Angular service worker在虚拟的ngsw / 目录下暴露调试信息。目前,暴露的URL是ngsw / state。这里是这个调试页面内容的一个例子

NGSW Debug Info:

Driver state: NORMAL ((nominal))
Latest manifest hash: eea7f5f464f90789b621170af5a569d6be077e5c
Last update check: never

=== Version eea7f5f464f90789b621170af5a569d6be077e5c ===

Clients: 7b79a015-69af-4d3d-9ae6-95ba90c79486, 5bc08295-aaf2-42f3-a4cc-9e4ef9100f65

=== Idle Task Queue ===
Last update tick: 1s496u
Last update run: never
Task queue:
 * init post-load (update, cleanup)

Debug log:

Driver state

信息的第一行就是驱动状态:

Driver state: NORMAL ((nominal))

NORMAL 表明service worker正常工作,没有在降级工作。

以下是两个可能的降级状态:

  • EXISTING_CLIENTS_ONLY: service worker没有一个整洁的最近的app版本。但旧的缓存版本是可安全使用的,所以现存的tab页面会继续运行在此缓存版本,而对于新app的加载会直接从网络中加载请求。
  • SAFE_MODE: service worker不能保证安全地使用缓存数据。发生了意外的错误或所有已缓存的版本已失效。所有的请求回复都直接从网络获取。service worker基本没有运作。

在以上两种情况,括号内会提供导致service worker进入降级状态的错误说明。

Latest manifest hash

Latest manifest hash: eea7f5f464f90789b621170af5a569d6be077e5c

这是service worker有的最新版本的app的SHA1 hash

Last update check

Last update check: never

这表明service worker最近一次检查更新或升级app版本的时间,never说明从来没有进行更新检查。

在这个例子的调试文件中,更新检查当前正被调度,如下一节所述。

Version

=== Version eea7f5f464f90789b621170af5a569d6be077e5c ===

Clients: 7b79a015-69af-4d3d-9ae6-95ba90c79486, 5bc08295-aaf2-42f3-a4cc-9e4ef9100f65

这例子里,service worker有该app的一个版本缓存,并为两个tab页提供服务。能看到,这版本hash 是与上一个latest manifest hash的内容一样。两个客户端都在展示最新版本的app。每个客户端的id是由浏览器的相关api产生的。

Idle task queue

=== Idle Task Queue ===
Last update tick: 1s496u
Last update run: never
Task queue:
 * init post-load (update, cleanup)

空闲任务队列是service worker在后台待完成的任务表。如果有任务,则有相关描述展示。这例子中,service worker有一个任务计划,一个初始化操作包括了一个更新检查和清除旧的缓存。

last update tick/run 就是队列事件计数器。"Last update run"表示上一个任务执行的时间。"Last update tick"表示离上一个队列可能执行的事件的时长。

Debug log

Debug log:

service worker里发生的错误日志。

开发者工具

Chrome 之类的浏览器提供了与service worker交互的开发者工具。这些工具如果被合适使用将是十分强大,不过这里一些是要注意的:

  • 当开启开发者工具后,service worker会保持在后台运行而且不会重新加载。这有可能导致体验与一般用户的体验不一样。
  • 如果进入Cache Storage分页,会经常发现缓存过期了。可以右键对应缓存然后选择refesh去更新。

在Service Worker的面板里停止和开始服务都会触发更新检查事件。

故障保障

如同任何的复杂系统,bugs 或者错误的配置可能会导致Angular service worker出现意外的故障。其设计尝试将这些问题的影响降到最低,service worker拥有故障保护机制如果管理员需要快速停用service worker。

要停用service worker,可移除或者改名ngsw-config.json文件,当service worker请求ngsw.json返回404时,ervice worker会清除所有的缓存并把自身的注册取消,彻底自我销毁。

更多的关于 Angular service workers

你可能对以下感兴趣

你们的赞赏是我的无限动力

如果觉得文章对你有点用的话,麻烦拿出手机,这里有一个你我都有的小福利(每天一次): 打开支付宝首页搜索“8601304”,即可领红包。谢谢支持

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335