网站内容更新机制(1.PWA离线机制用户在断网的情况下也能访问您的网站)
优采云 发布时间: 2021-09-28 19:09网站内容更新机制(1.PWA离线机制用户在断网的情况下也能访问您的网站)
1.PWA 离线机制
即使网络断开,用户也可以访问您的 网站。实际上,用户访问的是他在本地下载并安装的 service worker 文件。Service Worker 权限高,只支持 https 协议或 localhost。
如果你的浏览器控制台输出是这样,就证明service worker是支持的。
如果你的浏览器控制台输出是这样的,证明不支持service worker
2.引入离线缓存机制,即使断网,依然可以访问页面。废话几句,直接上代码
项目中使用了sw-precache-webpack-plugin插件,在你的项目生产环境的config配置中插件SWPrecacheWebpackPlugin添加
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
plugins:[
isEnvProduction && new SWPrecacheWebpackPlugin(
{
cacheId: 'pc',
filename: 'service-worker.js',
minify: true,
navigateFallback: paths.publicUrlOrPath + 'index.html',
navigateFallbackWhitelist: [/^(?!\/__).*/],
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
}
),
]
让入口文件安装并注册service worker
function swRegister(path) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./service-worker.js', { scope: path }).then(
function (registrations) {
console.log('ServiceWorker registration successful with scope', registrations.scope);
},
function (err) {
console.log('ServiceWorker registration failed: ', err)
}
)
}
}
const swScope = [
'./',
]
for(let s of swScope){
swRegister(s)
}
3.重要配置解析staticFileGlobsIgnorePatterns,这个配置是基于正则匹配,忽略哪些文件,这样就不会被缓存。
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/]
这样配置service worker缓存index.html并添加hash值
只有缓存 index.html 才能在断网的情况下访问网页。如下
一旦用户访问我们的网页,我们就像红糖一样粘着他,他总是可以访问,即使互联网断开了。有一天我们放弃了 网站 并且他仍然可以访问它。这就是将缓存写入缓存存储,并安装注册到用户本地。
4. 发布和在线issue暴露了一个,如果你仔细观察,你会发现它。这不是错误
首先,解释我们为什么引入离线缓存。每次发布上线,都需要刷新两次修改后的代码才能生效,以后用户才能正常访问。
PWA 离线缓存机制,如果我们修改了一个小内容,那么 npm run build 就会被释放并启动。因为我引入了 PWA 离线机制,用户更喜欢访问我们本地缓存的资源,记住它们只是静态资源。这时候,用户访问了我们网站,实际上做了两件事。
4.1 首次开放
打开我们的网页时,浏览器首先会读取service worker的版本是否更新,因为数据被修改了,所以必须更新版本。浏览器发送请求,发现service-worker.js文件从#1990变成了#1991,才意识到需要重置缓存。
4.2 再次刷新
然后再次刷新页面。这时候会发送一个http请求来获取我们修改后的代码。这时候我们修改发布的代码就会被用户看到。用户之后访问我们的网站是正常的。以后如果你的项目有新需求迭代,完成后发布上线,那么还是会执行上面的机制,即两次刷新才能看到你修改的内容。
4.3 如何解决每次发布上线,用户第一次拿到旧的,需要重新刷新的问题?
我这里给出两种解决方案:一:强制刷新,二:引导用户刷新。其实这个问题和我们手机APP软件类似。每次我们更新,都会弹出一个弹框:我们修复了什么,是否需要更新。确定或取消
代码显示如下:
const swRegister = function() {
const SW = navigator.serviceWorker
if ('serviceWorker' in navigator) {
SW.register('./service-worker.js').then((registration) => {
// 捕获到registration.installing触发
registration.onupdatefound = function(){
const installingWorker = registration.installing;
installingWorker.onstatechange = function(){
// 发布时每次更新了新的内容,用户首次看到的是旧的内容,要二次刷新的问题
if(installingWorker.state === 'activated'){
if(SW.controller){
// 这个是后台你配置的开关,是否暴力刷新页面。以防万一发布上线了错误的代码,第一时间关闭按钮
const forceReload = false;
if(forceReload){
console.log('暴力刷新页面');
// window.location.reload();
return;
}else{
console.log('有新的内容更新,请刷新页面');
// window.location.reload();
}
}
}
}
}
console.log('注册成功!注册作用域是:', registration.scope);
},
(err) => {
console.log('ServiceWorker registration failed: ', err)
}
)
}
}
swRegister();
5. 如果只缓存js、css等静态资源,可以不断网访问。
然后你发布的内容会实时更新(记住第一次发布不是实时的,因为里面还有html缓存,当你第二、第三...都是实时的),即使发布后,用户第一次打开网页,不会出现两次刷新的问题。怎么做,我们只是不缓存html
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
plugins:[
isEnvProduction && new SWPrecacheWebpackPlugin(
{
cacheId: 'pc',
filename: 'service-worker.js',
minify: true,
navigateFallback: paths.publicUrlOrPath + 'index.html',
navigateFallbackWhitelist: [/^(?!\/__).*/],
staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/,/.html$/],
}
),
]
.html 文件在此处被忽略。
6.service-worker.js 注册安装范围
function swRegister(path) {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./service-worker.js', { scope: path }).then(
function (registrations) {
console.log('ServiceWorker registration successful with scope', registrations.scope);
},
function (err) {
console.log('ServiceWorker registration failed: ', err)
}
)
}
}
const swScope = [
'./',
]
for(let s of swScope){
swRegister(s)
}
这个swScope就是注册的范围,如果不设置,默认在当前域名下。但是我们的项目不会简单的注册在当前域名下,比如路由等,所以范围首先很重要。
如果我们要注册到当前域名下的用户页面。我们需要修改swScope如下:
const swScope = [
'./user/',
]
7.总结
希望以上文章可以对你有所帮助。如果有任何错误,请纠正我。笔名:minion