亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

前端項目部署后如何提示用戶版本更新詳解

 更新時間:2024年03月30日 09:24:48   作者:不叫貓先生  
這篇文章主要給大家介紹了關于前端項目部署后如何提示用戶版本更新的相關資料,文中通過代碼介紹的非常詳細,對大家的工作或者學習具有一定的參考借鑒價值,需要的朋友可以參考下

前言

項目部署上線后,特別是網(wǎng)頁項目,提示正在操作系統(tǒng)的用戶去更新版本非常 important。一般我們都會用“刷新大法”來清理緩存,但是對于正在操作網(wǎng)頁的用戶,不造系統(tǒng)更新了,請求的還是老版本的資源。

為了確保用戶能夠及時獲得最新的功能和修復的 bug,我們需要通知用戶刷新頁面獲取最新的代碼。

解決方案

每次打包時,都生成一個時間戳,作為系統(tǒng)的偽版本,放到JSON文件中,通過對比文件的響應頭Etag判斷是否有更新。具體步驟如下:

  • 在public文件夾下加入manifest.json文件,里面存放兩個字段:更新內(nèi)容、更新時間戳
  • 前端打包的時候向manifest.json寫入當前時間戳信息
  • 在入口文件main.js中引入檢查版本更新的邏輯,有更新則提示更新。有兩種方式提示提示用戶:
    • 路由守衛(wèi)router.beforeResolve(Vue-Router為例),檢查更新,對比manifest.json文件的響應頭Etag判斷是否有更新
    • 通過Worker輪詢,檢查更新,對比manifest.json文件的響應頭Etag判斷是否有更新。Worker線程并不影響其他線程的邏輯。

整體邏輯如下所示:

1、public目錄下新建manifest.json

{
   "timestamp":21312321311,
   "msg":"更新內(nèi)容如下:\n--1.添加系統(tǒng)更新提示機制"
}

2、寫入當前時間戳到manifest.json

vue.config.js文件中

const { readFile, writeFile } = require('fs')
// 獲取路徑
const filePath = path.resolve(`./public`, 'manifest.json')
// 讀取文件內(nèi)容
readFile(filePath, 'utf8', (err, data) => {
  if (err) {
    console.error('讀取文件時出錯:', err)
    return
  }
  // 將文件內(nèi)容轉換JSON
  const dataObj = JSON.parse(data)
  //修改時間戳
  dataObj.timestamp = new Date().getTime()
  // 將修改后的內(nèi)容寫回文件
  writeFile(filePath, JSON.stringify(dataObj), 'utf8', err => {
    if (err) {
      console.error('寫入文件時出錯:', err)
      return
    }
  })
})

3、檢查版本更新

新建 checkUpdate.js 文件

(1)初始化變量

import Worker from "./checkUpdate.worker.js";
import router from '../router'
//上次的Etag
let lastEtag = '';
//是否更新
let hasUpdate = false
//創(chuàng)建worker線程
const worker = new Worker();

(2)檢查版本更新

//檢查版本更新
async function checkUpdate() {
  try {
    // 檢測前端資源是否有更新
    let response = await fetch(`/manifest.json?v=${Date.now()}`, {
      method: 'head'
    })
    // 獲取最新的etag  
    let etag = response.headers.get('etag')
    hasUpdate = lastEtag && etag !== lastEtag
    lastEtag = etag
  } catch (e) {
    return Promise.reject(e)
  }
}

其中let response = await fetch(/manifest.json?v=${Date.now()}, { method: 'head' }),
使用 fetch 函數(shù)發(fā)起了一個 HTTP 請求,獲取了指定資源的頭信息(HTTP 頭部)。其中 manifest.json 是要請求的資源,Date.now() 會生成當前時間的時間戳,作為查詢參數(shù) v 的值,這樣可以避免瀏覽器緩存,強制獲取最新的資源。請求方式為 HEAD,這意味著只請求資源的頭部信息而不獲取具體的內(nèi)容。

