PWA应用与Service Worker
本文最后更新于 2024年6月17日 凌晨
什么是PWA应用
PWA: Progressive Web Apps,渐进式 Web 应用
简单来说, 就是一种允许用户将web页面作为应用程序安装的技术。
一方面,Web 应用更加易于发现:相比于安装应用,访问一个网站显然更加容易和迅速。你还可以通过链接来分享 Web 应用。
另一方面,原生应用与操作系统可以更加完美的整合,也因此为用户提供了无缝的用户体验。你可以通过安装应用使得它在离线的状态下也可以运行;相较于使用浏览器访问,用户也更喜欢通过点击主页上的图标来访问它们喜爱的应用。[2]
当你打开一个网站时, 最能直观展示他是不是PWA的就是看chrome会不会弹出一个"安装"按钮
什么是Service Worker
Service Worker 是浏览器和网络之间的虚拟代理。 它们终于解决了前端开发人员多年来一直在努力解决的一些问题,其中最值得关注的是,解决了如何正确缓存网站资源并使其在离线时可用的问题。
Service Worker 运行在一个与页面 JavaScript 主线程独立的线程上,并且无权访问 DOM 结构。这引入了一种与传统 Web 编程不同的方式:它的 API 是非阻塞的,并且可以在不同的上下文之间发送和接收信息。您可分配给 Service Worker 一些任务,并通过基于 Promise 的方法在任务完成时收到结果。
它不仅仅提供离线功能,还可以做包括处理通知、在单独的线程上执行繁重的计算等事务。Service workers 非常强大,因为他们可以控制网络请求、修改网络请求、返回缓存的自定义响应,或者合成响应。[1]
简单来说, Service Worker就是一个位于浏览器和互联网间的代理, 可以拦截, 处理, 缓存HTTP请求, 同时可以实现通知推送和离线缓存
一个详细的angular实现service worker通知的教程
https://blog.angular-university.io/angular-push-notifications/
Angular创建一个pwa应用
之前一段时间我写了一些前端的小demo并作为一个工具合集放在一个网站里:
下面展示一下以Angular为例, 创建一个pwa应用的过程, react和vue框架使用的更加广泛, 应该也有相应的配置
以下内容主要参考angular官方文档, 加上个人的一些实践的理解和踩坑, 内容可能会因angular版本不同而有所不一致, 可参考: https://angular.cn/guide/service-worker-getting-started
安装angular/pwa
注意pwa一定要安装对应angular-cli版本的
具体可以参考https://www.npmjs.com/package/@angular/pwa
选择对应tag的版本, 如我的angular-cli是v9, 则使用下面的方式安装:
1 |
|
这一步会进行如下操作:
- 把 @angular/service-worker 添加到你的项目中。
- 在 CLI 中启用 Service Worker 的构建支持。
- 在应用模块中导入并注册 Service Worker。
- 修改
index.html
文件:
- 包含要添加到
manifest.webmanifest
文件中的链接。- 为
theme-color
添加 meta 标签。- 创建图标文件,以支持安装渐进式应用(PWA)。
- 创建一个名叫
ngsw-config.json
的 Service Worker 配置文件,它会用来指定缓存的行为以及其它设定。[4]
我们观察nsgw-config.json
:
1 |
|
这是一个指定缓存的配置文件, 该文件表示浏览器将离线缓存这些内容:
index.html
favicon.ico
- 构建结果(JS 和 CSS 包)
assets
下的一切- 图片和字体直接位于所配置的
outputPath
(默认为./dist/<project-name>/
) 或resourcesOutputPath
下。关于这些配置的更多信息,请参阅ng build
。
到这里, 我们就可以重新ng build
构建我们的项目, 注意:
**ng serve
**并不会使项目工作在service worker模式下, 需要使用一个独立的http服务器在本地测试, 可以使用npm的http-server
包:
1 |
|
这时就可以在本地愉快地测试你的pwa应用了!
发布
我的 https://tools.roccoshi.top/ 基于github pages, 这里给出一个发布的参考
1 |
|
这里注意构建的产物不一定在dist/<project-name>/browser
中, 这里是因为我设置了app-shell
, 如果没有使用app-shell
构建的产物应该就在dist/<project-name>
中
等github action构建完毕后打开页面:
就可以发现支持安装啦~
可以直接在windows菜单栏打开, 也可以拖到桌面之类的, 本质还是一个浏览器页面
如果你使用edge, 还可以在设置 => 应用
管理安装的PWA应用程序
解决刷新后404的问题
上面的发布我遇到了一个棘手的问题, 导致卡了很久, 这个问题来源于浏览器的两种路由模式:
- hash(#)模式
- history模式
hash模式的url大概长这样: https://abc.com/#/page
history模式的url大概长这样: https://abc.com/page
angular默认使用的路由模式就是history模式, 但是在pwa中会导致一个问题:
如果你直接基于路由访问一个页面, 而不是先访问主页, 会404错误:
比如你直接访问
https://tools.roccoshi.top/code-comparison
而不是由https://tools.roccoshi.top
导航而来, 会直接报404
我找到的相关的issue:
- https://github.com/angular/angular/issues/22023
- https://stackoverflow.com/questions/59580289/angular-8-angular-pwa-routing-doesnt-work-with-direct-url
目前我也不清楚原因具体出在哪, 我觉得并不是路由模式的问题, 应该是哪个配置项出错了.
不清楚原因, 而且也极难搜到完全正确的解决方式, 我怀疑是路由或PWA配置的某个地方出现了问题, 最终尝试换成hash模式的路由, 也就是将:
1 |
|
更换为
1 |
|
就可以正常直接访问子路由页面了
关于PWA应用的看法
这篇文章: 小程序鼻祖 —— 在国内逐渐消亡的 PWA 可以带给我们哪些启示? - SegmentFault 思否我觉得说的很好
由于中国的特殊性,PWA 的前景在一定程度上比较悲观:
- 国内较重视 iOS,而 iOS 目前还不支持 PWA。
- 国内的 Android 实为「安卓」,不自带 Chrome 是一,可能还会有其他兼容问题。
- 国内厂商可能并不会像三星那样对推动自家浏览器支持 PWA 那么感兴趣。
- 依赖 GCM 推送的通知不可用,Web Push Protocol 还没有国内的推送服务实现。
- 国内 webview 环境较为复杂(比如微信),黑科技比较多。
由于浏览器的限制, 兼容性的问题, 以及国内移动网络的高度普及化, PWA在我国市场注定是不会再火起来了, 所以这篇文章纯属了解和娱乐, 具体的技术栈我也不打算深入研究了~