项目部署以及版本更新检测

简介

在前端开发中,检测网站版本是否有更新是一个非常场景的需求。那么具体有哪些方式可以实现这一需求呢? 下面我就来分享一下我所接触到的方案

部署

部署一个react项目

在开始检测页面版本更新需求之前,我们先使用docker+nginx来部署一波react项目。因为我们需要模拟线上的真实环境。

  1. 创建React项目
ts 复制代码
npx create-react-app version-detect --template typescript

PS:这里我采用pnpm包管理器,脚手架默认采用的是npm包管理器此时通过pnpm import命令将npm项目转为pnpm项目

  1. 编写dockerFile文件用于构建镜像 首先来看一下docker的结构图,如下图可以看出宿主机docker项目之间的依赖关系。那么接下来就来编写dockerFile文件
  • 在项目的根目录创建.dockerignore文件用指定要忽略的文件和目录

    .git
    node_modules

  • 在项目的根目录创建Dockerfile文件用编写指定image的代码。指定镜像分为如下两个步骤
    步骤一: (构建前端静态的资源)

bash 复制代码
# 将node节点命名为builder
FROM node:17-alpine AS builder
# 指定工作目录
WORKDIR /app
# 将当前目录下的所有文件复制到工作目录当中。
COPY . ./
# 安装pnpm包管理器
RUN npm install -g pnpm
# 安装node_modules并且进行打包
RUN pnpm install && pnpm build

PS: FROM ...(基础镜像) AS ...(别名)就是给这个阶段的镜像起个别名,在后面引用这个阶段的镜像时直接使用别名
步骤二: (构建ngnix服务)

ts 复制代码
# 基于nginx镜像构建
FROM nginx:alpine
# 将工作目录设置为nginx静态资源目录
WORKDIR /usr/share/nginx/html
# 删除之前存在的默认文件
RUN rm -rf ./*
# 从builder中将/app/build复制到当前目录里
COPY --from=builder /app/build .
# 全局运行nginx并且关闭进程守护
ENTRYPOINT ["nginx", "-g", "daemon off;"]

最终代码如下:

  • 在项目中执行docker build ~构建镜像我们的镜像.如果你的Dockerfile
erlang 复制代码
docker build -t version-detect-nginx .

构建完成之后,就可以通过docker images命令或者用可视化桌面Docker Desktop看到构建的镜像了

  • 最后通过docker run ~来运行此项目,
ts 复制代码
# docker run 是指通过一个镜像启动一个容器,-p是一个端口映射,容器里面Nginx默认为80, 8080是指定宿主机端口, -d就是后台运行。--name version-detect-project就是定义容器的名字,version-detect-nginx就是指定镜像的名字
docker run  -p 8080:80 -d --name version-detect-project version-detect-nginx

Docker Desktop的用法 最终就可以通过http://localhost:8080/来访问部署好的react项目了

版本检测

通过上面的步骤,我们完成了基于docker+nginx的react项目部署,接下来我们就来实现版本更新检测的功能

唯一hash值

  1. hash文件的生成
    创建hash.js文件,生成一个唯一值用于标识当前版本
ts 复制代码
const crypto = require('crypto');
const fs = require('fs');
const data = crypto.randomBytes(16).toString('hex');
const hash = crypto.createHash('sha256').update(data).digest('hex');
fs.writeFile('./build/hash.txt', hash, (err) => {
  if (err) throw err;
});

修改package.json下的build命令

json 复制代码
 "build": "react-scripts build && node ./hash.js",

运行build命令之后就会生成hash.text文件 2. 在react项目添加轮训,请求hash.text文件。每隔1s请求一次。

ts 复制代码
 const oldHash = useRef(null)
  useEffect(() => {
    loopTimer();
  }, [])

  // 使用setTimeout模拟setInterval
  function loopTimer() {
    let timer: any = null;
    const interval = async () => {
      try {
        const { data } = await axios.get('/hash.txt')
        if (oldHash.current && oldHash.current !== data) {
          console.log('检测到版本更新了');
        } else {
          oldHash.current = data
        }
      } finally {
        timer = setTimeout(interval, 1000);
      }
    };
    setTimeout(interval, 1000);
    return {
      cancel: () => {
        clearTimeout(timer);
      },
    };
  }

重新打包react项目,然后重新部署。可以看到控制台打印了检测到版本更新了字段。然后我们就可以愉快的提示用户刷新页面了

通过HEAD请求

我们也可以通过轮训获取到当前项目协商缓存字段Etag来判断版本是否有更新。因为我们不需要获取到响应体只需要响应头的Etag数据即可,因此采用HEAD方法来实现

ts 复制代码
  // 使用setTimeout模拟setInterval
  function loopTimer() {
    let timer: any = null;
    const interval = async () => {
      try {
        const { headers } = await axios.head('')
        if (oldEtag.current && oldEtag.current !== headers.Etag) {
          console.log('检测到版本更新了');
        } else {
          oldEtag.current = headers.Etag
        }
      } finally {
        timer = setTimeout(interval, 1000);
      }
    };
    setTimeout(interval, 1000);
    return {
      cancel: () => {
        clearTimeout(timer);
      },
    };
  }

更新react项目重新部署之后etag发生了变化,因此就可以判定版本更新了

其他

当然你也可以使用SSE方案由后端主动告知前端版本更新等,本来想用nestJS实现一下的但时间有限,而且也不难可以参考神光大佬的实现方式

PS: 如果公司所有项目都需要检测项目版本是否更新可以编写webpack插件,让插件去注入轮询代码,这样子就不需要自己手动的一个个项目去编写注入了

本文的github demo链接地址

相关推荐
程序员黑豆5 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
To_OC5 小时前
踩了个 TS 的坑之后,我终于把 type 和 interface 掰明白了
前端·react.js·typescript
GreenTea5 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
浮生望6 小时前
前端API工程化:用 Mock 数据与 Axios 配置实现独立于后端的并行开发
前端
万少6 小时前
给 DeepSeek Harness 装个"应用商店":一条命令,595 个插件随你逛
前端·javascript·后端
波波0076 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
Brown.alexis7 小时前
es6知识点1-自备使用
前端·ecmascript·es6
小爬的老粉丝8 小时前
JavaScript 纯前端预览 WPS:先识别容器,再路由解析器
前端·javascript·wps
计算机魔术师8 小时前
新兴多智能体系统的模式与问题
前端
用户059540174469 小时前
AI Agent 上下文污染踩坑实录:用 pytest + Redis 揪出 3 类记忆串号 bug,排查 6 小时
前端·css