网站内容更新机制(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

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线