let etag = response.headers.get('etag'),從 HTTP 響應中獲取了 ETag 頭部信息,ETag 是服務器生成的資源唯一標識,用于檢查資源是否發(fā)生了變化。具體比較邏輯如下:

1、客戶端發(fā)起請求,請求中包含上次獲取的資源的ETag。
2、服務器收到請求后,比較客戶端提供的ETag與當前資源的ETag是否一致。
3、如果一致,則返回HTTP 304 Not Modified響應,表示資源未發(fā)生變化,客戶端可以使用緩存的版本。
4、如果不一致,服務器返回最新的資源內(nèi)容,同時更新ETag。
5、客戶端收到響應后,更新本地緩存的資源內(nèi)容和ETag。

(3)路由跳轉檢測版本更新

 // 路由攔截
 router.beforeEach(async (to, from, next) => {
  next()
  try {
    await checkUpdate()
    if (hasUpdate) {
      worker.postMessage({
        type: 'destroy'
      })
      location.reload()
    }
  } catch (e) {}
})

(4)向worker線程發(fā)送檢查版本更新邏輯

worker.postMessage({
  type: 'check'
})

(5)接收到 worker 線程數(shù)據(jù)更新

worker.onmessage = ({ data }) => {
  console.log(data,'data')
  if (data.type === 'hasUpdate') {
    hasUpdate = true
    confirmReload(data.msg, data.lastEtag)
  }
}

(6)收到版本更新信息,進行彈框提示

收到版本更新信息后,先暫停輪詢檢查版本更新,點擊確定按鈕,則發(fā)送destory消息,點擊取消按鈕則發(fā)送recheck消息

async function confirmReload(msg = '', lastEtag) {
  worker &&
    worker.postMessage({
      type: 'pause'
    })
  try {
  //彈框提示邏輯
  } catch (e) { }
}

checkUpdate.js 全部代碼實現(xiàn)

import Worker from "./checkUpdate.worker.js";
import router from '../router'
//上次的Etag
let lastEtag = '';
//是否更新
let hasUpdate = false
//創(chuàng)建worker線程
const worker = new Worker();

//檢查版本更新
async function checkUpdate() {
  try {
    // 檢測前端資源是否有更新
    let response = await fetch(`/manifest.json?v=${Date.now()}`, {
      method: 'head'
    })
    // 獲取最新的etag  
    let etag = response.headers.get('etag')
    hasUpdate = lastEtag && etag !== lastEtag
    lastEtag = etag
    console.log(lastEtag = etag,'lastEtag = etag')
  } catch (e) {
    return Promise.reject(e)
  }
}

async function confirmReload(msg = '', lastEtag) {
  worker &&
    worker.postMessage({
      type: 'pause'
    })
  try {
    console.log('版本更新了')
  } catch (e) { }
}
 // 路由攔截
 router.beforeEach(async (to, from, next) => {
  next()
  try {
    await checkUpdate()
    if (hasUpdate) {
      worker.postMessage({
        type: 'destroy'
      })
      location.reload()
    }
  } catch (e) {}
})

worker.postMessage({
  type: 'check'
})


worker.onmessage = ({ data }) => {
  console.log(data,'data')
  if (data.type === 'hasUpdate') {
    hasUpdate = true
    confirmReload(data.msg, data.lastEtag)
  }
}

4、woker線程

新建 checkUpdate.worker.js

(1)初始化變量

let lastEtag;//上次的Etag
let hasUpdate = false;//是否更新
let intervalId = '';

(2)檢查版本更新

邏輯更第三步差不多,唯一一點就是檢測到更新后,發(fā)送hasUpdate消息,給出彈框提示是否需要更新

async function checkUpdate() {
  try {
    // 檢測前端資源是否有更新
    let response = await fetch(`/manifest.json?v=${Date.now()}`, {
      method: 'get'
    })
    // 獲取最新的etag和data
    let etag = response.headers.get('etag')
    let data = await response.json()
    hasUpdate = lastEtag !== undefined && etag !== lastEtag
  
    if (hasUpdate) {
      postMessage({
        type: 'hasUpdate', 
        msg: data.msg,
        lastEtag: lastEtag,
        etag: etag
      })
    }
    lastEtag = etag
  } catch (e) {
    return Promise.reject(e)
  }
}

