PWA 的离线缓存与更新机制详解

什么是 PWA

PWA 是 Progressive Web App 的缩写,中文名为渐进式 Web 应用。它是一种新型的 Web 应用程序模型,具有可以安装、离线使用、接近原生应用的用户体验等特点。PWA 能够让 Web 应用程序在移动设备上运行得更快,更加流畅,并且可以将更多的功能发布到用户手中。

PWA 的离线缓存机制

离线缓存是指将 Web 应用的资源缓存到本地,使得应用可以在离线状态下使用。对于 PWA 应用来说,离线缓存是其最重要的特性之一。

PWA 的离线缓存机制主要依靠浏览器的 Service Worker 技术。Service Worker 是一种独立于 Web 页面的 JavaScript 脚本,它可以代理 Web 请求,并将响应存储到浏览器的缓存中。它可以在浏览器后台运行,使得 Web 应用即使没有打开也可以得到更新和缓存资源。

安装 Service Worker

要使用 Service Worker 技术,需要在 Web 应用的 JavaScript 中编写相应的代码。在 JavaScript 中注册 Service Worker 的代码如下所示:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', function() {
        navigator.serviceWorker.register('/sw.js').then(function(registration) {
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }, function(err) {
            console.log('ServiceWorker registration failed: ', err);
        });
    });
}

在上面的代码中,我们首先判断当前浏览器是否支持 Service Worker,如果支持就在页面加载完成后注册 Service Worker。register 方法的第一个参数是 Service Worker 脚本的路径,第二个参数指定了该 Service Worker 的作用范围。当 Service Worker 注册成功后,我们可以在控制台中看到相应的输出信息。

缓存资源

接下来我们需要在 Service Worker 中添加缓存资源的代码。在 Service Worker 中,我们需要监听 install 事件,在该事件中完成资源的缓存。

例如,在下面的代码中,我们使用 caches.open() 方法打开一个名为 my-cache 的缓存库,并通过 cache.addAll() 方法将相关资源添加到缓存中:

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'
            ]);
        })
    );
});

在上述例子中,我们将根目录、index.html、main.css、main.js 和 logo.png 等资源添加到了缓存中。这些资源可以根据应用需求定制。在应用启动时,Service Worker 会自动下载这些资源并将它们保存在浏览器缓存中。在下一次访问应用时,浏览器就可以直接从缓存中获取这些资源,而不需要再次从服务器端下载。这样就能够实现离线访问。

获取缓存资源

当应用离线时,我们需要从缓存中获取已经缓存的资源。在 Service Worker 中,我们需要将 fetch 事件拦截下来,从缓存中获取相应的资源。

例如,下面的代码可以将所有请求的响应缓存到 my-cache 缓存中,并在当前缓存无法找到请求资源时,从网络中获取资源。

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) {
                if (!response || response.status !== 200 || response.type !== 'basic') {
                    return response;
                }
                var responseToCache = response.clone();
                caches.open('my-cache').then(function(cache) {
                    cache.put(event.request, responseToCache);
                });
                return response;
            });
        })
    );
});

在上述例子中,我们首先通过调用 caches.match() 方法检查缓存中是否有匹配的响应,如果有,直接返回它。如果没有,就从服务器端获取响应,并将该响应存储到缓存中。

PWA 的更新机制

PWA 的另一个重要特性是可以自动更新。通过 Service Worker 技术,可以使得 PWA 应用的资源始终保持最新。

一旦用户访问应用程序,Service Worker 就会在后台检查有没有更新,如果有更新将会自动下载和安装。在更新过程中,Service Worker 会先安装新的版本,然后再将旧的版本移除。一旦更新完成,PWA 就会在用户下次访问应用时展示新的内容。

更新 Service Worker

在 Service Worker 中,我们需要手动调用 skipWaiting() 方法,在 Service Worker 安装成功后立即激活新的 Service Worker,并取代旧的 Service Worker。

例如,在下面的代码中,我们可以检测到新版本的 Service Worker 脚本已经下载完成,并开始安装。在安装完成后,我们会调用 skipWaiting() 方法,以激活新版本的 Service Worker。

self.addEventListener('install', function(event) {
    // 更新当前的 Service Worker
    self.skipWaiting();
});

在调用 skipWaiting() 方法后,新版本的 Service Worker 将会被激活,然后立即取代旧的 Service Worker。

监听更新事件

在 Service Worker 中,我们可以添加一个 activate 监听器,以便检测到新版本的 Service Worker 已经取代了旧的版本。利用该监听器,我们可以完成一些清理旧版本缓存等工作。

例如,下面的代码中,在 activate 事件触发时,我们可以通过调用 caches.keys() 获取所有的缓存名称,然后将它们与当前版本的缓存名称进行比较。如果某个缓存不在当前版本中,就将其删除掉。

self.addEventListener('activate', function(event) {
    event.waitUntil(
        caches.keys().then(function(cacheNames) {
            return Promise.all(
                cacheNames.map(function(cacheName) {
                    if (cacheName !== 'my-cache') {
                        return caches.delete(cacheName);
                    }
                })
            );
        })
    );
});

在上述例子中,我们首先调用 caches.keys() 方法获取所有的缓存名称,然后遍历每一个缓存名称。如果当前缓存名称不在当前版本的缓存库列表中,就将其删除。

总结

PWA 的离线缓存和更新机制是该技术最为核心的特性之一。它通过 Service Worker 技术来实现缓存和自动更新,使得 PWA 应用可以获得接近原生应用的用户体验。开发者可以通过合理地使用 Service Worker 技术,提升 Web 应用程序的性能、可靠性和用户体验。

希望本篇文章对大家了解 PWA 的离线缓存和更新机制有所帮助。祝您编程愉快,欢迎提出宝贵建议和意见。

示例代码:https://github.com/alipay/pwa-demo/tree/master/offline-cache

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65b2387cadd4f0e0ffb66f28