前端项目发布后,如何使正在使用的用户更新为最新的版本?

news2024/11/19 18:31:31

1.背景

  • 每次项目上线后,异常监控总是零零散散报一些资源加载或者解析失败的告警
    在这里插入图片描述
  • 仔细对比chunk的hash值会发现已经是上一版本的js文件
  • 为什么会出现这个问题呢?也不难想到,项目是单页应用,页面使用懒加载分多个chunk打包,首次只加载首页需要的js文件。如果在项目发布前,用户已经在程序中,并且还有未访问的页面,此时我们重新发布上线了,老的文件已经被覆盖,用户再访问未访问过的页面时就会找不到资源,导致白屏。
  • 如果用户在发布前已经进入过其他页面,被缓存在本地,这样虽然不会导致白屏了,但是也无法看到最新的效果。
  • 在测试环境模拟一下,点击一个未访问过的页面时,确实白屏了,报错信息也吻合
    在这里插入图片描述

2.解决思路

  • 导致这些问题的根本原因就是,用户和程序都无法感知项目已上线,无法做到立即刷新,重新加载,那我们就想办法在项目上线后通知页面进行刷新。

2.1运行中的项目,如何感知到项目更新了

  • 最容易想到的就是有一个存储版本号的地方,我们去轮询是否和上一次请求到的版本一致,如果不一致去做一些刷新的操作
  • 既然是前端的项目,最好还是我们自己去维护这个数据,所以我选择在每次打包的时候生成一个存储当前时间戳的json文件,存在dist目录下一起放到我们前端服务器上。
  • 写一个最最简单的webpack插件帮我们实现生成json文件的功能
const pluginName = 'GenerateTimeJsonWebpackPlugin';
const fs = require('fs');
const path = require('path');

class GenerateTimeJsonWebpackPlugin {
  apply(compiler) {
    compiler.hooks.run.tap(pluginName, (compilation) => {
      const filePath = path.resolve('build', 'timeStamp.json');
      fs.writeFile(filePath, `${JSON.stringify({time: new Date().getTime()})}`, (err) => {
        console.log(err);
      });
    });
  }
}

module.exports = GenerateTimeJsonWebpackPlugin;
  • 这样每次构建时就会多一个文件
    在这里插入图片描述
    在这里插入图片描述

2.2什么时机判断是否更新?

  • 轮询肯定是最耗性能的,间隔太小浪费,间隔太大又有白屏的风险
  • 由于我们出现请求页面的时机总是在页面加载的时候,所以选择加一个路由守卫,在页面跳转前判断是否更新,如果更新了就reload页面。
  • 项目是用react进行开发的,所以写个高阶组件来实现守卫的功能
import { Route } from 'react-router-dom';
import { useRef, useState } from 'react';
import axios from "axios";
const basePath = '/mp/138519745866498048/368331042878263296/credit-shop/';

// 路由守卫
const BeforeRouteEnter = (props) => {
  const {path, exact, component} = props;

  // 用来控制在时间戳未请求到时,不加载路由对应的页面,避免请求到老的资源
  const [loading, setLoading] = useState(process.env.NODE_ENV === 'production');

  // 用来存储当前项目的时间戳
  const timesTamp = useRef('');
  
  // 生产环境需要判断 当前访问的chunk是否已经更新
  if (process.env.NODE_ENV === 'production') {

    // 由于项目中统一封装过的axios做了很多错误的处理 为了不影响正常页面的功能 选择单独使用axios请求
    axios
      .get(basePath + `timeStamp.json?t=${new Date().getTime()}`)
      .then(res => {

        // 判断是否已经更新了代码 更新了就重新加载页面 请求新的资源
        if (timesTamp.current && (timesTamp.current !== res.data?.time)) {
          window.location.reload();
        }
        timesTamp.current = res.data?.time;
        setLoading(false);
      }).catch(err => {
        setLoading(false);
      });
  }
  return !loading ? <Route path={path} exact={exact} component={component}></Route> : ''

}
export default BeforeRouteEnter;

然后将Route组件改成我们自己封装的BeforeRouteEnter,这样在每次跳转前都请求一次当前打包的时间戳,判断是否和正在运行中的一致,不一致就重载,这样一来就解决了我们的问题~

