🧑💻 寫在開頭
點贊 + 收藏 === 學會🤣🤣🤣
前言
老闆:新的需求不是上線了嘛,怎麼使用者看到的還是老的頁面呀
窩囊廢:讓使用者重新整理一下頁面,或者清一下快取
老闆:那我得告訴使用者,重新整理一下頁面,或者清一下快取,才能看到新的頁面呀,感覺使用者體驗不好啊,不能直接重新整理頁面嘛?
窩囊廢:可以解決(OS:一點改的必要沒有,使用者全是大聰明)
產品介紹
c端需要經常進行一些文案調整,一些老版的文字字眼可能會導致一些輿論問題,所以就需要更新之後重新整理頁面,讓使用者看到新的頁面。
思考問題為什麼產生
專案是基於vue的spa應用,透過nginx代理靜態資源,配置了index.html協商快取,js、css等靜態檔案Cache-Control
,按正常前端重新部署後,
使用者重新
訪問系統,已經是最新的頁面。
但是絕大部份使用者都是訪問頁面之後一直停留在此頁面,這時候前端部署後,使用者就無法看到新的頁面,需要使用者重新整理頁面。
產生問題
- 如果後端介面有更新,前端重新部署後,使用者訪問老的頁面,可能會導致介面報錯。
- 如果前端部署後,使用者訪問老的頁面,可能無法看到新的頁面,需要使用者重新整理頁面,使用者體驗不好。
- 出現線上bug,修復完後,使用者依舊訪問老的頁面,仍會遇到bug。
解決方案
- 前後端配合解決
- WebSocket
- SSE(Server-Send-Event)
- 純前端方案 以下示例均以vite+vue3為例;
- 輪詢html Etag/Last-Modified
在App.vue中新增如下程式碼
const oldHtmlEtag = ref(); const timer = ref(); const getHtmlEtag = async () => { const { protocol, host } = window.location; const res = await fetch(`${protocol}//${host}`, { headers: { "Cache-Control": "no-cache", }, }); return res.headers.get("Etag"); }; oldHtmlEtag.value = await getHtmlEtag(); clearInterval(timer.value); timer.value = setInterval(async () => { const newHtmlEtag = await getHtmlEtag(); console.log("---new---", newHtmlEtag); if (newHtmlEtag !== oldHtmlEtag.value) { Modal.destroyAll(); Modal.confirm({ title: "檢測到新版本,是否更新?", content: "新版本內容:", okText: "更新", cancelText: "取消", onOk: () => { window.location.reload(); }, }); } }, 30000);
- versionData.json
自定義plugin,專案根目錄建立/plugins/vitePluginCheckVersion.ts
import path from "path"; import fs from "fs"; export function checkVersion(version: string) { return { name: "vite-plugin-check-version", buildStart() { const now = new Date().getTime(); const version = { version: now, }; const versionPath = path.join(__dirname, "../public/versionData.json"); fs.writeFileSync(versionPath, JSON.stringify(version), "utf8", (err) => { if (err) { console.log("寫入失敗"); } else { console.log("寫入成功"); } }); }, }; }
在vite.config.ts中引入外掛
import { checkVersion } from "./plugins/vitePluginCheckVersion"; plugins: [ vue(), checkVersion(), ]
在App.vue中新增如下程式碼
const timer = ref() const checkUpdate = async () => { let res = await fetch('/versionData.json', { headers: { 'Cache-Control': 'no-cache', }, }).then((r) => r.json()) if (!localStorage.getItem('demo_version')) { localStorage.setItem('demo_version', res.version) } else { if (res.version !== localStorage.getItem('demo_version')) { localStorage.setItem('demo_version', res.version) Modal.confirm({ title: '檢測到新版本,是否更新?', content: '新版本內容:' + res.content, okText: '更新', cancelText: '取消', onOk: () => { window.location.reload() }, }) } } } onMounted(()=>{ clearInterval(timer.value) timer.value = setInterval(async () => { checkUpdate() }, 30000) })
- plugin-web-update-notification
Use
// vite.config.ts import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { webUpdateNotice } from '@plugin-web-update-notification/vite' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), webUpdateNotice({ logVersion: true, }), ] })
本文轉載於:https://juejin.cn/post/7439905609312403483
如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。