使用 Service Worker 的新应用
命令如下:
ng new myApp --service-worker (or using the alias — -sw )
有了这个服务工作者标志,Angular CLI 1.6 将为我们做一些自动化:
- Angular Service Worker 包将被安装。
- 将启用对 NGSW 的构建支持。
- 将为您的申请注册 NGSW。
- 将使用一些智能默认值创建 NGSW 配置文件。
不管怎样,即使在 CLI 1.6 发布之后,知道如何重现这些步骤也很好,因为我们必须手动执行它们才能将 NGSW 支持添加到现有应用程序。让我们在 PWAtter 中添加 Angular Service Worker。
向现有应用添加 Angular Service Worker
让我们手动执行上面相同的 4 个步骤:
1.安装 NGSW
npm install @angular/service-worker --save
2。启用构建支持(仅适用于 Angular CLI 1.6,请参阅下面的通知)
ng set apps.0.serviceWorker=true
或在.angular-cli.json 文件中手动添加/编辑此参数。
重要!目前,当我们使用 Angular CLI 1.5 时,请
确保您在.angular-cli.json 中没有此属性,它会
导致构建错误。了解如何在 Angular CLI 1.5 中模拟此步骤
下面。
3.在您的AppModule 中注册 NGSW。这就是它在 Angular 中的样子
CLI 1.6:
import { ServiceWorkerModule } from '@angular/service-worker'
import { environment } from '../environments/environment';
...
@NgModule({
imports: [
...
environment.production ? ServiceWorkerModule.register('/ngsw-worker.js') : []
],
...
})
export class AppModule { }
4.创建 NGSW 配置文件(默认名称为 src/ngsw-config.json)。这是 Angular CLI 1.6 将生成的默认内容。
{
"index": "/index.html",
"assetGroups": [{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html"
],
"versionedFiles": [
"/*.bundle.css",
"/*.bundle.js",
"/*.chunk.js"
]
}
}, {
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**"
]
}
}]
}
目前,在使用 Angular CLI 1.5 时,我们还必须模拟第 2 步的构建支持。实际上,除了 ng build --prod 命令之外,还需要执行 2 个额外的操作(使用生产构建很重要,以便使用 NGSW!):
使用 NGSW CLI ngsw-config 根据 NGSW 配置文件 src/ngsw-config.json 生成 NGSW 控制(清单)文件 ngsw.json。
将 NGSW 本身从 npm_modules 包文件夹复制到我们的 dist 文件夹。
为了有一个简单的命令来生成支持 NGSW 的生产版本,让我们添加一些 npm 脚本:
{
...
"scripts": {
...
"ngsw-config": "node_modules/.bin/ngsw-config dist src/ngsw-config.json",
"ngsw-copy": "cp node_modules/@angular/service-worker/ngsw-worker.js dist/",
"build-prod-ngsw": "ng build --prod && npm run ngsw-config && npm run ngsw-copy",
"serve-prod-ngsw": "npm run build-prod-ngsw && http-server dist -p 8080"
}
}
现在,如果我们运行 npm run build-prod-ngsw,我们将在 dist 文件夹中拥有 Angular PWA。或者,我们可以使用最简单的 http-server 通过运行 npm run serve-prod-ngsw 来提供它。
重要!不要使用ng serve 来测试你的Angular Service Worker。
此开发服务器并非旨在与
PWA 流。始终构建应用程序的生产版本并提供服务
使用任何静态 Web 服务器从您的分发文件夹中。
应用程序外壳
如果我们执行上述操作并运行npm run build-prod-ngsw — 默认形式的 Angular PWA 已经为我们准备好了!部署应用程序或使用任何静态 Web 服务器在本地运行它(在我的情况下,http-server 包,您运行 npm run serve-prod-ngsw 来构建和服务)。
我们下线后应用程序将继续运行。为什么?因为 NGSW 缓存了配置文件的assetGroups部分列出的所有资源,现在它负责从缓存存储中提供它们,缓存存储现在已经满是记录了:
Service Worker 已注册并处于活动状态
我们可以查看缓存响应的内容(目前仅在Chrome Canary中可用)
NGSW 使用缓存存储来存储 HTTP 响应数据和一些元数据来处理版本控制:
NGSW 的存储类型
- 后缀为
:cache 的条目— 实际的 HTTP 响应。
- 带有后缀
:meta 的条目— 用于存储版本控制元信息。稍后这种存储的数据可能会移动到indexedDB。
如果您保持 DevTools 打开,缓存存储部分中的条目
很可能不会在每次操作后自动更新
服务人员方面。如果您想查看实际数据,请右键单击
并选择刷新缓存。
没错。 NGSW 配置文件的默认形式对于我们的案例来说是不够的,因为我们使用 Material Icons webfont。显然,这些资源(对应的 CSS 和 WOFF2 文件)没有被 NGSW 缓存,但是我们可以通过在默认的 app 和 assets 之外再添加一组到 assetGroups 来轻松修复它。我们就叫它fonts:
{
...
"assetGroups": [
...
{
"name": "fonts",
"resources": {
"urls": [
"https://fonts.googleapis.com/**",
"https://fonts.gstatic.com/**"
]
}
}]
}
使用 glob 语法指定这些资源是有意义的,因为字体文件的确切 URL 可能会不时更改以支持 webfont 版本控制。此外,您可能会注意到我们既没有指定installMode 也没有指定updateMode。一方面,两者都将在生成的 NGSW 控制文件中设置为 prefetch,因为这是默认值。另一方面,它们只有在被请求后才会被缓存,因为urls 的具体规定是列出资源的方式。
在我们重建、运行并切换到离线模式后,我们将看到应用程序的正常状态以及所有图标。
在缓存存储中,我们将看到两个新条目:
NGSW 生成的存储
我们甚至可以预览缓存的字体:
assetGroups 和 dataGroups 之间存在根本区别。
-
assetGroups 正在跟踪应用 [shell] 版本。
-
dataGroups 独立于应用程序版本。它们被缓存使用
他们自己的缓存策略,这是处理我们的适当部分
API 响应。
运行时缓存
对我的/timeline API 端点使用网络优先策略,对/favorites 端点使用缓存优先策略。 src/ngsw-config.json 中的相应设置如下所示:
{
...
"dataGroups": [{
"name": "api-freshness",
"urls": [
"/timeline"
],
"cacheConfig": {
"strategy": "freshness",
"maxSize": 100,
"maxAge": "3d",
"timeout": "10s"
}
},
{
"name": "api-performance",
"urls": [
"/favorites"
],
"cacheConfig": {
"strategy": "performance",
"maxSize": 100,
"maxAge": "3d"
}
}
]
}
有一个定义 NGSW 行为的主开关:cacheConfig / strategy。对于网络优先策略,它是freshness,对于缓存优先 — performance。
现在构建、提供服务,单击加载我的时间线和加载我的收藏夹按钮以获取和缓存 API 响应,然后切换到离线状态。
关于在线模式的优化。返回在线并单击Timeline / Favorites 一次或两次。可以清楚地看到收藏夹立即加载,只是因为我们跳过了整个网络行程并从缓存中获取数据。要指定缓存多长时间使用cacheConfig 部分中的设置 — 我们在那里有细粒度的控制。
NGSW 在一些非常智能的网络优化方面为我们提供了很多帮助,只需要我们进行一些 JSON 配置。