前言
在现代 web 应用中,PWA(Progressive Web App)成为了越来越流行的选择。PWA 带来了可靠、快速、可免费安装到桌面以及离线工作等良好的用户体验。Service Worker(SW)作为 PWA 技术的核心,可以为扩展 PWA 带来如网络代理和缓存等能力。这篇文章会深入介绍 SW 的生命周期以及缓存策略,希望可以为你深入了解 PWA 技术提供帮助。
SW 的生命周期
Service Worker 的生命周期一般可以分为以下三个阶段:
安装阶段(install)
在这个阶段中,我们可以将需要缓存的 assets 预存储到浏览器缓存中,以便下次离线使用。这个阶段会在 SW 文件被注册时执行,一般可以通过监听 install
事件来进行处理:
self.addEventListener('install', function(event) { event.waitUntil( caches.open('my-cache').then(function(cache) { return cache.addAll([ '/', '/index.html', '/styles/main.css', '/scripts/main.js', '/images/logo.png' ]); }) ); });
上面的代码中,我们使用了 caches
API 来创建了一个名为 my-cache
的缓存,并将需要缓存的文件添加到了这个缓存中。注意,在添加完资源之后我们使用了 waitUntil
方法来保证 SW 安装阶段不会结束,直到我们的资源都被正确地缓存起来。
激活阶段(activate)
在第一次安装 SW 以及新 SW 版本被注册/安装时,激活事件会触发。在这个阶段中,我们可以开始使用与新版本 SW 相关的资源,例如删除旧版本资源。
self.addEventListener('activate', function(event) { var cacheWhitelist = ['my-cache']; event.waitUntil( caches.keys().then(function(cacheNames) { return Promise.all( cacheNames.map(function(cacheName) { if (cacheWhitelist.indexOf(cacheName) === -1) { return caches.delete(cacheName); } }) ); }) ); });
在上述代码中,我们使用了 caches.keys()
方法来获取当前 scoped 到 SW 的所有缓存,并使用了 Promise
和 map
方法来异步删除所有未出现在 cacheWhitelist
列表中的缓存。这个列表中包含了所有 SW 需要用到的缓存名。
拦截阶段(fetch)
在这个阶段中,我们可以处理所有从文档中发出的 HTTPS 请求。这个阶段的处理可以通过监听 fetch
事件来完成。
self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request).then(function(response) { if (response) { return response; } return fetch(event.request); }) ); });
在上述代码中,我们首先使用了 caches.match()
来查找资源的缓存。如果缓存存在,则直接将其返回;否则,我们使用 fetch()
方法来请求该资源。
缓存策略
SW 的灵活性和强大能力使其成为了 PWA 架构的核心。通过缓存和从缓存中获取资源,我们可以大大提高 web 应用的性能和速度。让我们来看看 SW 最常见的缓存策略并为每个策略给出示例代码:
网络优先策略
这个策略中,我们通过尝试从网络中获取资源。如果获取成功,则直接返回该资源;否则,我们使用通过缓存返回有效资源。这个策略的实现示例代码如下:
self.addEventListener('fetch', function(event) { event.respondWith( fetch(event.request).then(function(response) { if (response.status === 404) { return caches.match('404.html'); } return response; }).catch(function() { return caches.match(event.request); }) ); });
在上述代码中,我们通过返回 404 错误页面来展现了当网络不可用且请求的资源不在缓存中时,通过缓存返回的实现。
缓存优先策略
在这个策略中,我们首先尝试从缓存中获取资源。如果缓存不存在/已失效,则尝试从网络中获取资源。如果获取成功,我们将其添加到缓存中,并返回该成功获取到的资源。这个策略的实现示例代码如下:
self.addEventListener('fetch', function(event) { event.respondWith( caches.match(event.request).then(function(response) { if (response) { return response; } return fetch(event.request).then(function(response) { caches.open('my-cache').then(function(cache) { cache.put(event.request, response.clone()); }); return response; }); }) ); });
在上述代码中,我们先尝试从缓存中获取资源。如果在缓存中找到了资源,将其直接返回。如果未找到资源,则尝试从网络中获取。当网络请求成功后,我们将其添加到缓存中,以便下次使用直接从缓存中获取。
网络优先但同时使用缓存策略
在这个策略中,我们首先尝试从网络中获取资源。如果获取成功,我们将其添加到缓存中并同时返回该资源。如果获取不成功,我们通过从缓存中获取资源来尝试解决该请求。这个策略的实现示例代码如下:
self.addEventListener('fetch', function(event) { event.respondWith( fetch(event.request).then(function(response) { caches.open('my-cache').then(function(cache) { cache.put(event.request, response.clone()); }); return response; }).catch(function() { return caches.match(event.request); }) ); });
在上述代码中,我们首先尝试从网络中获取资源。当获取成功时,我们将其添加到缓存中并同时返回该资源。如果失败,则从缓存中获取资源并返回该资源。
总结
SW 可以为 PWA 执行一些非常有用的任务,并提供了强大的缓存功能。我们希望这篇文章可以让你深入了解 Service Worker 生命周期和 PWA 的缓存策略,从而更好地了解如何开发一个快速、可靠且离线可用的 web 应用。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65acfcb7add4f0e0ff68f5e7