pro-collection / interview-question

目标:收集全网经典面试问题
713 stars 53 forks source link

项目部署更新之后,如何提醒用户去刷新更新页面资源【热度: 340】 #1067

Open yanlele opened 1 week ago

yanlele commented 1 week ago
  1. 使用版本号查询参数
    • 原理:在 HTML 文件中,对于引用的静态资源(如 JavaScript 文件、CSS 文件),可以在 URL 后面添加一个版本号查询参数。每次更新项目后,更新这个版本号。这样,浏览器会将带有新的版本号的资源视为一个新的请求,从而强制刷新资源。
    • 示例
      • 原始的 JavaScript 文件引用可能是<script src="main.js"></script>。更新后,可以将其改为<script src="main.js?v=2"></script>,其中v=2是版本号。每次更新项目时,递增这个版本号。
      • 在构建或部署工具中,可以通过配置自动更新这个版本号。例如,在使用 Webpack 构建时,可以使用html - webpack - plugin插件结合版本控制工具来自动更新版本号。假设你有一个简单的 Webpack 配置文件,如下:
        const HtmlWebpackPlugin = require("html - webpack - plugin");
        const webpack = require("webpack");
        const path = require("path");
        module.exports = {
        entry: "./src/index.js",
        output: {
        filename: "main.js",
        path: path.resolve(__dirname, "dist"),
        },
        plugins: [
        new HtmlWebpackPlugin({
        template: "index.html",
        // 自定义版本号,这里可以通过读取文件系统中的版本文件或者其他方式来获取真实的版本号
        version: "2",
        }),
        new webpack.BannerPlugin("版权所有,翻版必究"),
        ],
        };
      • 这个配置文件中的HtmlWebpackPlugin插件可以将版本号插入到 HTML 文件中引用的静态资源 URL 中。
  2. 利用浏览器缓存清除技术(Service Workers)
    • 原理:Service Workers 是一种在浏览器后台运行的脚本,它可以拦截和处理网络请求。通过 Service Workers,可以控制浏览器缓存的清除和更新。当项目更新后,Service Workers 可以检测到新的资源版本,并通知浏览器清除旧的缓存,从而强制刷新页面资源。
    • 示例步骤
      • 首先,在网页中注册 Service Workers:
        if ("serviceWorker" in navigator) {
        navigator.serviceWorker
        .register("service - worker.js")
        .then(function (registration) {
        console.log("Service Worker注册成功");
        })
        .catch(function (error) {
        console.log("Service Worker注册失败: ", error);
        });
        }
      • 然后,在service - worker.js文件中编写缓存管理逻辑。例如,以下是一个简单的缓存更新逻辑:
        self.addEventListener("fetch", function (event) {
        event.respondWith(
        caches.match(event.request).then(function (response) {
        if (response) {
         return response;
        }
        return fetch(event.request);
        })
        );
        });
        self.addEventListener("activate", function (event) {
        var cacheWhitelist = ["v2 - cache"];
        event.waitUntil(
        caches.keys().then(function (cacheNames) {
        return Promise.all(
         cacheNames.map(function (cacheName) {
           if (cacheWhitelist.indexOf(cacheName) === -1) {
             return caches.delete(cacheName);
           }
         })
        );
        })
        );
        });
      • 这里的activate事件处理函数用于在 Service Workers 激活时,清除旧的缓存(不在cacheWhitelist中的缓存)。fetch事件处理函数用于拦截网络请求,首先尝试从缓存中获取资源,如果缓存中没有,则从网络中获取。
  3. 通过 WebSockets 或长轮询进行实时通知(较复杂)
    • 原理:建立一个服务器到客户端的实时通信通道,如 WebSockets 或长轮询。当项目更新时,服务器通过这个通道发送一个通知到客户端,客户端收到通知后,刷新页面或者重新加载相关资源。
    • 示例(以 WebSockets 为例)
      • 首先,在服务器端(假设使用 Node.js 和ws库)建立 WebSockets 服务:
        const WebSocket = require("ws");
        const wss = new WebSocket.Server({ port: 8080 });
        wss.on("connection", function connection(ws) {
        console.log("客户端已连接");
        // 当项目更新时,发送更新通知
        ws.send("update");
        });
      • 然后,在客户端建立 WebSockets 连接并监听更新通知:
        const socket = new WebSocket("ws://localhost:8080");
        socket.addEventListener("message", function (event) {
        if (event.data === "update") {
        location.reload();
        }
        });
      • 这种方法比较复杂,需要在服务器端和客户端都进行额外的配置,但可以实现非常及时的更新通知。