1.下载workbox-v7.4.1本地JS版本:workbox-v7.4.1。
将文件解压到public/static/js文件里面。
2.配置manifest.json,最简能用配置:
{
"name": "citya",
"short_name": "citya",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#ffffff",
"icons": [
{
"src": "/static/img/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/static/img/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
manifest.json文件放在public文件夹里。
html页面引用:
<link rel="manifest" href="/manifest.json">
3.写一个安装app.js,内容如下:
(function () {
'use strict';
if (!('serviceWorker' in navigator)) return;
window.addEventListener('load', function () {
navigator.serviceWorker.register('/sw.js')
.catch(function (err) {
if (window.Sentry) window.Sentry.captureException(err);
});
});
})();
app.js文件放到public/static/js目录中。
4.创建sw.js文件,内容如下:
importScripts('/static/js/workbox-v7.4.1/workbox-sw.js');
const RUNTIME_VERSION = 'v1';
workbox.setConfig({
modulePathPrefix: '/static/js/workbox-v7.4.1/'
});
/**
* 预缓存核心页面(只作为离线兜底,不强制走缓存)
*/
workbox.precaching.precacheAndRoute([
{ url: '文件路径,如:/static/img/logo.png', revision: '1' },
]);
/**
* HTML 页面:网络优先
*/
workbox.routing.registerRoute(
({ request }) => request.mode === 'navigate',
new workbox.strategies.NetworkFirst({
cacheName: `html-cache-${RUNTIME_VERSION}`,
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 500,
// maxAgeSeconds: 7 * 24 * 60 * 60 // 缓存 7 天
})
]
})
);
/**
* 带参数的请求:不缓存
*/
workbox.routing.registerRoute(
({ url }) => url.search.length > 0,
new workbox.strategies.NetworkOnly()
);
/**
* 图片:先缓存后台更新
*/
workbox.routing.registerRoute(
({ request }) => request.destination === 'image',
new workbox.strategies.StaleWhileRevalidate({
cacheName: `image-cache-${RUNTIME_VERSION}`,
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 500,
//maxAgeSeconds: 30 * 24 * 60 * 60
})
]
})
);
/**
* JS / CSS / 字体:永久缓存(手动版本控制更新缓存)
*/
workbox.routing.registerRoute(
({ request }) =>
request.destination === 'script' ||
request.destination === 'style' ||
request.destination === 'font',
new workbox.strategies.CacheFirst({
cacheName: `static-cache-${RUNTIME_VERSION}`,
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 500,
//maxAgeSeconds: 365 * 24 * 60 * 60
}),
new workbox.cacheableResponse.CacheableResponsePlugin({
statuses: [0, 200]
})
]
})
);
/**
* 匹配所有 POST/PUT/DELETE 请求:只走网络,不缓存
*/
workbox.routing.registerRoute(
({ request }) => ['POST', 'PUT', 'DELETE', 'PATCH'].includes(request.method),
new workbox.strategies.NetworkOnly()
);
/**
* API只能通过网络
*/
workbox.routing.registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new workbox.strategies.NetworkOnly()
);
/**
* 激活时清理旧缓存
*/
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames
.filter((name) => {
/**
* 保留 workbox 自身缓存
*/
if (name.startsWith('workbox-')) return false;
/**
* 保留当前版本的缓存(以 -v1 结尾的)
*/
if (name.endsWith(`-${RUNTIME_VERSION}`)) return false;
return true;
})
.map((name) => caches.delete(name))
);
}).then(() => self.clients.claim())
);
});
sw.js文件,放在public目录中。
5.Html页面引用app.js文件:
<script src="/static/js/app.js" defer>script>
经过上面的配置,网站就有了基本离线功能,只要打开过的网页,在没有网络的情况下也能够打开预览。