JackAtlas

Command Palette

Search for a command to run...

第七章 离线浏览 - 《Progressive Web Apps》读书笔记七
over 7 years ago
前端开发

第七章 离线浏览 - 《Progressive Web Apps》读书笔记七

7.1 解锁缓存

在没有网络时,用户尝试访问 Web 应用,Service Worker 能拦截 HTTP 请求,返回用户要查看的页面的缓存版本。

7.2 提供离线文件

↓ 将离线页面添加到 Service Worker 缓存中

const cacheName = 'offline-cache'
const offlineUrl = 'offline-page.html'

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(cacheName).then(function (cache) {
      return cache.addAll([offlineUrl])
    })
  )
})

↓ 当用户没有连接时提供离线页面

self.addEventListener('fetch', event => {
  if (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html')) {
    event.respondWith(fetch(event.request.url).catch(error => {
      return caches.match(offlineUrl)
    }))
  } else {
    event.respondWith(fetch(event.request))
  }
})

↓ 如果资源没有存储在缓存中,则降级成默认的离线页面

const cacheName = 'latestNews-v1'
const offlineUrl = 'offline-page.html'

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(cacheName)
      .then(cache => cache.addAll([
        './js/main.js',
        './js/article.js',
        './images/newspaper.svg',
        './css/site.css',
        './data/latest.json',
        './data/data-1.json',
        './article.html',
        './index.html',
        offlineUrl
      ]))
  )
})

self.addEventListener('fetch', event => {
  event.respondWith(caches.match(event.request).then(function (response) {
    if (response) return response

    var fetchRequest = event.request.clone()

    return fetch(fetchRequest).then(function (response) {
      if (!response || response.status !== 200) return response

      var responseToCache = response.clone()
      caches.open(cacheName).then(function (cache) {
        cache.put(event.request, responseToCache)
      })

      return response
    }).catch(error => { // 如果由于任何原因 fetch 事件失败,就检查用户是否跳转至其他页面并且请求的是 HTML 网页
      if (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html')) {
        return caches.match(offlineUrl) // 返回在 Service Worker 安装阶段存储在缓存中的离线页面
      }
    })
  }))
})

上一段代码永远会先从缓存中寻找资源,如果缓存中找不到,才会转而去发起请求。如果它无法通过网络来获取下一个网页,又会降级成缓存的离线页面。

7.3 几个需要注意的问题

是否需要在 Service Worker 安装期间将整个网站缓存?

当提供离线功能时,请考虑用户需求及用户量。用户是如何访问你的网站的?他们是否需要一次下载完整个网站,或者当它们访问某个新页面时再去获取?

7.4 缓存是非永久性的

每个站点都具有一定量的可用空间,这些空间可以与其他所有基于 Web 的存储器(LocalStorage、IndexedDB 和设备上的文件系统)共享。

7.5 离线用户体验

var offlineNotification = document.getElementById('offline')

function showIndicator() { // 当用户离线时,此函数用来显示离线通知
  offlineNotification.innerHTML = 'You are currently offline.'
  offlineNotification.className = 'showOfflineNotification'
}

function hideIndicator() { // 当用户再次上线时,此函数用来隐藏离线通知
  offlineNotification.className = 'hideOfflineNotification'
}

window.addEventListener('online', hideIndicator)
window.addEventListener('offline', showIndicator)

7.6 跟踪离线使用情况

如果用户处于离线状态,则无法使用传统的 Web 分析方法来跟踪它们。在没有网络连接的情况下,分析请求将无法发出,用户的操作行为将会丢失。

Google 的开源工具库 Workbox 提供了一个叫 googleAnalytics 的离线分析工具。当用户离线时,这个库会将所有分析请求放入队列中等候,一旦用户重新连接网络,会将队列中的请求发送到分析服务器。