发布于 2026-01-06 0 阅读
0

通过 Workbox 和 Service Workers 开始构建渐进式 Web 应用程序

通过 Workbox 和 Service Workers 开始构建渐进式 Web 应用程序

作者:Nic Raboy ✏️

渐进式 Web 应用程序由许多方面构成,例如移动友好的用户体验 (UX)、原生桌面和移动 API 集成,或者无需互联网连接即可使用该应用程序。

在本教程中,我们将探讨如何使用Workbox生成的服务工作线程使 Web 应用程序能够离线工作。Workbox 是一款旨在大大简化缓存的工具。

LogRocket 免费试用横幅

如果你之前从未接触过 Service Worker,它其实是浏览器在后台运行的一段脚本,可以实现一些无需网页或用户交互的功能。问题在于,即使 Service Worker 的 API 并不难用,设计起来也可能很棘手。这是因为你必须考虑很多情况,例如缓存过期、更新等等。正因如此,像Workbox这样的框架在开发过程中才能发挥如此大的作用。

如果你和我一样是 Hugo 开发者,你可能还记得我写过一篇教程,演示如何将静态生成的网站转换为 PWA 格式。这很棒,但这次我们希望让这个过程更通用一些,以便它可以在 Hugo 之外的场景中使用。

使用 HTML、CSS 和 JavaScript 构建网站

让我们创建一个简单的网站,了解发生了什么以及服务工作者为什么能帮助我们,而不仅仅是为了让我们的应用程序被称为 PWA。

几乎每个网站都会包含 HTML、CSS 和 JavaScript 文件,所以我们就从这些文件开始创建一个项目。在你的电脑上,创建一个新文件夹,并在其中放入 index.html 文件、styles.css 文件和 scripts.js 文件。

在 scripts.js 文件中添加以下代码:

console.log("HELLO WORLD!");
Enter fullscreen mode Exit fullscreen mode

这绝对不是你见过的最复杂的脚本,但它会在适当的时候证明我们的观点。我们只是想表明我们的应用程序中有一个单独的 JavaScript 文件。同样地,将以下内容添加到项目的 styles.css 文件中:

body { margin: 0; }
h1 { margin: 0; }
Enter fullscreen mode Exit fullscreen mode

再次强调,本教程的目的并非追求复杂性。我们的目标是演示 Service Worker 如何为我们的项目增值,以及您应该如何引入它们。让我们创建一个包含脚本和样式的 HTML 文件,来完成这个非常基础的项目。打开项目的 index.html 文件,并添加以下内容:

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="styles.css" />
    </head>
    <body>
        <div>
            <h1>Hello World!</h1>
        </div>
        <script src="scripts.js"></script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

如果我们愿意,可以打开 HTML 文件,看到一个完全可以接受的网站。但为了尽早解决问题,我们不能直接在文件系统中打开文件来查看实际效果。我们需要部署我们的项目,可以使用像 Python 或 Caddy 这样的工具,或者将应用程序发布到托管服务提供商处。

如果您使用的是 macOS 或 Linux 系统,或者您的 Windows 电脑上安装了 Python,您可以执行以下操作:

python -m SimpleHTTPServer
Enter fullscreen mode Exit fullscreen mode

上述命令将在http://localhost:8000/index.html上提供我们的应用程序,这对于本示例来说非常理想。

现在我们已经创建了一个简单的 Web 应用程序,接下来打开 Chrome 开发者工具(假设您使用的是 Google Chrome 浏览器)。切换到“网络”选项卡,您会看到类似下图的内容:

Chrome 开发者工具网络信息
Chrome 开发者工具网络信息

虽然每个 HTML、CSS 和 JavaScript 资源都不算特别大,速度也不算慢,但它们都需要被获取。每个用户每次请求都需要获取这些资源。如果是在实际的生产环境中,这可能会导致数 MB 的下载量和数秒的延迟,这在网络世界中是不可接受的,尤其是在移动设备上使用蜂窝网络访问时。

