使用 Service Worker 构建离线优先的 Web 应用

93 阅读5分钟

浏览你的网页应用总是流畅流畅,直到网络连接断开。突然间,你的用户看到那令人沮丧的灰色“您处于离线状态”的提示,体验就此结束。但事实并非如此。你的应用应该能够立即加载,感觉像原生应用一样可靠,即使在网络故障的情况下也能正常工作。

是的。您的 Web 应用无需联网即可运行。这就是渐进式 Web 应用 (PWA) 和“离线优先”开发模式的优势。

在本文中,您将学习如何将任何标准 Web 应用程序转变为强大且可安装的 PWA。我们将深入探讨如何使用 Service Worker 缓存应用的核心文件,让您的 UI 免受网络问题的影响。本文中的原则具有通用性,因此您可以将其应用于您正在进行的任何前端项目。

准备好了吗?出发啦🚀

你需要什么? 单页 Web 应用。它可以简单到只是一个index.html包含一些 CSS 和 JavaScript 的文件。关键在​​于它包含一些我们可以缓存的不同文件,这样即使离线也能加载主界面(“应用外壳”)。

步骤 1:创建 Web 应用清单 我们想告诉浏览器我们的应用程序以及它在“安装”后应该如何运行。我们用一个manifest.json文件来实现这一点。

创建清单:在项目的根目录中,创建一个名为 的新文件manifest.json。 添加配置:将以下 JSON 粘贴到文件中。请务必根据您自己的项目 自定义name、short_name和。descriptionicons { "name": "My Awesome App", "short_name": "AwesomeApp", "start_url": ".", "display": "standalone", "background_color": "#ffffff", "theme_color": "#007bff", "description": "A description of my awesome PWA.", "icons": [ { "src": "images/icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "images/icon-512.png", "sizes": "512x512", "type": "image/png" } ] } 请记住,您需要将自己的图标文件保存在images文件夹中,才能使其完美运行。

链接清单:打开您的index.html并在标签内添加此行:

有了它,Chrome 等浏览器现在会在地址栏中显示“安装”图标,允许用户将您的应用添加到他们的主屏幕。

步骤 2:注册 Service Worker Service Worker 是一种特殊类型的 JavaScript 文件,您的浏览器会在后台运行,独立于您的网页。它的作用类似于代理,允许拦截网络请求并在代码中处理。这是离线功能的关键。

在项目根目录中创建一个sw.js文件。暂时保留为空。

通过告诉主应用程序安装 Service Worker 来注册它。将以下脚本标签添加到in 文件的底部index.html。 此代码检查浏览器是否支持服务工作者,如果支持,则sw.js在页面加载时注册该文件。

步骤 3:缓存 App Shell 以供离线使用 现在,让我们给 Service Worker 分配一个任务。首次安装 Service Worker 时,我们会让它下载并保存构成应用用户界面(即“应用外壳”)的所有必要文件。

打开sw.js并添加以下代码:

const CACHE_NAME = 'app-shell-cache-v1'; const ASSETS_TO_CACHE = [ '/', '/index.html', '/styles.css', // <-- your main CSS file '/app.js', // <-- your main JS file/entry point '/some-other-chunk.js', // other JS files your app needs '/favicon.ico', '/images/icon-192.png' // <-- remember your own icon file in your images folder ];

// the install event fires when the service worker is first installed self.addEventListener('install', event => { console.log('service worker: installing...');

event.waitUntil( caches.open(CACHE_NAME) .then(cache => { console.log('service worker: caching app shell'); return cache.addAll(ASSETS_TO_CACHE); }) ); }); 在这里,我们定义了一个对 UI 至关重要的文件列表。该install事件会打开一个特定名称的缓存,并保存这些文件以供日后使用。现代 JavaScript 工具(例如 Vite 或 Create React App)通常会创建多个 JS 和 CSS 文件。为了确保应用能够离线运行,您必须缓存所有必需的文件。使用浏览器 DevTools 中的“网络”选项卡,可以查看页面加载时请求的所有文件,并将它们添加到此列表中。虽然操作有点繁琐,但它能让您的应用完美地离线运行。

步骤 4:拦截请求并从缓存提供服务 文件缓存完成后,最后一步是告诉 Service Worker 实际使用缓存。我们将监听fetch页面发出的任何网络请求(事件)。如果请求的文件存在于缓存中,则会直接从缓存中提供文件,完全绕过网络。

将此代码添加到文件底部sw.js:

// sw.js (continued)

// the activate event fires after the install event, good place to clean up old caches self.addEventListener('activate', event => { console.log('service worker: activating...'); event.waitUntil( caches.keys().then(cacheNames => { return Promise.all( cacheNames.map(cache => { if (cache !== CACHE_NAME) { console.log('service worker: clearing old cache'); return caches.delete(cache); } }) ); }) ); });

// the fetch event fires for every network request self.addEventListener('fetch', event => { console.log('service worker: fetching');

event.respondWith( caches.match(event.request) .then(response => { // if the request is in the cache, return it, else fetch from the network return response || fetch(event.request); }) ); }); 这种“缓存优先”策略非常适合 App Shell。现在,即使用户离线,只要他们访问过一次网站,Service Worker 就会拦截该请求index.html并直接从缓存中提供服务。

步骤 5:测试离线优先应用 测试这一点的最佳地点是 Chrome DevTools。

打开 DevTools(Ctrl+Shift+I或Cmd+Opt+I)。 转到应用程序选项卡。 屏幕截图显示了 Chrome DevTools 中的“应用程序”选项

在“服务工作者”部分下,您应该看到您的sw.js文件“已激活并正在运行”。您可以先注销所有旧的服务工作者。 在“缓存存储”下,您可以检查app-shell-cache-v1并查看您保存的所有文件。您可以随意删除旧的缓存。 屏幕截图显示了 Chrome DevTools 中的“缓存存储”部分

勾选DevTools 窗口顶部的“离线”复选框,然后尝试刷新页面。页面应该仍然可以完美加载。 DevTools 应用程序选项卡的屏幕截图,显示了已注册的服务工作线程和

瞧😁!你的 Web 应用已经大幅升级了。它现在速度更快、更可靠,并且通过可安装和离线运行,提供了媲美原生应用的体验。这些技术正是现代高质量 Web 开发的核​​心。

这只是您 PWA 之旅的开始。从这里开始,您可以探索使用 IndexedDB 缓存动态 API 数据,或使用推送通知吸引用户。作者www.mjsyxx.com