有问题欢迎大家及时指出,避免误导其他同学~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/191525.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SDP零信任网络安全架构

安全狗零信任SDP接入解决方案基于“以身份认证为中心&#xff0c;以信任为基础&#xff0c;持续动态授权认证”的理念&#xff0c;打造企业全方位立体业务访问安全体系。 其SDP零信任网络安全架构如下图&#xff1a; SDP零信任产品优势 1、多维度终端环境感知 系统风险感知&…

浅谈--声调

声调 根据声调的有无&#xff0c;我们可以把世界上的语言分为声调语言和非声调语言两大类。 非声调语言&#xff0c;并不是说音节没有高低升降的音高变化&#xff0c;只是这种变化只能改变语气作用&#xff0c;并不能区别意义。如&#xff1a;在英语单词book&#xff0c;音高…

Nacos 初始

1.Nacos 的安装使用。 nacos的安装步骤 1.端口配置 Nacos的默认端口是8848&#xff0c;如果你电脑上的其它进程占用了8848端口&#xff0c;请先尝试关闭该进程。 如果无法关闭占用8848端口的进程&#xff0c;也可以进入nacos的conf目录&#xff0c;修改配置文件中的端口&am…

(考研湖科大教书匠计算机网络)第三章数据链路层-第五节:点对点协议PPP

专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;点对点协议&#xff08;PPP&#xff09;概述二&#xff1a;PPP协议组成部分三&#xff1a;PPP协议帧格式四&#xff1a;PPP协议的透明传输&#xff08;1&#xff09;字节填充法…

磨金石教育摄影技能干货分享|优秀摄影作品如何表现创意与思想的

在摄影活动中并不是简单的利用镜头把事物拍下来&#xff0c;而是要尽量的融入作者对当时当地事物的情意表达出来。利用摄影技术&#xff0c;因时制宜展现个人的创意&#xff0c;然后表达自己的思想。下面给大家分享一组摄影大赛获奖作品&#xff0c;看看这些获奖作品如何做到的…

vue(iviewui) 输入框历史记录

安装&#xff1a;npm install good-storage -S 缓存cache.js: /*把搜索的结果保存下来*/ /*用export把方法暴露出来*/ /*定义存储搜索的key _search_定义内部使用的key*/ let searches_list [] const SEARCH_MAX_LENGTH15 /*插入方法 arr存储的数据 val传入存储的值 comp…

leetcode-每日一题-1664-生成平衡数组的方案数(中等,动态规划)

时间长不做动态规划的题目&#xff0c;现在突然看过去有些生疏&#xff0c;第一眼看到这个题目想了一下暴力&#xff0c;然后突然注意到了题目的难度是中等&#xff0c;力扣里面的中等难度的题目都是没有暴力可以做出来的&#xff0c;目前我做这么多题来看的话&#xff0c;第一…

StarRocks荣获开源中国“2022 年度优秀开源技术团队”

近日&#xff0c;国内知名开源技术社区开源中国&#xff08;OSCHINA&#xff09;&#xff0c;综合了平台上各大认证官方技术团队、开源社区账号年度发表的内容频率及质量、开展各种活动运营积极性等多方面表现&#xff0c;向StarRocks颁发了 OSCHINA“2022年度优秀开源技术团队…

编译原理学习笔记19——语义分析和中间代码生成4

编译原理学习笔记19——语义分析和中间代码生成419.1 常用的控制语句19.2 控制语句的属性文法19.3 控制语句的属性计算19.4 一遍扫描翻译控制语句19.5 一遍扫描翻译控制语句示例19.1 常用的控制语句 常用的控制语句 S → if E then S1S → if E then S1 else S2S → while E …

机器学习笔记之生成对抗网络(二)全局最优解的求解逻辑

机器学习笔记之生成对抗网络——全局最优解的求解逻辑引言回顾&#xff1a;生成对抗网络的判别过程关于生成对抗网络的一些特性最优解的求解过程引言 上一节介绍了生成对抗网络&#xff0c;并介绍了其判别过程&#xff0c;本节将介绍关于模型参数的求解逻辑。 回顾&#xff1…