您可以通过转到 Chrome 开发者工具的“审核”选项卡来进一步评估情况。

Chrome 开发者工具审核信息
Chrome 开发者工具审核信息

你会发现该应用并未被评为渐进式 Web 应用 (PWA),当你查看原因时,会发现它缺少一些功能,离线功能就是其中之一。虽然我们并不太在意开发一个 100% 符合 PWA 标准的应用,但我们确实很重视 Service Worker 和离线功能。这不仅有助于我们向用户证明我们的网站是 PWA,更重要的是提升用户体验。

那么,让我们首先添加一个使用 Workbox 格式的服务工作线程的缓存策略。

使用 Workbox 定义缓存策略

Workbox 的用途非常广泛,但首先它可以作为 Service Worker 的运行时替代方案。为了了解它的工作原理,我们创建一个 sw.js 文件来代表我们的 Service Worker。

importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");

workbox.routing.registerRoute(
    /\.(?:css|js)$/,
    new workbox.strategies.StaleWhileRevalidate({
        "cacheName": "assets",
        plugins: [
            new workbox.expiration.Plugin({
                maxEntries: 1000,
                maxAgeSeconds: 31536000
            })
        ]
    })
);

workbox.routing.registerRoute(
    /\.(?:png|jpg|jpeg|gif|bmp|webp|svg|ico)$/,
    new workbox.strategies.CacheFirst({
        "cacheName": "images",
        plugins: [
            new workbox.expiration.Plugin({
                maxEntries: 1000,
                maxAgeSeconds: 31536000
            })
        ]
    })
);
Enter fullscreen mode Exit fullscreen mode

上面的 JavaScript 代码展示了一个使用 Workbox 创建的 Service Worker。这段代码主要包含两个方面,具体内容可能会根据您的业务需求而有所变化。这两个方面分别是针对不同文件采用的两种不同的缓存策略。

对于 JavaScript 和 CSS 文件,StaleWhileRevalidate采用的是缓存策略。这意味着资源会始终被获取并缓存,除非网络连接不可用,此时才会使用缓存版本。对于CacheFirst图片,采用的是缓存策略,始终使用缓存版本,直到缓存版本过期或被手动清除为止。

同样,你需要根据自身业务需求选择策略。策略不止StaleWhileRevalidate一种CacheFirst

要激活此服务工作线程,我们可以编辑index.html文件,使其如下所示:

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="styles.css" />
    </head>
    <body>
        <div>
            <h1>Hello World!</h1>
        </div>
        <script src="scripts.js"></script>
        <script>
            if ("serviceWorker" in navigator) {
                window.addEventListener("load", () => {
                    navigator.serviceWorker.register("sw.js").then(swReg => { }).catch(err => {
                        console.error('Service Worker Error', err);
                    });
                });
            }
        </script>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

请注意,sw.js 文件现在已被 Web 应用程序注册。如果我们重新加载浏览器并转到 Chrome 开发者工具的“网络”选项卡,情况应该会略有不同。

Chrome 开发者工具 Service Worker
Chrome 开发者工具服务工作线程

这次,JavaScript 和 CSS 文件是通过 Service Worker 从缓存加载的。虽然在这个例子中请求时间的节省可能并不明显,但对于接近 1MB 大小的文件来说,从缓存加载不仅能显著提升应用程序的速度,还能使其支持离线运行。

那么我们如何才能改进这个过程呢?

使用 Workbox 构建策略预缓存资源

使用 Workbox 并不特别困难,但我们可以做出一些改变,不仅可以改进流程,还可以改进功能。

假设我们希望在网站首次加载时缓存资源,而不是按需缓存。我们需要制定一个预缓存策略。实现这一目标的最佳方法是通过 Workbox Build 配置,该配置可以使用 Node.js 执行,或者在Hugo 的示例中,可以使用 Gulp 执行。

