引入 Angular Service Worker
首先
这篇文章是 Angular Advent Calendar 2017 第17天的文章。
在这篇文章中,我们将介绍如何将 Angular v5 中发布的 @angular/service-worker 引入现有的 Angular 项目中。
角度项目
我没有时间自己准备,所以我会利用这个很不错的示例应用程序来继续进行。
在注册Service Worker之前,让我们先在Lighthouse中进行分析。
$ npm i
$ ng build --prod
$ http-server dist
引入 Angular Service Worker
在这篇日文文章中,laco在Angular CLI 1.5下的Angular Service Worker快速入门中表现得非常出色,我在这篇文章中也有很大的参考价值。
$ npm i @angular/service-worker
$ ng set apps.0.serviceWorker=true
这样在 .angular-cli.json 文件中将会添加参数 “serviceWorker”: true 的设置。
然后,Angular Service Worker使用了以下两个文件。
-
- ngsw-worker.js: Angular Service Workerの本体
- ngsw.json: ngsw-worker.jsが使う設定ファイル
使用Angular CLI的资产功能,将ngsw-worker.js文件从node_modules目录下复制到输出目录的根目录。
"assets": [
"assets",
"favicon.ico",
"sitemap.xml",
"googled41787c6aae2151b.html",
"CNAME",
{
"input": "../node_modules/@angular/service-worker",
"glob": "ngsw-worker.js",
"output": "."
}
],
通过使用 Angular Service Worker 提供的 ngsw-config 命令来生成 ngsw.json 文件。创建一个新的原始配置文件 src/ngsw-config.json。
{
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": ["/favicon.ico", "/index.html"],
"versionedFiles": ["/*.bundle.css", "/*.bundle.js", "/*.chunk.js"]
}
}
]
}
在package.json中注册一个新的构建脚本。
"scripts": {
"build:ngsw": "ng build -prod && node_modules/.bin/ngsw-config dist src/ngsw-config.json"
},
最后,我们需要将ngsw-worker.js文件作为Service Worker注册到应用程序中,为此我们需要在应用程序中引入ServiceWorkerModule。打开app.module.ts文件,并进行以下编辑。
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
// Import NGSW module
import {ServiceWorkerModule} from '@angular/service-worker';
import {APP_CONFIG, AppConfig} from './config/app.config';
import {AppRoutingModule} from './app-routing.module';
import {SharedModule} from './shared/modules/shared.module';
import {CoreModule} from './core/core.module';
import {AppComponent} from './app.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {HTTP_INTERCEPTORS, HttpClient, HttpClientModule} from '@angular/common/http';
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {HttpLoaderFactory} from './app.translate.factory';
import {HeroTopComponent} from './heroes/hero-top/hero-top.component';
import {ProgressBarService} from './core/progress-bar.service';
import {ProgressInterceptor} from './shared/interceptors/progress.interceptor';
import {TimingInterceptor} from './shared/interceptors/timing.interceptor';
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
SharedModule.forRoot(),
CoreModule,
AppRoutingModule,
// Register ngsw-worker.js as SW
ServiceWorkerModule.register('/ngsw-worker.js'),
],
declarations: [
AppComponent,
HeroTopComponent
],
providers: [
{provide: APP_CONFIG, useValue: AppConfig},
{provide: HTTP_INTERCEPTORS, useClass: ProgressInterceptor, multi: true, deps: [ProgressBarService]},
{provide: HTTP_INTERCEPTORS, useClass: TimingInterceptor, multi: true}
],
bootstrap: [AppComponent]
})
export class AppModule {
}
那么让我们现在试着在这个状态下运行应用程序。
$ npm run build:ngsw
$ http-server dist
当您使用DevTools或Lighthouse进行检查时,您将会发现已经注册了Service Worker。
并且根据在ngsw-config.json中设置的缓存配置,除了从外部API获取数据的部分之外,其余的离线支持也已经完成。现在就来试一试吧。
如果在选择「离线」后重新加载或页面转换,则外部的应用程序框架将保持不变,但是英雄信息将不会显示,加载状态将继续。
为了备用离线访问,也要将Hero的信息存入缓存中。
运行时缓存
为此,将使用与之前使用的assetGroups不同的dataGroups。
-
- assetGroups
app [shell]のバージョンを追跡していて、グループのうち1つ以上のリソースが更新された場合、利用可能な新しいバージョンのアプリがあるとみなし、対応する更新フローを開始する
dataGroups
appのバージョンとは独立していて、独自のキャッシュポリシーを使ってキャッシュを行う。APIレスポンスを処理するのに適切
在ngsw-config.json中添加dataGroups配置,并进行如下编辑。
{
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html"
],
"versionedFiles": [
"/*.bundle.css",
"/*.bundle.js",
"/*.chunk.js"
]
}
}
],
"dataGroups": [
{
"name": "api-freshness",
"urls": [
"/",
"/heroes"
],
"cacheConfig": {
"strategy": "freshness",
"maxSize": 100,
"maxAge": "3d",
"timeout": "10s"
}
}
]
}
即使处于离线状态,英雄的信息也能够从缓存中成功显示出来!
参考资料
-
- Angular CLI 1.5によるAngular Service Workerクイックスタート – lacolaco-blog – Medium
-
- Automatic Progressive Web Apps using the Angular Mobile Toolkit by Maxim Salnikov
-
- A new Angular Service Worker — creating automatic progressive web apps. Part 1: theory
-
- A new Angular Service Worker — creating automatic progressive web apps. Part 2: practice
- https://angular.io/guide/service-worker-intro
最后
关于ngsw-config.json的设置,请参阅官方文档以获取详细信息,并尝试阅读该文档。