記錄---前端如何優雅通知使用者重新整理頁面?

林恒發表於2024-11-29

🧑‍💻 寫在開頭

點贊 + 收藏 === 學會🤣🤣🤣

前言

老闆:新的需求不是上線了嘛,怎麼使用者看到的還是老的頁面呀
窩囊廢:讓使用者重新整理一下頁面,或者清一下快取
老闆:那我得告訴使用者,重新整理一下頁面,或者清一下快取,才能看到新的頁面呀,感覺使用者體驗不好啊,不能直接重新整理頁面嘛?
窩囊廢:可以解決(OS:一點改的必要沒有,使用者全是大聰明)

產品介紹

c端需要經常進行一些文案調整,一些老版的文字字眼可能會導致一些輿論問題,所以就需要更新之後重新整理頁面,讓使用者看到新的頁面。

思考問題為什麼產生

專案是基於vue的spa應用,透過nginx代理靜態資源,配置了index.html協商快取,js、css等靜態檔案Cache-Control,按正常前端重新部署後, 使用者重新訪問系統,已經是最新的頁面。

但是絕大部份使用者都是訪問頁面之後一直停留在此頁面,這時候前端部署後,使用者就無法看到新的頁面,需要使用者重新整理頁面。

產生問題

  • 如果後端介面有更新,前端重新部署後,使用者訪問老的頁面,可能會導致介面報錯。
  • 如果前端部署後,使用者訪問老的頁面,可能無法看到新的頁面,需要使用者重新整理頁面,使用者體驗不好。
  • 出現線上bug,修復完後,使用者依舊訪問老的頁面,仍會遇到bug。

解決方案

  1. 前後端配合解決
  • WebSocket
  • SSE(Server-Send-Event)
  1. 純前端方案 以下示例均以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

如果對您有所幫助,歡迎您點個關注,我會定時更新技術文件,大家一起討論學習,一起進步。

記錄---前端如何優雅通知使用者重新整理頁面?

相關文章