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

简介

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

部署

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

相关推荐
blackorbird27 分钟前
Edge 浏览器 IE 模式成攻击突破口:黑客借仿冒网站诱导攻击
前端·edge
谷歌开发者1 小时前
Web 开发指向标 | Chrome 开发者工具学习资源 (一)
前端·chrome·学习
名字越长技术越强1 小时前
Chrome和IE获取本机ip地址
前端
天***88961 小时前
Chrome 安装失败且提示“无可用的更新” 或 “与服务器的连接意外终止”,Chrome 离线版下载安装教程
前端·chrome
半梦半醒*1 小时前
zabbix安装
linux·运维·前端·网络·zabbix
清羽_ls2 小时前
React Hooks 核心规则&自定义 Hooks
前端·react.js·hooks
你的人类朋友2 小时前
“签名”这个概念是非对称加密独有的吗?
前端·后端·安全
西陵2 小时前
Nx带来极致的前端开发体验——任务缓存
前端·javascript·架构
Panda__Panda3 小时前
docker项目打包演示项目(数字排序服务)
运维·javascript·python·docker·容器·c#
xx.ii3 小时前
Docker监控
运维·docker·容器