请在项目中创建一个新的 generator.js 文件。在打开它之前,我们需要配置项目以使用 Node.js,这意味着需要获取依赖项。假设您已经安装了 Node.js,请执行以下操作:

npm init -y
npm install workbox-build --save-dev
Enter fullscreen mode Exit fullscreen mode

需要说明的是,这些是开发依赖项。您的 Web 应用程序不需要使用 Node.js。

安装好所有依赖项后,打开项目的 generator.js 文件并添加以下内容:

const workbox = require("workbox-build");

workbox.generateSW({
    cacheId: "example",
    globDirectory: "./",
    globPatterns: [
        "**/*.{css,js}"
    ],
    globIgnores: [
        "node_modules/**/*",
        "**/gulpfile.js",
        "**/sw.js"
    ],
    swDest: "./sw.js",
    runtimeCaching: [
        {
            urlPattern: /\.(?:html|htm|xml)$/,
            handler: "staleWhileRevalidate",
            options: {
                cacheName: "markup",
                expiration: {
                    maxAgeSeconds: 60 * 60 * 24 * 7,
                },
            },
        }
    ],
});
Enter fullscreen mode Exit fullscreen mode

那么,让我们来弄清楚这个生成器脚本中发生了什么,首先从最熟悉的部分开始,也就是这个runtimeCaching部分。

在这里runtimeCaching,我们为任何给定的文件类型定义策略。在本例中,我们为 HTML 或 XML 文件定义策略,但我们可以轻松地添加更多文件类型。我们选择预缓存 JavaScript 和 CSS 等资源,而不是在运行时缓存它们。要预缓存资源,应将其添加到globPatterns数组中。为了消除缓存开发依赖项的风险,我们可以将资源添加到globIgnores数组中。

预缓存应谨慎使用,因为它会在应用程序加载后立即进行。如果预先缓存过多资源或非常大的文件,用户体验会非常糟糕。因此,应该只预缓存那些能为用户带来最佳体验的资源。

执行node generator.js此操作后,应该会在项目中添加一个 sw.js 文件。该文件与手动创建的 Service Worker 类似,区别在于它现在定义了预缓存。

结论

我们刚刚探讨了如何缓存 Web 应用程序资源,这不仅可以提升 Web 应用程序的性能,还能使其离线可用。Service Worker 是开发完全符合规范的渐进式 Web 应用程序 (PWA) 的第一步,而像 Workbox 这样的框架让这一切变得非常简单。

虽然我们并没有像使用推送通知等原生 API 那样制作 PWA,但我们仍然致力于构建一个像 Google Chrome 这样的浏览器能够识别的 PWA。


编者按:发现本文有误?您可以在这里找到正确版本。

插件:LogRocket,一款用于 Web 应用的 DVR

 
LogRocket 控制面板免费试用横幅
 
LogRocket是一款前端日志工具,可让您重现问题,如同在您自己的浏览器中发生一样。无需猜测错误原因,也无需用户提供屏幕截图和日志转储,LogRocket 即可让您重现会话,快速了解问题所在。它与任何框架的应用程序完美兼容,并提供插件来记录来自 Redux、Vuex 和 @ngrx/store 的额外上下文信息。
 
除了记录 Redux 操作和状态之外,LogRocket 还会记录控制台日志、JavaScript 错误、堆栈跟踪、包含标头和正文的网络请求/响应、浏览器元数据以及自定义日志。它还会对 DOM 进行插桩,记录页面上的 HTML 和 CSS,即使是最复杂的单页应用程序,也能生成像素级精确的视频。
 
免费试用


这篇文章《通过 Workbox 和 Service Worker 开始使用渐进式 Web 应用程序》最初发表在LogRocket 博客上。

文章来源:https://dev.to/bnevilleoneill/getting-started-with-progressive-web-applications-through-workbox-and-service-workers-kc0