Angular 6 PWA 开发踩坑
栏目: JavaScript · 发布时间: 5年前
内容简介:更新中提示:在测试程序的时候尽量使用Chrome的在
更新中
提示:在测试程序的时候尽量使用Chrome的 隐身模式 ,确保 Service Worker 不会从以前的残留状态中读取数据!!
1. PWA在Angular 6 工程上的初始化:
在 sudo ng new pwa
新建工程之后,在工程的根目录上运行 sudo ng add @angular/pwa
,此时就会自动添加Service Worker文件,Manifest.json文件和各种不同尺寸的icon文件。 Angular PWA中文网传送门
2. PWA程序的更新
在 app.component.ts
中引入 import { SwUpdate } from '@angular/service-worker';
来加载SW的更新模块,每次PWA程序有更新都可以在这里使用SwUpdate模块获取更新,并使用如下代码可实现程序的更新操作:
export class AppComponent { update: boolean; constructor(updates: SwUpdate, private data: DataService) { updates.available.subscribe( event => { this.update = true; updates.activateUpdate().then(() => document.location.reload() ); } ); } title = 'PWA'; } 复制代码
然后在html中使用一个 *ngIf
来判断是否更新,(是则显示text,不是则不显示):
<span *ngIf="update">There's an update associated with your progressive web application!</span> 复制代码
每次更新了程序都要重新build production程序,在根目录上运行 sudo ng build --prod
,然后进入 cd dist/PWA
,最后运行 http-server -o
在服务器上运行更新后的程序。
由于 ng serve
对 Service Worker
无效,所以必须用一个独立的 HTTP 服务器在本地测试项目。 可以使用任何 HTTP 服务器,我使用的是来自 npm 中的 http-server 包。当然也可以自定义端口以防止port冲突:
http-server -p 8080 -c-1 dist/<project-name> 复制代码
注意: 如果想定期更新PWA,也就是使用interval创建一个周期轮询方法,需要先让应用注册Aervice worker的进程进入稳定状态,再让它开始执行轮询的过程,如果不断轮询更新(比如调用 interval())将阻止应用程序达到稳定态,也就永远不会往浏览器中注册 ServiceWorker 脚本。另外: 应用中所执行的各种轮询都会阻止它达到稳定态
constructor(appRef: ApplicationRef, updates: SwUpdate) { // Allow the app to stabilize first, before starting polling for updates with `interval()`. const appIsStable$ = appRef.isStable.pipe(first(isStable => isStable === true)); const everySixHours$ = interval(6 * 60 * 60 * 1000); const everySixHoursOnceAppIsStable$ = concat(appIsStable$, everySixHours$); everySixHoursOnceAppIsStable$.subscribe(() => updates.checkForUpdate()); } 复制代码
所以对于自动更新模块的使用总结:
constructor(appRef: ApplicationRef, updates: SwUpdate, private data: DataService) { const appIsStable$ = appRef.isStable.pipe(first(isStable => isStable === true)); const everySixHours$ = interval(6 * 1000); const everySixHoursOnceAppIsStable$ = concat(appIsStable$, everySixHours$); everySixHoursOnceAppIsStable$.subscribe(() => { updates.checkForUpdate(); // console.log('check update in Service Worker'); }); updates.available.subscribe(event => { console.log('gotta new version here', event.available); updates.activateUpdate().then(() => document.location.reload()); }); } 复制代码
每6妙检测一次更新版本,如果没有 updates.activateUpdate().then(() => document.location.reload());
则只是在检测到新版本时候提醒并不刷新并更新程序。 测试的时候需要重新 ng build --prod
然后 http-server -p 8080 -c-1 dist/PWA
重新运行http服务器,这时候在原来的页面上的console上就会发现出现了新版本的提醒。
(其实每次运行build命令都会出现版本更新无论是否更改代码, 当应用的一个新的构建发布时,Service Worker 就把它看做此应用的一个新版本 ,版本是由 ngsw.json 文件的内容决定的,包含了所有已知内容的哈希值。 如果任何一个被缓存的文件发生了变化,则该文件的哈希也将在ngsw.json中随之变化,从而导致 Angular Service Worker 将这个活动文件的集合视为一个新版本)
3. 如何缓存文件以及API的地址以及其他项目?
全在 nsgw-config.json
文件中定义PWA缓存,比如想缓存google的 Montserrat
字体和API地址,该文件中所有的代码形式都是glob格式,也就是:
- ' ** ' 匹配 0 到多段路径
- ' * ' 匹配 0 个或更多个除 / 之外的字符
- ? 匹配除 / 之外的一个字符
- ! 前缀表示该模式是反的,也就是说只包含与该模式不匹配的文件
比如:
- /**/*.html 指定所有 HTML 文件
- /*.html 仅指定根目录下的 HTML 文件
- !/**/*.map 排除了所有源码映射文件
在实际代码中这样做:
<link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet"> 复制代码
在已经被创建的 assetGroups
中添加:
"urls": [ "https://fonts.googleapis.com/**" ] 复制代码
AssetGroup遵循的TypeScript接口规则为:
interface AssetGroup { name: string; installMode?: 'prefetch' | 'lazy'; // prefetch 告诉 Angular Service Worker 在缓存当前版本的应用时要获取每一个列出的资源。 这是个带宽密集型的模式,但可以确保这些资源在请求时可用,即使浏览器正处于离线状态 // lazy 不会预先缓存任何资源。相反,Angular Service Worker 只会缓存它收到请求的资源。 这是一种按需缓存模式。永远不会请求的资源也永远不会被缓存。 这对于像为不同分辨率提供的图片之类的资源很有用,那样 Service Worker 就只会为特定的屏幕和设备方向缓存正确的资源。 updateMode?: 'prefetch' | 'lazy'; // prefetch 会告诉 Service Worker 立即下载并缓存更新过的资源 // lazy 告诉 Service Worker 不要缓存这些资源,而是先把它们看作未被请求的,等到它们再次被请求时才进行更新。 lazy 这个 updateMode 只有在 installMode 也同样是 lazy 时才有效。 resources: { files?: string[]; /** @deprecated As of v6 `versionedFiles` and `files` options have the same behavior. Use `files` instead. */ versionedFiles?: string[]; urls?: string[]; }; } 复制代码
在下方创建 dataGroups
缓存API地址:
"dataGroups": [ { "name": "jokes-api", "urls": [ "https://api.chucknorris.io/jokes/random" ], "cacheConfig": { "strategy": "freshness", "maxSize": 20, "maxAge": "1h", "timeout": "5s" } } ] 复制代码
dataGroups的配置遵循下面的接口:
export interface DataGroup { name: string; urls: string[]; version?: number; cacheConfig: { maxSize: number; maxAge: string; timeout?: string; strategy?: 'freshness' | 'performance'; }; } 复制代码
其中的缓存设置中的几个项目分别是:
-
"strategy" :
- performance,默认值,为尽快给出响应而优化。如果缓存中存在某个资源,则使用这个缓存版本。 它允许资源有一定的陈旧性(取决于 maxAge)以换取更好的性能。适用于那些不经常改变的资源,例如用户头像。
- freshness 为数据的即时性而优化,优先从网络获取请求的数据。只有当网络超时时,请求才会根据 timeout 的设置回退到缓存中。这对于那些频繁变化的资源很有用,例如账户余额。
- "maxSize" : (必需)缓存的最大条目数或响应数。开放式缓存可以无限增长,并最终超过存储配额,建议适时清理。
- "maxAge" : d(必需)maxAge 参数表示在响应因失效而要清除之前允许在缓存中留存的时间。(d:天数,h:小时数,m:分钟数,s:秒数,u:微秒数)
- "timeout" : 这个表示持续时间的字符串用于指定网络超时时间。 如果配置了它,Angular Service Worker 在开始使用缓存之前就会先等待网络给出响应,这个等待时间就是网络超时时间。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- ABP开发框架前后端开发系列---(14)基于Winform的ABP快速开发框架
- Java开发人员的Flex开发
- Java开发人员的Flex开发
- 行为驱动开发让开发做正确事
- 让开发者专注于应用开发,OpenCenter 3.0 开发者预览版发布
- 让开发者专注于应用开发,OpenCenter 3.0 开发者预览版发布
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。