PWA(Progressive Web App) 的概念相信很多人都不陌生,但真正去应用 PWA 的网站确是少之又少,而应用了 PWA 并不等于就是离线WebApp,很多网站虽然用了PWA,但也仅仅是为了加快网站打开速度,并没有完整的实现一个离线WebApp

离线WebApp,顾名思义,即使断网也能够正常使用的网页,会有点难以想象,可以亲自体验一下:https://geek4.wuchen.org ,打开过一次之后(iOS的webview暂不支持离线,需要使用safari打开),再次打开不需要网络,使用上也不会有阻碍。上述网站只是一个demo,这是合合信息第四届极客大赛题目,做一个支出管理的App,可以扫描票据自动录入信息。

如何做一个离线WebApp?

这个问题有点太大,没办法用一句话来回答,我们做一下拆分。

  • 如何离线document请求?
  • 如何离线css、js、图片、字体等资源请求?
  • 如何使用浏览器本地存储?
  • 如何设置App的名字和logo?
  • 如何实现消息推送?

通常打开一个网页,浏览器会先从服务器下载一个document文档,然后下载对应的js和css资源,可能还会有图片或者字体等资源,最后会发出ajax请求获取数据来展示页面。如果要做离线WebApp,ajax请求则可以放弃,通常使用浏览器来存储用户数据,这有点像是在开发单机游戏。

如何离线document请求?

第一印象可能是 Http Cache,采用max-age等强制缓存,但之前文章也说过,这种存储方式一般只能设置30天的最长时间,超过30天会变成永久缓存,你的网页可能会永远失去控制。采用强制缓存的缺陷是,无法实时更新,只能等缓存到期之后才能从服务器获取新版本。

我们需要引入 service worker 的概念。service workerweb worker 的一个变种,web worker 是主线程之外的另一个线程,可以用来执行一些复杂且耗时的操作,service worker 也是一个线程,但它可以让开发者控制主线程的所有网络请求,类似于 nginx 的反向代理。利用 service worker ,我们可以将document请求缓存下来,下次请求,则从缓存中读取,而且它自带更新机制。

如何离线资源请求?

同样的,service worker 也可以帮我们缓存资源文件,而且可控性比 Http Cache 强制缓存要更好。

<html>
  <head>
    <title>找到</title>
  </head>
  <body>
    <script src="app.12345.js"></script>
  </body>
</html>

上面这个document,依赖一个12345版本的app.js,只要document不更新,那相应的依赖的资源也不会变化。所以资源一般是跟随document一起缓存的,这样整个站点都被缓存下来,也就实现了离线WebApp的基础框架。

如何使用浏览器本地存储?

浏览器本地存储有以下几种:

  • cookie: 这个一般是与服务器交互的时候会用到,每一个请求都会携带cookie信息
  • localStorage: 本地存储一些简单key-value的信息,但容量有限,一般为2M上限
  • sessionStorage: 同上,唯一区别是,localStorage 是永久缓存,而 sessionStorage 是本tab才有效
  • IndexDB: 浏览器端的数据库,属于NoSQL类型,非关系型数据库,与MongoDB类似,可以存储大量数据,只要硬盘够用
  • Cache Storage: 专门为 service worker 提供的本地存储,常用于请求的缓存,get与post都能缓存

离线WebApp,除了cookie,基本都会用到。

如何设置App的名字和logo?

我们会用到一个 manifest.json 的配置文件,在原生应用开发中,清单配置文件很常见,在web上也有这么一套规范,可以让开发者给自己网站设定名字、logo、启动路径等信息。

如何实现消息推送?

消息推送在国内暂时无法实施,因为依赖浏览器推送服务。国产浏览器基本不支持 Web Push 机制,chrome支持,但却依赖google,因GFW的问题,我们无法使用google服务。

总结

本文只是离线WebApp这个系列的一个开始,后面将围绕着这几个问题进行展开,最终实现开头给的demo网站。

参考

https://web.dev/progressive-w...


找到Web
66 声望54 粉丝

专注于w3c标准,先定一个小目标,日更一篇,近期主要关于前端性能优化方面