Day19 X Application Shell Architecture

昨天介绍 Service Workers 後我们知道它是 PWA 的要素之一,且也是让 Web App 实现离线浏览的关键技术。今天我们将延伸昨天的知识,介绍 Application Shell Architecture 这个架构,并看看它能为网页效能带来什麽样的优化。

What is Application Shell Architecture ?

Application Shell (App Shell) 是建构 PWA 的要素之一,除了提升使用者体验与载入速度外,也是实现离线浏览的一个关键。

不知道读者有没有在离线的时候分别点开 Web App 与 Native App 的经验,通常 web 如果没有特别做处理的话,一般会显示 network error,使用者基本上什麽内容都看不到,且也没办法操作页面。而 App 在这方面的行为就不太ㄧ样了,虽然有些 App 仍然会限定一定要有网路才能操作,不过大部分的 App 应该都还是能正常开启,即使很多操作都没办法在离线进行,至少使用者还是可以看到画面或是看到之前的操作记录,离线状况的使用者体验可以说是大胜 Web。

而 App Shell 就是让 Web 也能达成这件事的技巧。

所谓 App Shell 指的是把 UI 上一些不常变动的部分 (例如 navbar, footer) 与需要动态抓取的部分(Dynamic Content)拆分开来,App Shell 在下载後可以存到 Service Workers 的快取里,之後再次请求页面时就可以迅速显示快取的内容,并且在网路状况不佳甚至离线时也可以从快取显示 App Shell 的内容。

如果以 Native App 的角度来思考,App Shell 就很像在 Native App 中被开发并上架到 App Store 或是 Google Play 的核心程序码,即使没有网路,使用者仍然可以看见 App Shell 的建立出的骨干画面,剩下的内容都是透过网路请求动态去抓取。

总结一下,App Shell 应该要可以达到以下的功能与特性:

  • 快速载入
  • 将动态资料抽离
  • 从快取中载入静态资源

切分出 App Shell 架构

App Shell 的概念不难,但是在切分 App Shell 与 Dynamic Content 时要格外谨慎才能发挥最大的效益。

一般来说,设计 App Shell 时会考量到以下特点:

  • App Shell 越简单越好
  • 要包含足够有意义的页面内容
  • 为了使用者体验,可以包括一些 placeholder 之类的元件

就以 Google 推荐的离线版维基百科为例为例,我使用 DevTool 模拟了一下 offline 时网站的显示状况

可以推测出 App Shell 的内容应该包括上方的搜寻栏位与下方灰色的 body。

至於 Dynamic Content 也是可以放到快取中以便 offline 时使用者可以继续浏览已经载入过的内容以提升使用者体验,不过这麽做的话就要注意资料新鲜度的问题,要尽量做到网路连线恢复时能让使用者看到最新版的资料。

以这个离线版本的维基百科来说,它会把之前动态载入的 JSON 档案也放到 Service Workers 快取中,以便离线时也能够浏览。

App Shell 对网页效能的影响

采用 App Shell 架构在第一次渲染时会需要比较久的时间,因为需要在浏览器注册 Service Workers 并且将属於 Shell 的静态资源放到 Services Workers 的 Cache 里,不过之後的请求因为可以从 Cache 立即显示 Shell 的元件,所以会有较快的 First Meaningful Paint (FMP),之後再靠 Ajax 的方式抓取动态的资料并渲染到画面上。

这个方式也让使用者的「感知效能」提升,虽然使用者还是必须等待动态资料回传後才能操作网页,但我们却可以利用一些小技巧让使用者可以先看到部分画面,降低等待页面的痛苦。

关於 App Shell 对於载入时间的影响可以参考 Google 在 3G 网路环境下做的实验。

什麽状况适合采用 App Shell 架构?

当页面有许多动态内容时采用 App Shell 架构去拆分出静态 Shell 与动态内容会比较有意义,如果网站规模很小或是内容基本上都是静态的话,采用 App Shell 会有点失去意义,毕竟如果都是静态内容,整个网站 build 完後都可以放到快取中。

遇到不支援 Service Workers 的浏览器怎麽办?

在一些比较旧浏览器或是比较轻量级的浏览器例如在东南亚十分流行的 KaiOS 就还没有支援 Service Workers,那这时候该怎麽办呢?

还记得在昨天 Day18 的内容有提到 Service Workers 的 Cacahe 应该要跟 HTTP Cache 彼此搭配吗?透过设置 HTTP Cache Control 的 header,就可以让没有支援 Service Workers 的浏览器仍然能透过 Browser Caching 保障一定的效能体验。

本日小结

今天的内容虽然跟其他篇相比稍嫌简短(明天又会恢复长篇大论来折磨读者了XDD),但我认为还蛮受用的。虽然 PWA 可能不像一开始推出时所说的可以取代 Native App (至少在 iOS 那麽多功能不支援的状况下是不太可能的),但其实 PWA 本身就不是一个明确的技术,而是一个渐进式的概念,许多支援相对完整的功能是值得学习与套用在的专案上的,离线浏览就是其中一个非常重要的功能。

透过 App Shell 架构,让使用者有机会在没有网路连线时也能够保有最低限度的使用者体验,并且也透过快取加快了页面的载入速度。如果网站的内容可以明确分为动态的内容与静态的「壳」,就十分推荐可以试试看采用 App Shell 架构喔!

至於如何实作 App Shell 架构,其实结合昨天与今天两篇文章读者应该就能自行推敲出作法,如果想要更完整的教学,可以参考 Google 关於 Offline Web App 的 Lab

到目前为止介绍了 Browser Cache 与 Service Workers Cache 两种快取,但你以为两层防护就是极限了吗?还有!明天将介绍 Web 开发者不可以不知道的技术 - CDN,我们明天见。

Referneces & 图片来源

https://developers.google.com/web/fundamentals/architecture/app-shell?hl=zh_tw

https://developers.google.com/web/showcase/2016/iowa2016?hl=zh_tw

https://developers.google.com/web/updates/2015/11/app-shell


<<:  Day 22 - 运算过载,warning ! warning !

>>:  Day 22:开始来学资料系结:属性系结(一)

从零开始用github架设静态网站入门(5) - 部署到Github Pages

GitHub Pages是GitHub提供的一个网页代管服务,虽然是限制我们只能使用静态网站的功能,...

【Day13】[资料结构]-二元树Binary Tree

二元树(Binary Tree)是最广泛被使用的树状资料结构,简单来说即为每个节点最多只能有两个子节...

有线上网:ADSL、Cable Modem 和光纤网路差在哪里?

知道了 ISP 所提供的服务後,我们来深入一点聊聊这些服务的基本原理,以及差别在哪里吧! 依序来看看...

第二十三天:再探 Gradle Plugin

今天要继续撰写 Gradle Plugin,我们会延续昨天的范例 - 档案差异比对 Plugin。 ...

16. HTTP request methods ( 下 )--- PUT vs. PATCH

延续昨天的文章15. HTTP request methods ( 上 )--- GET vs. P...