大家好,我是 那个曾经的少年回来了
。10年前我也曾经年轻过,如今已步入被淘汰的年龄,但现在幡然醒悟,所以活在当下,每天努力一点点,来看看2024年的时候自己会是什么样子吧,2024年的前端又会是什么样子,而2024年的中国乃至全球又会变成什么样子,如果你也有想法,那还不赶紧行动起来。期待是美好的,但是更重要的是要为美好而为之奋斗付诸于行动。
1、前言
由于正在负责的一个项目,就说前端涉及到PC端、公众号端、APP端的H5、小程序端、可视化大屏端,而PC和APP又通过qiankun引入了微前端的理念。整体一圈下来可能光前端编译打包就要build差不多二十次。而有时候经常性的bug改动,这个时候便只需要进行测试后需要进行小范围的测试。
还有一个不得不说,用JavaScript就能写出自动化编译打包的脚本,对于一个前端程序猿来说还是非常的nice。上手也是非常的快。欢迎你也来一起体验加入。
先说一下目前我代码里已经实现的功能 我已将所有代码上传到github了,github地址:github.com/aehyok/zx-d… ,有兴趣的话可以一起研究学习一下
2、实现的功能
2.1、 拉取代码
实现cd到应用后,先git pull拉取代码(没有实现安装依赖的功能,需要手动实现检查)
export const gitPullBy = async(projectName: string, path: string) => { try { writerLog(projectName, `git pull start`, global.version); const gitPullInfo = await $`cd ${path}; git pull;`; console.log(gitPullInfo, "pullInfo"); if (gitPullInfo.exitCode === 0) { writerLog(projectName, `git pull end success`, global.version); } else { console.log("fail", $`$?`); } } catch { writerLog(projectName, `git pull error`, global.version); } };
这里目前可以进行优化处理:比如配置好git仓库地址和对应所在目录后,再自动安装依赖,build编译打包项目
2.2、设置版本号
这里简单啰嗦一下,比如在我们前端项目中一般都有一个显示版本号的地方,可能在设置中,或者我的最下面的某个地方。这是我目前开发的一个项目,如下图所示是微信小程序中显示版本号的地方
首先我通过 standard-version
这个依赖来更新版本号,自动根据当前版本号进行匹配生成。 我的版本号是通过读取package.json中的version的,所以我可以上面 2.1、
拉取代码后,通过代码先将package.json
中的 version版本号进行修改
// 显示版本号的地方 // 引入package.json文件 import config from '../../package.json' this.version = config.version
export const updateVersion = (path: string) => { cd(`${ path }`); const packageString = fs.readFileSync(`${path}\\package.json`).toString(); let packageJson = JSON.parse(packageString) packageJson.version = global.version; fs.writeFileSync(`${path}\\package.json`, JSON.stringify(packageJson, null, 2)) }
主要通过 nodejs
的 fs
模块的 readFileSync
,读取package.json文件,转换为JSON对象,进行修改,然后再通过 fs
模块的 writeFileSync
将版本号写回。
当然版本号的获取还有别的很多方式,这里只是我自己想出来比较简单的一种方式,如果你有更简单的方式,咱们可以留言学习一波。
2.3、编译打包项目
修改完前端项目的版本号以后,就是要对项目进行build编译打包了
export const yarnBuildBy = async (path: string) => { try { oneLogger(`yarn build start ${path}`); const buildInfo = await $` cd ${path};yarn build;`; console.log(buildInfo, "buildInfo"); if (buildInfo.exitCode === 0) { oneLogger(`yarn build end success`); } else { oneLogger(`yarn build error: ${buildInfo.stderr}`); } } catch(error) { console.log('yarn build error', error) oneLogger("yarn build error"); } }
这里我目前使用的 yarn build
进行编译前端项目,根据具体的项目可以进行适当的修改,或者进行配置即可。
2.4、对代码仓库进行git tag打标签
因为有时候编译打包后,可能会发现线上的版本代码是有bug的,那么就需要对线上版本的代码进行bug的修复,如果我们自动打好标签,跟线上版本比对后,直接根据当前线上版本的tag生成对应分支的代码即可。
const addTag = async (path: string, isExist: boolean) => { const result = await $` cd ${path}; git tag -a ${global.version} -m 'chore:version ${global.version}版本号'; git push origin ${global.version};`; if (result && result.exitCode === 0) { if (isExist) { await oneLogger(`re create tag [${global.version}] success`); } else { await oneLogger(`create tag [${global.version}] success`); } } };
这里我只是简单的进行tag的标记,并推送,其实我们在打tag的时候,首先要尽量检查一下tag是否已经存在,如果存在,考虑一下是否删除重新生成,或者使用新的tag名称等等。
其实这里有一个注意事项: tag标签和分支名称进行不要重复,首先说明一下重复是没问题的,毕竟一个是tag标签,一个是分支,但是有时候我们推送代码的时候没有明确的指定 就会出现问题。当然如果你的git 操作的非常流弊,各种姿势都非常熟练,那肯定是没问题的。比如像我可能就会注意一下尽量保证分支名和tag标签名是不一致的,避免后期产生一些头疼的问题。
2.5、推送源代码到git仓库
上面我们的git tag其实就已经推送到了代码仓库,道理是一样的,加入上面修改版本号以后,我们想将代码文件推送到仓库
const message=`chore: ${buildProject}::commit-version-${global.version}` const result = await $`cd ${releasePath}; git add . ; sleep 3; git commit -m ${message}; git push origin;` if(result && result.exitCode === 0 ) { await writerLog(name, `git push end success`, global.version); } else { await writerLog(name, `git push error: ${result.stderr}`, global.version); }
这里我一键三连, git add .
git commit
git push
中间使用sleep 3,沉睡了三秒钟,这样执行 git commit
的时候一般不会出现问题。
2.6、拷贝编译后的打包文件
代码打包编完成之后,是在本地服务器指定位置,假如我们想拷贝到远程服务器
export const copyFile = async() => { try { const path = global.project.projectName const ipAddress = 139.9.184.171 // const ipAddress = '139.9.184.171' const result = await $`scp -r /e/work/git-${global.environment}/release/cms/${path}/* root@${ipAddress}:/usr/local/sunlight/dvs/dvs-ui/${path}/` if(result.exitCode === 0) { oneLogger(`copy file [${global.version}] end success`) } else { console.log("fail", $`$?`); } } catch { oneLogger(`copy file [${global.version}] end error`) } }
这里我是将本地代码拷贝到了远程的linux服务器,可以将本地的ssh秘钥拷贝到远程服务器的指定目录。
2.7、将编译的项目文件,单独存放到一个代码仓库
比如这个仓库叫 release
仓库
因为有时候一个项目可能涉及到多个端的代码,比如PC有项目,APP的H5也有项目,而小程序里也有H5的项目要打包,项目大了以后,整个编译打包也变的复杂多变,这样就有一个单独仓库当前项目打包编译后的仓库,方便记录,以及回滚,单独某个小项目发布的需求。
这里的代码就比较简单了,上面的代码中也有提到,其实就是将一键三连将代码提交并推送到远程git仓库
export const gitPullBy = async(projectName: string, path: string) => { try { writerLog(projectName, `git pull start`, global.version); const gitPullInfo = await $`cd ${path}; git pull;`; console.log(gitPullInfo, "pullInfo"); if (gitPullInfo.exitCode === 0) { writerLog(projectName, `git pull end success`, global.version); } else { console.log("fail", $`$?`); } } catch { writerLog(projectName, `git pull error`, global.version); } };
其实我这里想了一下,如果对打包编译后的仓库,也打包tag标签,保证线上版本和这个release仓库的,再做一个历史记录进行保存,这样其实很容易方便回滚,比如当前发布的版本是3.5.1,可是突然发现了重大问题,必须回滚,这个时候就需要将线上的版本马上回滚到3.5.0,OK,那么现在马上拉取release仓库中的 tag标签为3.5.0的仓库代码即可。感觉上好像没什么问题。
同时服务器也可以进行历史版本的备份动作,方便回滚操作。
2.8、后端编译也是完全没有问题的
主要就是对构建流程的梳理而已,跟前后端其实是没关系的。
import { $ } from 'zx' import { gitPull } from './utils/git-pull.mjs'; const path = "/H/work/dvs/server-csharp/" const collectPath= path + "Services/DVS.Collect.API" // await gitPull(); const buildInfo = await $`cd ${collectPath}; dotnet publish -o ../../publish/dvs-collect -f net6.0 -r linux-arm64 --no-self-contained;`; if(buildInfo.exitCode === 0) { console.log("build info ok") } else { console.log(`build info error: ${buildInfo.stderr}`) } const buildpath = 'dvs-collect' const ipAddress = '139.9.184.171' // 139.9.184.171 // 121.37.222.1 const result = await $`scp -r /h/work/dvs/server-csharp/publish/${buildpath}/* root@${ipAddress}:/usr/local/sunlight/dvs/${buildpath}/` if(result.exitCode === 0) { console.log(`copy file end success`) } else { console.log("fail", $`$?`); } // 可以执行本地的server.sh脚本指令 (-t保持登录状态 ssh -t root@139.9.184.171 < server.sh) // 还可以添加脚本参数 const login = await $`ssh root@${ipAddress} < server.sh` if(login.exitCode === 0) { console.log(`ssh login success`) } else { console.log("fail", $`$?`); }
运行完本地的打包编译后,登录远程,并执行server.sh,比如来执行服务的重启等。
3、goploy
来看看这个产品,它在github上是有开源的,开箱即用,简单部署一下就可以使用,感觉还是非常方便的,这是我在自己的window本机部署了一套环境,其实跟我自己写的有很多功能是重复的,当然我做的还算是比较陋跟大佬简直不可比拟,使用上更加的人性化,毕竟通过操作界面就可以完成
github开源地址: github.com/zhenorzz/go…
前端采用的Vue3+TypeScript+ Element-plus 这个前端技术跟我还是非常的匹配,后端采用的是大热的go语言,这个对我来说可能难度稍微大了一些,毕竟没接触过。不过我觉得可能经过一个周左右的时间,应该看懂一点代码,应该问题不大吧,猜测的 当然可能是自己太自信了 哈哈, 明年有时间的话会将这个工具结合自身的使用进行升级一波。可能更贴合于现在公司的使用场景吧。
当然了目前公司也使用了这个工具,已经极大的简化了部署的繁杂,应该说是节省了很多的时间,而且按照这个步骤来,很多时候是不容易出错的。
4、总结
目的就是为了让那些重复性的工作,慢慢的通过工具来替代,将节省下来的时间去研究更有意义的事情,或者去摸摸鱼划划水,是不是更香呢?当然记得不要告诉老板哟? 哈哈 开个玩笑
我的个人博客:vue.tuokecat.com/blog
我的个人github:github.com/aehyok
我的前端项目:pnpm + monorepo + qiankun + vue3 + vite3 + 工具库、组件库 + 工程化 + 自动化
不断完善中,整体框架都有了
在线预览:vue.tuokecat.com
github源码:github.com/aehyok/vue-…