渐进式 Web 应用:离线

1. 欢迎

在本实验中,您将使用一个现有的 Web 应用,并将其设置为可离线使用。这是一系列关于渐进式 Web 应用研讨会的配套 Codelab 中的第一个。本系列中还有 7 个 Codelab。

学习内容

  • 手动编写 Service Worker
  • 将 Service Worker 添加到现有 Web 应用
  • 使用 Service Worker 和 Cache Storage API 将资源设为可离线使用

注意事项

  • 基本 HTML 和 JavaScript

所需条件

2. 进行设置

首先,克隆或下载完成本 Codelab 所需的起始代码:

如果您克隆了代码库,请确保您位于 starter 分支上。该 ZIP 文件中还包含该分支的代码。

此代码库需要 Node.js 14 或更高版本。获得代码后,从命令行的代码文件夹中运行 npm ci,以安装您需要的所有依赖项。然后,运行 npm start 来启动此 Codelab 的开发服务器。

源代码的 README.md 文件会为所有分布式文件提供说明。此外,下面是此 Codelab 中您将会用到的主要现有文件:

密钥文件

  • js/main.js - 主应用 JavaScript 文件
  • service-worker.js - Application 的 Service Worker 文件

3.离线测试

在进行任何更改之前,请先测试一下,看看 Web 应用目前是否无法离线使用。为此,请让我们的计算机处于离线状态,然后重新加载 Web 应用,如果您使用的是 Chrome,请执行以下操作:

  1. 打开 Chrome 开发者工具
  2. 切换到“应用”标签页
  3. 切换到“Service Worker”部分
  4. 选中“离线”复选框
  5. 刷新页面而不关闭 Chrome 开发者工具

已打开“Chrome 开发者工具应用”标签页,其中的“离线工作”复选框已选中

在测试了网站但未能成功加载离线数据后,接下来该添加一些在线功能了!取消选中离线复选框并继续执行下一步。

4.离线保存

是时候添加基本的 Service Worker!此过程将分两步进行:注册 Service Worker 和缓存资源。

注册 Service Worker

您已经有一个空的 Service Worker 文件,因此,请确保显示更改,让我们在应用中注册该文件。为此,请将以下代码添加到 js/main.js 的顶部:

import swURL from 'sw:../service-worker.js';

// Register the service worker
if ('serviceWorker' in navigator) {
  // Wait for the 'load' event to not block other work
  window.addEventListener('load', async () => {
    // Try to register the service worker.
    try {
      const reg = await navigator.serviceWorker.register(swURL);
      console.log('Service worker registered! 😎', reg);
    } catch (err) {
      console.log('😥 Service worker registration failed: ', err);
    }
  });
}

说明

只有在页面加载后,以及网站支持 Service Worker 时,此代码才会注册空的 service-worker.js Service Worker 文件。

预缓存资源

为了使 Web 应用能够离线工作,浏览器需要能够响应网络请求并选择路由目的地。为此,请将以下内容添加到 service-worker.js

// Choose a cache name
const cacheName = 'cache-v1';
// List the files to precache
const precacheResources = ['/', '/index.html', '/css/style.css', '/js/main.js', '/js/app/editor.js', '/js/lib/actions.js'];

// When the service worker is installing, open the cache and add the precache resources to it
self.addEventListener('install', (event) => {
  console.log('Service worker install event!');
  event.waitUntil(caches.open(cacheName).then((cache) => cache.addAll(precacheResources)));
});

self.addEventListener('activate', (event) => {
  console.log('Service worker activate event!');
});

// When there's an incoming fetch request, try and respond with a precached resource, otherwise fall back to the network
self.addEventListener('fetch', (event) => {
  console.log('Fetch intercepted for:', event.request.url);
  event.respondWith(
    caches.match(event.request).then((cachedResponse) => {
      if (cachedResponse) {
        return cachedResponse;
      }
      return fetch(event.request);
    }),
  );
});

现在,返回到浏览器,关闭预览标签页,然后重新打开。您应该看到与 Service Worker 中的不同事件相对应的 console.log

接下来,请再次离线并刷新网站。即使您处于离线状态,也能看到加载成功!

说明

在 Service Worker 的安装事件期间,使用 Cache Storage API 打开命名的缓存。然后,使用 cache.addAll 方法将 precacheResources 中指定的文件和路由加载到缓存中。这称为“预缓存”,因为它在安装期间会预先缓存文件集,而不是在需要或请求时缓存文件。

在 Service Worker 控制网站后,请求的资源会像代理一样通过 Service Worker。每个请求都会触发提取事件,在此 Service Worker 中,在缓存中搜索匹配项(如果有),并返回缓存的资源。如果不匹配,则会正常请求资源。

通过缓存资源,应用可以避免网络请求,从而离线工作。现在,该应用在离线时也能响应 200 状态代码!

5. 恭喜!

您已了解如何使用 Service Worker 和 Cache Storage API 使 Web 应用处于离线状态。

本系列的下一个 Codelab 是使用 Workbox