6

在 Twitter 上看到 Addy Osmani 发的视频被狂转, 开始注意
https://twitter.com/addyosmani/status/734753297274306561
https://speakerdeck.com/addyosmani/progressive-web-apps-across-all-frameworks
之前几乎对这个词语没有印象, 看到是在 IO 的演讲还以为是新技术
在 Youtube 上找一下, 这次好多个视频是关于 Progressive Web Apps 的
视频的内容主要是讲网站优化, 分别用 React, Angular, Ember 做例子
可惜没有 Vue, 大概要等小右补... 方案应该没有问题
从视频看, 优化的效果非常显著, 本来好几秒的应用能优化到一秒内.. 很夸张
所以仔细了解了一下怎么回事, 现在大概了解

视频里给的优化方案大概分成几个步骤(细节还要看视频确认):

  • 添加 manifest.json 文件, 生成 Android 主屏打开的网页加载页面

  • 编写 Service Worker 脚本处理缓存, 更快读取缓存

  • 服务端渲染, 用 App Shell 带来效果, 然后动态加载

  • 启动过程 JavaScript 代码的性能优化

虽然是新技术, 但文档可以追溯到一年前甚至一年半以前
Service Worker 在 2014 年底就在 HTML5 Rocks 上介绍了
manifest.json 的识别功能在 Chrome 39 已经加入
App Shell 仅仅是模板渲染略过动态内容的一个优化
前两个 API 整体上是 Chrome 支持, 所以兼容性问题较大
那么 Google 既然在大会上推, 说明方案已经比较成熟值得深入了

Progressive Web Apps(PWA)

简称 PWA 吧, 名字是从 Android Chrome 的"添加到主屏幕"开始的

2015 年六月份的文章, 第一次有了这个提法, 针对这类应用
网页应用在这样的场景下和移动应用很相似了, 可以从主屏打开
而且, 能快速地加载, 可以跑后台进程, 加密的连接, 离线使用等等

到了年底的时候 Addy Osmani 发了文章, 大致上已经是前面演讲的内容了
首先是渲染 App Shell 也就是页面的框架, 给用户更好的加载体验
而且可以通过 Service Worker 来做 App Shell 渲染, 去掉网络请求的时间
然后再动态地请求更多内容, 填充数据. 整体上看的加载速度会变快

2015 年底还有个 Google Developer Summit, 我以前都没注意到
据说大会上 PWA 已经名声很大了, Medium 上专门介绍了一下

演讲视频的话, YouTube 上几个大会录的演讲都挺丰富的:
https://www.youtube.com/results?search_query=progressive+web+apps

现在已经有做了不少的 PWA 的 Demo 了, 比如第一个 washingtonpost

Web App Manifest

manifest.json 前面说了, 加进来挺久了, 主要是为了添加 Splash Screen

根据 manifest.json 可以自动生成一个网页(主屏幕按钮打开)的启动界面
这样看上去就很像一个 Native App 了, 包含图片, 文字, 背景

我尝试的时候主要是图片遇到了问题, 128dp 对应最小要求 192px
我当时图片太小了结果很久没显示出来, 到文档上才发现
详细的 manifest.json 内容可以在下面一些界面找到

Service Worker

Service Worker 可以简单理解成跑在网络请求的拦截器
或者当做是 Nginx, 它可以监听页面的请求, 判断返回什么内容
它可以通过 Cache 处理本地的缓存, 也可以用 fetch 抓线上的资源


另外演讲视频还有介绍处理消息推送功能, 类似离线收发消息, 还没细看.
关于 API 使用需要深入看文档, 已经有很详细的介绍了:

Google 提供了一些类库, 能实现 Express.js 风格的简化写法:

具体的浏览器兼容性可以看:

关于调试, Google Chrome 试验版本已经更新了 Application Tab
其中 Service Worker 被放到了显眼的位置, 不过, 功能多了还是挺复杂的
另外下面这些链接会有帮助:

其他

另外了解和尝试 Demo 的时候我也想到一些跟自己项目比较相关的内容

React Native 对比

很 RN 一样这套方案能让网页应用在效果上更接近原生应用
PWA 主要是处理应用加载部分, 让应用能离线打开, 启动过程跟 App 一样变快
因此原来寄托在 RN 的功能已经能做到了, 离线, App 启动界面
我正在考虑把我以前某个 Demo 重写, 看下能有多像 App 的体验

React 相关的尝试

从前简聊优化应用启动用过本地存储整个 Store 数据的办法
普通页面 App Shell 不错了, 而 React 应该能做整个页面放 Service Worker
或者说, Store 放进 Service Worker 里, Virtual DOM 也放进去
那么网页主线程其实只有 DOM 操作部分的代码, 可能启动速度能提升非常大
而且 React 已经有把 DOM Diff 放进 Worker 的尝试, 还可以延伸下

整个这样想, 对 React 应用的整体架构改变将会挺大的
而 Angular, Vue 之类的框架应该也会做类似的架构调整

Service Worker 代码打包问题

文档里的 Demo 对应的 sw.js 代码都是的直接用链接加载的
我们搭配 CDN 使用当有打包以及 revision 方便的考虑
这就要求打包工具要对 service worker 的语法做良好的支持
Webpack 有看到相关的 PR 提交对应的功能, 其他工具不了解:
https://github.com/webpack/worker-loader/pull/14

项目代码引用 sw.js 的写法:

navigator.serviceWorker.register('/sw.js')

sw.js 内部再引入其他代码的写法:

importScripts('serviceworker-cache-polyfill.js');

可能的话还需要把 CommonJS ES6 模块打包进去, 会挺复杂的
以及局部更新, 热替换之类的开发环境的打包方案改进等等

HTTPS

有点意外, 似乎之前 iOS 有做过强制 HTTPS? 我第一次遇到
Service Worker 运行要求网站是 HTTPS 或者 localhost
这样的话本地开发, Android 上做 remote debugging 会有些不便
我找的办法是直接在本地 Nginx 配置不安全的证书来方便开发的:
https://serversforhackers.com/video/self-signed-ssl-certificates-for-development
比较直接的办法当然是找个有域名的服务器然后用 HTTPS 开发

fraserxu教了我一招, 回头试试, 可以用 https://ngrok.com/
把本地的端口监听转化成一个在线的 HTTPS 地址...

小结

考虑缓存处理上带来的速度提升, 我对 PWA 整套方案很看好
而且之前的 HTML5 应用缓存来说, PWA 的自由度和体验都改进了很多
所以会逐渐开始考虑现实往这方面做迁移的思路:

  • 兼容性: 目前主要 Safari 不支持, 而 Chrome 方面已经比较成熟, 国产浏览器就...

  • 工具链: 调试工具已经不错, 打包和局部更新还要等待技术支持

  • 缓存方案: API 和语法糖都有了, 虽然代码比较啰嗦但是抄代码可以比较快

  • 动态数据方案: 动态的数据怎么抓取和推送, 还不大了解, 不过 Google 有演示过一些

做到这些基本上已经可以对页面的加载过程做不小的优化了
等待出更多的 Demo 以及大网站公布试验的数据如何...

未来的更多代码被放进 Service Worker 之后, 带来的改变会更大一些
最后贴一张图片膜拜一下前端的复杂度:


https://twitter.com/sstephenson/status/730039913052176384


题叶
17.3k 声望2.6k 粉丝

Calcit 语言作者