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

简介

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

部署

部署一个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链接地址

相关推荐
星就前端叭1 小时前
【开源】一款基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间项目
前端·后端·开源·webrtc
m0_748234521 小时前
前端Vue3字体优化三部曲(webFont、font-spider、spa-font-spider-webpack-plugin)
前端·webpack·node.js
Web阿成1 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript
jwensh2 小时前
【Jenkins】Declarative和Scripted两种脚本模式有什么具体的区别
运维·前端·jenkins
关你西红柿子2 小时前
小程序app封装公用顶部筛选区uv-drop-down
前端·javascript·vue.js·小程序·uv
益达是我2 小时前
【Chrome】浏览器提示警告Chrome is moving towards a new experience
前端·chrome
济南小草根2 小时前
把一个Vue项目的页面打包后再另一个项目中使用
前端·javascript·vue.js
聪小陈2 小时前
圣诞节:记一次掘友让我感动的时刻
前端·程序员
LUwantAC2 小时前
CSS(一):选择器
前端·css
Web阿成2 小时前
5.学习webpack配置 babel基本配置
前端·学习·webpack