使用预缓存方法时如何检查已安装的 Web 应用程序 (PWA) 更新
How to check for installed web app (PWA) updates when using precache method
我有一个 Progressive Web App,其中 service worker 的配置如下所示。我遵循预缓存方法。每个文件都将首先被缓存,请求将从缓存中得到服务。如果本地缓存中没有匹配项,则通过网络提供请求。如果一切都失败,则会显示 offline/error 页面。一切正常。但我一直坚持更新 index.html 文件。
const pb_cache = "cv1";
const assets = [
"./manifest.json",
"./index.html",
"./offline.html",
]
self.addEventListener("install", installEvent => {
installEvent.waitUntil(
caches.open(pb_cache)
.then((cache) => {
return cache.addAll(assets)
.then(() => {
return self.skipWaiting(); //To forces the waiting service worker to become the active service worker
})
})
);
});
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.status === 404) {
return caches.match('/offline.html');
}
return response
});
}).catch(function() {
return caches.match('/offline.html');
})
);
});
场景
我已将网络应用程序安装到我的 android phone。一切都被缓存并且工作正常。我需要更改 index.html 文件。所以我对文件进行了一些调整并更新了网站。但是由于安装在 android 中的网络应用服务于本地缓存,因此网站的变化没有反映出来。所以我需要一种机制来检查更新。我应该检查什么参数或什么东西来更新?看了很多这方面的资料,还是没能掌握其中的内容。
我知道的一件事是,我必须检查服务工作者中某处的更新,并在网络中找到时将其添加到缓存中。我不知道要检查哪个事件或什么标准。
执行此操作的“手动”方法是包含类似
的内容
// VERSION: 1
在你的 service worker 文件的顶部,并且记住在你对你在 install
期间缓存的资产进行 任何 更改时更改该数字。更新后的版本号将导致自动 service worker update check 指示有新内容,这又会触发更新后的 service worker 文件中的 install
处理程序再次触发。此时您的所有预缓存资产将再次添加到缓存中。
在评论中进行一些澄清后,我认为在 install
处理程序中使用 cache.addAll()
可能会有问题,因为您无法控制 Cache-Control
headers,而cache.addAll()
会先去HTTP缓存再去网络。这是一个替代的 install
处理程序,它通过传入 Request
objects 和适当的 cache
属性 而不是传入 URL 来解决这个问题] 字符串:
self.addEventListener("install", installEvent => {
const cacheBypassRequests = assets.map(
(url) => new Request(url, {cache: 'reload'});
installEvent.waitUntil(
caches.open(pb_cache)
.then((cache) => {
return cache.addAll(cacheBypassRequests)
.then(() => {
return self.skipWaiting();
})
})
);
});
这显然是 error-prone,因为当您对其中一项资产进行小幅调整时,您可能会忘记增加该值。
一种更稳健的方法是在您的 Web 应用程序的构建过程中添加一个步骤,该步骤将在您每次重新部署时更新您的 Service Worker 文件的版本号。
一种更 production-ready 的方法是使用一种工具来解决这个特定的用例,例如 workbox-precaching
以及节点、webpack 或 CLI 构建接口。这将负责自动生成您要预缓存的每个资产的哈希值,每当其中一个发生变化时触发新安装,并且只有 re-downloading 更新的资产。
此实现最简单的解决方案是在您更改 index.html
时更新 pb_cache
值,这将导致服务工作者更新并重新 index.html
-缓存。但是,不会删除旧的缓存版本。
如果无法从网络获取页面,return 使用 Workbox, it will pre-cache the files indicated in urls
, then when a request for one of those files is made, it will use a stale, while revalidate strategy. The user may see an old version initially, but on the next reload, they'll get the latest. For any other requests (that are not in urls
, it will use a network only strategy. And finally, setCatchHandler
的解决方案将离线页面。
importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.1.0/workbox-sw.js');
// URLs to cache and keep up to date
const urls = [
'/index.html',
'/manifest.json',
'/script.js',
'/style.css',
'/offline.html',
];
// Turn on logging for development, change to false for production
workbox.setConfig({
debug: true
});
const {clientsClaim} = workbox.core;
const {NetworkOnly} = workbox.strategies;
const {StaleWhileRevalidate} = workbox.strategies;
const {warmStrategyCache} = workbox.recipes;
const {registerRoute} = workbox.routing;
const {setDefaultHandler} = workbox.routing;
const {setCatchHandler} = workbox.routing;
self.skipWaiting();
clientsClaim();
// Normalize cache key URLs to:
// - drop query parameters
// - for URLs ending in '/', append 'index.html'
async function cacheKeyWillBeUsed({request}) {
const url = new URL(request.url);
if (url.pathname.endsWith('/')) {
return url.origin + url.pathname + 'index.html';
}
return url.origin + url.pathname;
}
// Initialize a stale while revalidate strategy.
// See https://developers.google.com/web/tools/workbox/modules/workbox-strategies#stale-while-revalidate
const strategy = new StaleWhileRevalidate({
plugins:[
{cacheKeyWillBeUsed},
],
});
// Ensure that an initial set of URLs are cached,
// so that the PWA works offline immediately.
warmStrategyCache({urls, strategy});
// Use the Stale While Revalidate strategy for URLs in `urls`
registerRoute(
({url}) => {
let pathname = url.pathname;
// Normalize paths, for URLs ending in '/', append 'index.html'
if (pathname.endsWith('/')) {
pathname += 'index.html';
}
return urls.includes(pathname);
}, strategy
);
// Use only the network for all other requests
setDefaultHandler(new NetworkOnly());
// This "catch" handler is triggered when any of the other routes fail to
// generate a response. This is a simplified version of the Comprehensive Fallback
// https://developers.google.com/web/tools/workbox/guides/advanced-recipes#comprehensive_fallbacks
setCatchHandler(({event}) => {
if (event.request.destination === 'document') {
return caches.match('/offline.html');
}
});
整个解决方案结合了 Workbox Advanced Recipes 部分的许多方法。
我有一个 Progressive Web App,其中 service worker 的配置如下所示。我遵循预缓存方法。每个文件都将首先被缓存,请求将从缓存中得到服务。如果本地缓存中没有匹配项,则通过网络提供请求。如果一切都失败,则会显示 offline/error 页面。一切正常。但我一直坚持更新 index.html 文件。
const pb_cache = "cv1";
const assets = [
"./manifest.json",
"./index.html",
"./offline.html",
]
self.addEventListener("install", installEvent => {
installEvent.waitUntil(
caches.open(pb_cache)
.then((cache) => {
return cache.addAll(assets)
.then(() => {
return self.skipWaiting(); //To forces the waiting service worker to become the active service worker
})
})
);
});
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.status === 404) {
return caches.match('/offline.html');
}
return response
});
}).catch(function() {
return caches.match('/offline.html');
})
);
});
场景 我已将网络应用程序安装到我的 android phone。一切都被缓存并且工作正常。我需要更改 index.html 文件。所以我对文件进行了一些调整并更新了网站。但是由于安装在 android 中的网络应用服务于本地缓存,因此网站的变化没有反映出来。所以我需要一种机制来检查更新。我应该检查什么参数或什么东西来更新?看了很多这方面的资料,还是没能掌握其中的内容。
我知道的一件事是,我必须检查服务工作者中某处的更新,并在网络中找到时将其添加到缓存中。我不知道要检查哪个事件或什么标准。
执行此操作的“手动”方法是包含类似
的内容// VERSION: 1
在你的 service worker 文件的顶部,并且记住在你对你在 install
期间缓存的资产进行 任何 更改时更改该数字。更新后的版本号将导致自动 service worker update check 指示有新内容,这又会触发更新后的 service worker 文件中的 install
处理程序再次触发。此时您的所有预缓存资产将再次添加到缓存中。
在评论中进行一些澄清后,我认为在 install
处理程序中使用 cache.addAll()
可能会有问题,因为您无法控制 Cache-Control
headers,而cache.addAll()
会先去HTTP缓存再去网络。这是一个替代的 install
处理程序,它通过传入 Request
objects 和适当的 cache
属性 而不是传入 URL 来解决这个问题] 字符串:
self.addEventListener("install", installEvent => {
const cacheBypassRequests = assets.map(
(url) => new Request(url, {cache: 'reload'});
installEvent.waitUntil(
caches.open(pb_cache)
.then((cache) => {
return cache.addAll(cacheBypassRequests)
.then(() => {
return self.skipWaiting();
})
})
);
});
这显然是 error-prone,因为当您对其中一项资产进行小幅调整时,您可能会忘记增加该值。
一种更稳健的方法是在您的 Web 应用程序的构建过程中添加一个步骤,该步骤将在您每次重新部署时更新您的 Service Worker 文件的版本号。
一种更 production-ready 的方法是使用一种工具来解决这个特定的用例,例如 workbox-precaching
以及节点、webpack 或 CLI 构建接口。这将负责自动生成您要预缓存的每个资产的哈希值,每当其中一个发生变化时触发新安装,并且只有 re-downloading 更新的资产。
此实现最简单的解决方案是在您更改 index.html
时更新 pb_cache
值,这将导致服务工作者更新并重新 index.html
-缓存。但是,不会删除旧的缓存版本。
如果无法从网络获取页面,return 使用 Workbox, it will pre-cache the files indicated in urls
, then when a request for one of those files is made, it will use a stale, while revalidate strategy. The user may see an old version initially, but on the next reload, they'll get the latest. For any other requests (that are not in urls
, it will use a network only strategy. And finally, setCatchHandler
的解决方案将离线页面。
importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.1.0/workbox-sw.js');
// URLs to cache and keep up to date
const urls = [
'/index.html',
'/manifest.json',
'/script.js',
'/style.css',
'/offline.html',
];
// Turn on logging for development, change to false for production
workbox.setConfig({
debug: true
});
const {clientsClaim} = workbox.core;
const {NetworkOnly} = workbox.strategies;
const {StaleWhileRevalidate} = workbox.strategies;
const {warmStrategyCache} = workbox.recipes;
const {registerRoute} = workbox.routing;
const {setDefaultHandler} = workbox.routing;
const {setCatchHandler} = workbox.routing;
self.skipWaiting();
clientsClaim();
// Normalize cache key URLs to:
// - drop query parameters
// - for URLs ending in '/', append 'index.html'
async function cacheKeyWillBeUsed({request}) {
const url = new URL(request.url);
if (url.pathname.endsWith('/')) {
return url.origin + url.pathname + 'index.html';
}
return url.origin + url.pathname;
}
// Initialize a stale while revalidate strategy.
// See https://developers.google.com/web/tools/workbox/modules/workbox-strategies#stale-while-revalidate
const strategy = new StaleWhileRevalidate({
plugins:[
{cacheKeyWillBeUsed},
],
});
// Ensure that an initial set of URLs are cached,
// so that the PWA works offline immediately.
warmStrategyCache({urls, strategy});
// Use the Stale While Revalidate strategy for URLs in `urls`
registerRoute(
({url}) => {
let pathname = url.pathname;
// Normalize paths, for URLs ending in '/', append 'index.html'
if (pathname.endsWith('/')) {
pathname += 'index.html';
}
return urls.includes(pathname);
}, strategy
);
// Use only the network for all other requests
setDefaultHandler(new NetworkOnly());
// This "catch" handler is triggered when any of the other routes fail to
// generate a response. This is a simplified version of the Comprehensive Fallback
// https://developers.google.com/web/tools/workbox/guides/advanced-recipes#comprehensive_fallbacks
setCatchHandler(({event}) => {
if (event.request.destination === 'document') {
return caches.match('/offline.html');
}
});
整个解决方案结合了 Workbox Advanced Recipes 部分的许多方法。