pwa实践

pwa最近很热门,搜了下发现平台上并没有一篇pwa相关的文章,决定介绍下pwa,并就当下如何拥抱该技术的实践。

什么是pwa呢?一开始是Google推销的一个技术包装,用于构建匹配native体验的web app,其实不是新的东西。但技术包装也是很重要的,技术能够发展重要的是要构建生态,用户、开发者、公司都能参与进来。
pwa的核心技术是service worker,以前只有chrome支持,最近微软edge和safari preview也开始支持,所以现在是时候认真考虑在网站引入service worker。
本人初次接触service worker,也不大明白跟http cache的区别,除了离线后使用service worker还能显示网页,但也好像没多大用处如果离线的话。后来才明白了,pwa的一个关键词是reliable,也就是可靠性。
网络环境是复杂脆弱的,用户经常会切换场景,比如进入电梯,进入隧道或地铁,网络会不那么流畅,这个时候如果使用service worker就能检测到弱网环境并及时fail,然后取出缓存给用户。是不是觉得很有用。
下面介绍一些具体的实践。

1. https
站点必须首先引入https,为了安全,这是使用service worker的前提条件的。

2. 添加到屏幕
这个功能很好实现,需要在您的网站中添加一个包含您的应用详细信息的网络应用清单文件。
Web App Manifest Generator 这个工具可以帮助生成manifest。
当然是否提示添加到屏幕是由浏览器决定的,需要用户在两天访问两次。

3. workbox
service worker提供的api是比较底层的,如果google的workbox库提供友好的api,实现了常用的缓存策略。

缓存优先
适合图片资源,会优先从缓存中取。

workbox.routing.registerRoute(
  /\.(?:png|gif|jpg|jpeg|svg)$/,
  workbox.strategies.cacheFirst({
    cacheName: 'images',
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
      }),
    ],
  }),
);
有些图片比如封面图,如果缓存中没有,可以提供个默认图
const FALLBACK_IMAGE_URL = '/images/fallback.png';
const imagesHandler = workbox.strategies.cacheFirst();
worbox.routing.registerRoute(new RegExp('/images/'), ({event}) => {
  return imagesHandler.handle({event})
    .catch(() => caches.match(FALLBACK_IMAGE_URL));
});


网络优先
适合比如评论列表等请求,优先从网络中获取,如果失败,则从缓存中获取。
workbox.routing.registerRoute(
    ‘\.(?:json)$’,
    workbox.strategies.networkFirst({
        networkTimetoutSeconds: 3,
        cacheName: ‘JSONApi’,
        plugins: [
          new workbox.expiration.Plugin({
            maxEntries: 50,
            maxAgeSeconds: 5 * 60, // 5 minutes
          }),
        ],
    }),
);

staleWhileRevalidate
这种策略是,优先从缓存中取,但同时会去请求网络获取最新的更新缓存,适用于那些内容不会频繁改动的数据。
workbox.routing.registerRoute(
  /.*(?:googleapis|gstatic)\.com.*$/,
  workbox.strategies.staleWhileRevalidate(),
);

workbox-webpack-plugin
有了这个插件,webpack生成的资源文件都会被添加到precache列表。webpack构建随着代码的改动,生成的文件也不一样,这个插件会记录下当前构建的文件和上次构建之间的差异,然后从缓存中移除那些不再需要了的文件。

app shell
app shell架构是构建 Progressive Web App 的一种方式,使用service worker缓存初始HTML,快速呈现到屏幕,然后渐进加载渲染其他内容,这样的好处是用户不用对着白屏发呆。
这里需要注意,初始HTML不要包含动态内容,而只包含页面框架。这块会涉及到服务器端渲染或者同构渲染,就不深入了。最简单的是只包含loading态。
以上都可以无缝地引入到现有产品中,但还有些pwa的特性是否引入就需要和产品沟通了。

1. background sync
比如你发表了个评论,但这时你进入了电梯,网络不太好,OK,你关掉手机,等走出电梯后,打开手机你会看到提示说发送失败,然后你需要重新点击发送。
其实这样也ok,用户也可以接受,但如果用户走出电梯后手机有了稳定的网络,打开手机后看到的是评论发布成功,那就是更棒的体验。
我们可以先把需要发送的评论内容存到本地,比如indexedDB,手机有了稳定的网络会触发sync事件,从indexedDB取出要发送的评论发送。

2. push notification
消息推送,最大的障碍是,现在产品的kpi都是以客户端为主的,如果真的加了消息推送,对app的下载会有一定副作用。
注意点
1. sw.js文件要设置成无缓存
2. 比如有个活动路径是/activity/evol/,sw.js存放在/activity/evol/sw.js,那么scope为/activity/evol/,如果用户通过/activity/evol访问,service worker是不起作用的,这种情况需要redirect到/activity/evol/
ok

参考文档
https://developers.google.com/web/progressive-web-apps/
https://www.youtube.com/watch?v=z2JgN6Ae-Bo

本文来自网易实践者社区,经作者蒋云唬授权发布。