建立建筑领域科学的碳排放核算方法(江亿)

中国工程院院士、清华大学江亿教授受邀参加2022年12月28日“2022中国建筑节能协会年会暨第五届全国建筑节能与绿色建筑技术创新大会”并作了题为“建立建筑领域科学的碳排放核算方法”的报告。 实现能源转型&#xff0c;由碳基能源转为零碳能源&#xff0c;是中央确定的未来战…

九龙证券|锂离子电池在安全性能上应当满足哪些条件?

锂离子电池具有分量轻、容量大、无回忆效应等优势&#xff0c;因而得到了普遍运用——今朝的许多数码设备都采用了锂离子电池作电源&#xff0c;虽然其价格相对来说比较昂贵。锂离子电池的能量密度很高&#xff0c;它的容量是同分量的镍氢电池的1.5~2倍&#xff0c;而且具有很低…

Redis集群搭建

Redis集群搭建1.单机安装Redis2.Redis主从集群2.1.集群结构2.2.准备实例和配置2.3.启动2.4.开启主从关系2.5.测试3.搭建哨兵集群3.1.集群结构3.2.准备实例和配置3.3.启动3.4.测试4.搭建分片集群4.1.集群结构4.2.准备实例和配置4.3.启动4.4.创建集群4.5.测试基于CentOS7下的Redi…

数据库session分析表

目录 Active Session 活动会话 gv$active_session_history 每秒采集一次 dba_hist_active_sess_history 每10秒采集一次 背景 说明&#xff1a; 常用sql 直接使用V$ACTIVE_SESSION_HISTORY的sql 与其他表和视图共同查询…

神经网络数学原理与编码逻辑(一) 无隐层模型

概述 几年前就想写这篇文章&#xff0c;但是要上班应付各种工作内容&#xff0c;在解析神经网络的理论问题上也是断断续续&#xff0c;加上个人能力有限&#xff0c;很多问题并没有研究的很明白&#xff0c;以及神经网络本身高维问题的复杂性&#xff0c;导致这个问题的理解也…

OAuth2代码流程演示

目录 一&#xff0c;创建项目 二&#xff0c;项目结构 一&#xff0c;创建项目 新建项目时&#xff0c;如果换了工作区间我们一定要记得改maven地址&#xff0c;不然下载插件时不仅占用C盘内存&#xff0c;还会下载的很慢。 导入项目 导入新项目后就会下载新的插件&#xf…

消息队列简介

提高系统性能首先考虑的是数据库的优化&#xff0c;之前一篇文章《数据库的使用你可能忽略了这些》中有提到过开发中&#xff0c;针对数据库需要注意的事项。但是数据库因为历史原因&#xff0c;横向扩展是一件非常复杂的工程&#xff0c;所有我们一般会尽量把流量都挡在数据库…

Unity可用 运行时语音合成(文本转语音)插件 RT-Voice PRO

Unity语音合成文本转语音插件 RT-Voice PRO前言一、导入RT-Voice PRO插件二、使用步骤1.先看自带例子&#xff08;01-Speech&#xff09;2.自行配置总结前言 提示&#xff1a;这个插件在Unity Asset Store 卖 78美刀,确实买不起啊。 &#x1f602; AssetStore下载链接 文章最后…

复试数据结构篇[第5章-第6章]

文章目录第五章 数组和广义表1-数组定义2-数组的顺序表示3-矩阵的压缩存储&#xff08;1&#xff09;对称矩阵和三角矩阵&#xff08;2&#xff09;对角矩阵&#xff08;3&#xff09;稀疏矩阵&#xff08;3&#xff09;十字链表4-广义表的定义串、数组、广义表小结第六章 树与…

JVM的类加载

什么是类加载&#xff1f;java程序运行前&#xff0c;要经过编译即.java>.class文件。运行的时候java进程(JVM)就会读取对应的.class文件&#xff0c;并解析内容&#xff0c;在内存中构造出类对象并进行初始化&#xff08;类对象就是描述这个类有哪些属性&#xff0c;哪些方…