笔者之前的文章基于 Angular Universal 引擎进行服务器端渲染的前端应用 State Transfer 故障排查案例,介绍了 Angular 应用通过开启服务器端渲染,以实现搜索引擎优化(SEO),提高首屏加载速度,改善用户体验的这种业内最佳实践之一。
本文笔者将会向大家介绍 Web 应用开发里,另一种能够确保用户在桌面和移动设备上,获得不亚于原生应用程序用户体验的设计思路,即 Progressive Web App(下文简称 PWA),在 mozilla developer 官网上,PWA 又被翻译成渐进式 Web 应用。
下图是 PWA 技术官网首页:
图1:PWA 官网的中文镜像网站
什么是 PWA 开发方式?
PWA 是一种基于 Web 技术的应用程序开发方法,旨在提供具有可以和原生应用程序(iOS 和 Android 应用)的用户体验相媲美的 Web 应用程序。
显然,这个开发理念的关键就在于 Progressive
一词。
Progressive
含义来源于 Progressive Enhancement
的概念。Progressive Enhancement
是一种设计原则,旨在确保网页和应用在各种浏览器和设备上都能够提供基本功能
,同时在现代环境
中能够提供更多功能和增强体验。换言之,一个 PWA 应该在低性能、老旧浏览器和不稳定的网络条件下,仍然能够运行,并在现代浏览器和高速网络中,提供更多功能。遵循这种设计原则开发出的 PWA 应用,确保了能够被更广泛的受众能够使用,而不仅仅是那些拥有最新硬件和浏览器的用户。
简而言之,PWA 应用应该是渐进增强
的,即应用的基础功能
在所有设备
上都可以使用,而一些高级功能
仅在特定支持
的设备和环境上才能使用。
最终用户眼中的 PWA 应用一例
学习了这么多理论知识,我们来看个实际的例子。我们在电脑浏览器打开某红书首页,在地址栏里能看到 Install
图标。
图2:将 PWA 安装到桌面运行环境的入口
点击之后,弹出询问安装的提示对话框:
图3:PWA 安装提示窗口
点击 Install 之后,桌面就会多出一个快捷方式:
图4:PWA 安装后在桌面生成的快捷方式
下次我们点击桌面这个快捷方式,就能像启动操作系统上安装的原生应用一样,打开某红书应用了。
这个应用想必大家每天都在使用,所以可以按照本文介绍的步骤,自己动手一试,以对 PWA 的运行方式有一个直观的认识。
那么对于一个 Angular 应用,我们应该如何开发,才能让其支持 PWA 特性呢?某红书应用的开发细节笔者不清楚,因此本文笔者使用我所在的开发团队,负责开发的代号为 Spartacus 的电商 Storefront 应用为例,向大家分享我们团队是如何让这个 Angular 应用支持 PWA 特性的。
下图是 Spartacus 应用在桌面浏览器打开,并添加到桌面快捷方式的步骤,可以看出同某红书的操作步骤是完全一致的:
图5:Spartacus Storefront 应用的快捷方式添加到桌面的步骤
Spartacus Angular 应用的 PWA 特性支持步骤
- 使用 Angular CLI 创建应用的时候,使用如下命令行,Angular CLI 会自动安装
@angular/pwa
这个库到当前的 Angular 项目中。@angular/pwa
这个库包含了必要的配置和文件,用于启用 PWA 功能。
ng add @angular/pwa --project spartacus
这个命令行会在 Angular 项目的 package.json
文件里引入对 @angular/pwa
库的依赖:
图6:Angular 应用里对 pwa 工具库的依赖
- 生成
ngsw-config.json
配置文件,并将该文件注册到angular.json
文件内。
图7:angular.json 对 ngsw-config.json 文件的注册
Spartacus 的 ngsw-config.json 包含的内容如下:
{
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html",
"/*.css",
"/*.js",
"/manifest.webmanifest"
]
}
}
],
"dataGroups": [
{
"name": "basesites",
"urls": [
"*/basesites?fields=baseSites\\(uid,defaultLanguage\\(isocode\\),urlEncodingAttributes,urlPatterns,stores\\(currencies\\(isocode\\),defaultCurrency\\(isocode\\),languages\\(isocode\\),defaultLanguage\\(isocode\\)\\),theme,defaultPreviewCatalogId,defaultPreviewCategoryCode,defaultPreviewProductCode\\)*"
],
"cacheConfig": {
"maxSize": 1,
"maxAge": "1d",
"strategy": "performance"
}
}
]
}
这个配置文件的核心部分讲解如下:
-
index
: 定义了服务工作线程 (Service Worker) 中的主页文件,表示在缓存策略中将会使用此作为主页文件。 -
assetGroups
: 定义了需要缓存的资源组。在这里,名为app
的资源组被定义。这里的name
属性是资源组的名称,用于标识和管理该资源组。installMode
表示资源的安装模式。在这个例子中,installMode
设置为prefetch
,表示在空闲时间预取资源。resources
属性包含了需要被缓存的具体资源。files
定义了要缓存的文件列表,这些文件包括/favicon.ico
,/index.html
, 以及所有以.css
和.js
结尾的文件,还有/manifest.webmanifest
。这些文件在服务工作线程启动时将被预先缓存。 -
dataGroups
: 这个部分定义了数据缓存的配置。这里的name
属性定义了数据组的名称。urls
定义了需要被缓存的 URL 模式列表。在这里,匹配所有包含特定查询参数的URL。cacheConfig
包含了有关缓存行为的配置信息。maxSize
定义了缓存的最大大小。在这个示例中,maxSize
设置为1,表示该缓存组的最大容量为1。maxAge
这个属性定义了缓存的最大时间长度。在这个示例中,maxAge
设置为1d
,表示缓存将在1天后过期。strategy
定义了缓存更新策略。在这里,strategy
设置为performance
,表示采用性能优化的策略进行缓存更新。
- 使用命令行
ng build --prod
进行构建,确保生成必要的文件,并且将 Service Worker 进行注册。
Service Worker 是一种运行在 Web 浏览器背后的脚本,它可以在客户端之间提供一种代理服务器的功能。它将网络请求拦截下来,并根据是否有可用的数据或者是否处于在线状态,来决定如何响应。
在传统的 Web 开发中,如果用户的网络断开,那么应用就无法正常运行。但是在 PWA 中,由于有了 Service Worker 的帮助,我们可以预先将一些静态资源如 HTML、CSS、JavaScript、图片等缓存到用户的设备上。当网络断开时,Service Worker 可以拦截网络请求,直接从缓存中获取这些资源,使得应用能够在离线状态下继续运行。
我们可以在 Chrome 开发者工具的 Application 面板,找到所有注册了的 Service Worker:
图8:Chrome 开发者工具里查看 Service Worker
- 在 pwa.module-config.ts 文件里,添加两个配置项:
export const defaultPWAModuleConfig: PWAModuleConfig = {
pwa: {
enabled: false,
addToHomeScreen: false,
},
};
默认情况下,Spartacus 的 PWA 特性处于关闭状态,也不支持将其在移动设备上添加到 home page.
如果客户想开启这两个功能,将上述两个 boolean 类型的标志位,设置为 true 即可。
修改标志位之后,重新构建应用,就能看到下图所示的添加应用到移动设备首页的提示窗口了:
图9:移动设备里添加 PWA 的提示窗口
总结
本文首先介绍了 Progressive Web Application 这种 Web 应用开发方式的基本理念和能够给终端用户带来的收益,接着以 Spartacus 这个 Angular 应用为例,介绍了 Angular 应用开启 PWA 支持的一般步骤,希望对有类似需求的 Angular 开发者有所借鉴意义。