年报是否就是在工商网站做的,手机画户型图的软件,深圳十大穷人区,html视频教学有些前端的小伙伴可能会好奇#xff0c;nvm是什么#xff1f;这里接简单介绍下#xff0c;它是一个Nodejs版本管理工具。为什么需要它呢#xff1f;当然是需要多个Nodejs版本的时候#xff0c;那什么时候需要多个Nodejs版本#xff1f;那肯定是在有点年头的公司了#x… 有些前端的小伙伴可能会好奇nvm是什么这里接简单介绍下它是一个Nodejs版本管理工具。为什么需要它呢当然是需要多个Nodejs版本的时候那什么时候需要多个Nodejs版本那肯定是在有点年头的公司了例如vue2的很多依赖都是在Nodejs14年代的如果你升级到Node20那很可能会报错。如果你用vite创建新项目那也肯定是没法在Node14下运行。如果你问为啥要Nodejs欢迎留言或者看一部它的纪录片哈 迭代过快虽然能够享受到各种新科技但对于很多公司来说去适配nodejs版本也是不太值得投入的成本。ε(´ο*)))唉想想前端就累呀 报错信息具体内容
# node -v
node: /lib64/libm.so.6: version GLIBC_2.27 not found (required by node)
node: /lib64/libstdc.so.6: version GLIBCXX_3.4.20 not found (required by node)
node: /lib64/libstdc.so.6: version CXXABI_1.3.9 not found (required by node)
node: /lib64/libstdc.so.6: version GLIBCXX_3.4.21 not found (required by node)
node: /lib64/libc.so.6: version GLIBC_2.28 not found (required by node)
node: /lib64/libc.so.6: version GLIBC_2.25 not found (required by node)
nodejs都不可用更别说构建了如果构建不出东西在这个依赖框架的年代就相当于白干啊突然怀念jquery的时代了(#^.^#)
触发场景 有老的vue项目需要nodejs14 这个必须的18就构建不了有新的vue3项目需要nodejs20 vite需要的ε(´ο*)))唉自己开发是挺爽但没想到CI这里出问题了哈必须要jenkins上部署和构建jenkins跑在linux上之前我被windows server版docker搞的头发掉了一大撮构建物必须是一个docker镜像这几个项目放在一个镜像就是要一次构建多个项目
好像上面是这个时代比较通用的了于是便很自然的安装了nvm构建不同项目之前用nvm切换下。
问题分析
但是当我构建vue3项目是就遇到上面的报错了。呃搜索一通么得什么头绪我发现切回去node16就可以了啊竟然是版本问题后面发现是宿主机的centos版本太低了我的天我没想到一个前端竟然遇到这个问题也算是长姿势了 于是这时候就有个解决办法了那就是让运维的部署点高版本的centos吧提了个需求但不知道何时才能实现等等等 解决办法
看到这里问题大概就是找到了也可以解决了那就是升级centos版本
解决问题思路扩展
在docker容器内构建项目
但是我从第一性原理开始想为啥我需要安装这个Nodejs呢既然产出物是前端代码部署又不需要这个nodejs只需要一个nginx镜像那些构建物构建的时候能不能使用Docker构建只要用不同的镜像去构建不就可以了说干就干。
下面是Dockerfile构建脚本 阶段1构建注意不同的项目修改自己node:版本 这里用到了docker的多阶段构建想了解的可以自己去研究或许后期我会抽空介绍它的好处
# 构建阶段
FROM node:20.16-alpine as builder# 设置工作目录
WORKDIR /app# 复制package.json和package-lock.json如果存在
COPY package*.json ./# 安装项目依赖
RUN npm install# 复制项目文件到工作目录
COPY . .# 构建应用
RUN npm run build这个构建的产出物在镜像内的/app/dist如果是直接docker部署可以使用第二个stage直接复制到新的镜像中但此时为考虑到某些场景需要提取出这个目录就需要一个辅助的nodejs方法
1. 构建
2. 启动容器
3. 复制到目标目录
启动临时容器复制到宿主机目录
一个全功能辅助的nodejs脚本
下面这个方法是一个build.cjs脚本内容构建的时候定义好需要构建的模块然后node build.cjs就可以了这里不展开。
function buildRunCopy(imageName, dockerfileDir, containerDist, outputDir) {// 生成容器名称const containerName container-${imageName};// 构建 Dockerfile 路径和输出目录的绝对路径const dockerfilePath path.resolve(dockerfileDir, Dockerfile);const hostDir path.resolve(outputDir);try {// 创建宿主机目录如果不存在的话if (!fs.existsSync(hostDir)) {fs.mkdirSync(hostDir, { recursive: true });}// 构建 Docker 镜像console.log(Building Docker image...);execSync(docker build -t ${imageName} -f ${dockerfilePath} ${dockerfileDir},{stdio: inherit,cwd: dockerfileDir,});console.log(Docker image built successfully.);// 运行 Docker 容器console.log(Running Docker container...);execSync(docker run --name ${containerName} -d ${imageName});console.log(Docker container started successfully.);// 复制容器内的目录到宿主机目录execSync(docker cp ${containerName}:/${containerDist} ${hostDir});console.log(Files copied successfully.);} catch (error) {console.error(Error: ${error.message});throw error;} finally {// 停止并移除 Docker 容器try {console.log(Removing Docker container...);execSync(docker rm -f ${containerName});console.log(Docker container removed successfully.);} catch (removeError) {console.error(Error removing Docker container: ${removeError.message});}}
}
脚本函数用法举例
下面就是一个例子将项目某个test-app下面的项目进行构建并将其构建物从/app/dist复制到原项目下面的dist目录
// 构建 build.cjs const basePath path.join(projectsBasePath, test-app);const tmpDistFolder path.join(basePath, dist);console.info(清理构建临时目录);fs.rmSync(tmpDistFolder, { recursive: true, force: true });buildRunCopy(test-app, basePath, /app/dist, basePath);
然后就可以实现使用docker构建项目了宿主机的nodejs只需要跑这个脚本构建过程用到的nodejs是来自于容器内的想用啥版本直接修改Dockerfile文件就可了 看完记得活动下脖子这算是我今天的前3.5个小时的总结了...