(3)監(jiān)聽主線程發(fā)送過來的數(shù)據(jù)

// 監(jiān)聽主線程發(fā)送過來的數(shù)據(jù)
addEventListener('message', ({ data }) => {
  console.log(data,'消息')
  if (data.type === 'check') {  
    // 每5分鐘執(zhí)行一次
    // 立即執(zhí)行一次,獲取最新的etag,避免在setInterval等待中系統(tǒng)更新,第一次獲取的etag是新的,但是lastEtag還是undefined,不滿足條件,錯失刷新時機
    // checkUpdate()
    intervalId = setInterval(()=>{
      checkUpdate()
      //這里3s方便測試
    },  3 * 1000)
  }
  if (data.type === 'recheck') {
    // 每5分鐘執(zhí)行一次
    hasUpdate = false
    lastEtag = data.lastEtag
    intervalId = setInterval(()=>{
      checkUpdate()
    },  3 * 1000)
  }
  if (data.type === 'pause') {
    clearInterval(intervalId)
  }
  if (data.type === 'destroy') {
    clearInterval(intervalId)
    close()
  }
})

完整代碼邏輯如下:

let lastEtag
let hasUpdate = false
let intervalId = ''
async function checkUpdate() {
 
  try {
    // 檢測前端資源是否有更新
    let response = await fetch(`/manifest.json?v=${Date.now()}`, {
      method: 'get'
    })
    // 獲取最新的etag和data
    let etag = response.headers.get('etag')
    let data = await response.json()
    hasUpdate = lastEtag !== undefined && etag !== lastEtag
  
    if (hasUpdate) {
      postMessage({
        type: 'hasUpdate', 
        msg: data.msg,
        lastEtag: lastEtag,
        etag: etag
      })
    }
    lastEtag = etag
  } catch (e) {
    return Promise.reject(e)
  }
}

// 監(jiān)聽主線程發(fā)送過來的數(shù)據(jù)
addEventListener('message', ({ data }) => {
  console.log(data,'消息')
  if (data.type === 'check') {  
     console.log('checkcheckcheck')
    // 每5分鐘執(zhí)行一次
    // 立即執(zhí)行一次,獲取最新的etag,避免在setInterval等待中系統(tǒng)更新,第一次獲取的etag是新的,但是lastEtag還是undefined,不滿足條件,錯失刷新時機
    // checkUpdate()
    intervalId = setInterval(()=>{
      checkUpdate()
      console.log('檢查版本更新')
    },  3 * 1000)
  }
  if (data.type === 'recheck') {
    // 每5分鐘執(zhí)行一次
    hasUpdate = false
    lastEtag = data.lastEtag
    intervalId = setInterval(()=>{
      checkUpdate()
      console.log('檢查版本更新')
    },  3 * 1000)
    console.log('recheckrecheckrecheck')
  }
  if (data.type === 'pause') {
    clearInterval(intervalId)
  }
  if (data.type === 'destroy') {
    clearInterval(intervalId)
    close()
  }
})

5、入口文件引入

import "@/utils/checkUpdate.js"

可能出現(xiàn)的問題

1、worker

webpack 5 可以使用 Web Workers

new Worker(new URL('./checkUpdate.worker.js', import.meta.url));

webpack 5 以下,使用 worker-loader,先安裝worker-loader

yarn add worker-loader -D

然后在vue.config.js 配置

  chainWebpack(config) {
    config.module
    .rule('worker')
    .test(/\.worker\.js$/)
    .use('worker')
    .loader('worker-loader')
    .end()
  }

如果配置有問題,會一直出現(xiàn)下面這個問題,worker-loader 的配置要放在其他 loader 前。

總結 

到此這篇關于前端項目部署后如何提示用戶版本更新的文章就介紹到這了,更多相關前端提示用戶版本更新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論