2023-03-08
Node.js
00

目录

前言
实现终端交互选择版本号
跟Shell语言说再见
最后

封面.jpeg

前言

Github Actions实现仓库自动同步Gitee并更新文档 - 掘金 (juejin.cn)文章前言中描述了笔者开源一个工具库。在持续更新库的时候,发现每一次更新medash - npm (npmjs.com)版本时,存在需要手动Git Push、执行rollup打包命令以及更新package.json文件中version字段值等操作。为解放双手,写了50+行代码。

实现终端交互选择版本号

版本号修改只考虑四种情况:

  1. 更新主版本号, 如1.0.0修改成2.0.0
  2. 更新子版本号,如1.0.0修改成1.1.0
  3. 阶段版本号,如1.0.0修改成1.0.1
  4. Beta版本,如1.0.0修改成1.0.0-beta.1

版本号的命名规则是由. 进行拼接,所以可以使用正则将版本信息获取出来。

首先,版本号信息存储在package.jsonversion 字段值中,代码是使用了TypeScript中文网 · TypeScript——JavaScript的超集 (tslang.cn)。Ts执行时,es6模块化会被编译成node环境中支持的CommonJS模块化。即import pkg from "../package.json"; 会被转化成const pkg = require("../package.json") 。 CommonJS标准规定,导入Json文件时,将会有把Json反序列化的操作,所以读取的json 已经被反序列化,不需要再JSON.parse 操作。

TypeScript
import pkg from "../package.json"; const version = pkg.version; const reg = /([1-9])\.([0-9])\.([0-9])(?:(\-\w*)\.([1-9]+))?/g; const execs = reg.exec(version) as Array<any>;

然后,npm install inquirer 安装inquirer ,它是一个提供终端交互的工具包。

按照上述版本修改的四种情况,程序提供的版本号选择列表选择可以分成两种情况:

  1. 版本号含有beta;
  2. 版本号没有含有beta。

是否含有beta,通过对execs[4] 是否存在来判断。

TypeScript
//... const onSelectVersion = async () => { const beta = execs[4]; //处理版本含有beta的情况 const lists = beta ? getBetaVersionLists(beta) : getVersionlists(); inquirer.prompt([{ name: 'list', type: 'list', message: '请选择发布的版本:', choices: lists, default: [lists[0]] }]) //... }

处理含有beta的情况

TypeScript
const getBetaVersionLists = (beta) => ([ getVersion([execs[1], execs[2], execs[3]]), getVersion([execs[1], execs[2], execs[3]]) + `${beta}.${addOne(execs[5])}` ])

处理没有beta的情况

TypeScript
const getVersionlists = () => ([ getVersion([addOne(execs[1]), execs[2], execs[3]]), getVersion([execs[1], addOne(execs[2]), execs[3]]), getVersion([execs[1], execs[2], addOne(execs[3])]) ])

其中getVersionaddOne 方法分别用于拼接完整的版本号和数字+1

TypeScript
const addOne = (num) => Number(num) + 1; const getVersion = ([major, minor, patch]) => `v${major}.${minor}.${patch}`

不存在beta的效果:

存在beta的效果:

注意点:代码语言是使用TypeScript,所以执行时需要ts-node - npm (npmjs.com)工具帮我们编译下。

npm run release 是自定义命令,在文件package.json的scripts下配置即可。

JSON
//... "scripts": { //.. "release": "ts-node scripts/release.ts" }, //...

最后,导入node文件模块,将选择确定后的版本号重新赋值给version,再写入package.json

TypeScript
//... import path from "path"; import fs from "fs"; //... const onSelectVersion = async () => { const beta = execs[4]; //处理版本含有beta的情况 const lists = beta ? getBetaVersionLists(beta) : getVersionlists(); inquirer.prompt([{ name: 'list', type: 'list', message: '请选择发布的版本:', choices: lists, default: [lists[0]] }]).then(async ({ list }) => { pkg.version = list //... fs.writeFile(path.join(__dirname, '../package.json'), String(JSON.stringify(pkg)), 'utf8', async (error) => { if (error) { return; } //... }); }) }

好了,一个版本选择的功能就完成了。

跟Shell语言说再见

版本选择完成,接下来需要处理Git一系列命令提交代码、Git自动打Tag以及向Npm更新等操作。

需要处理命令有:

Bash
git add . git commit -m xx git tag ** git push origin ** //向远程仓库提交tag git push origin branch npm run build //rullop打包 npm publish //npm 发版

其中npm run build 将执行rullop打包

在终端中自动化执行一些命令,这个时候就需要Shell,创建Shell文件去完成对应的逻辑。作为前端工程师就需要去学习下Shell,有学习成本。

秉承能用Js实现的最终用Js实现的想法,node child_process 子进程模块中提供了可执行Shell命令的API。

当然还有更便捷的工具zx,由google开源。

npm i zx安装zx,导入zx,#!/usr/bin/env zx 是zx要求的。

TypeScript
#!/usr/bin/env zx /... import { $ } from 'zx';

正则匹配获取当前Git 分支:

TypeScript
const onSelectVersion = async () => { const beta = execs[4]; //处理版本含有beta的情况 const lists = beta ? getBetaVersionLists(beta) : getVersionlists(); inquirer.prompt([{ //... }]).then(async ({ list }) => { pkg.version = list let branch = await $`git branch`; const { stdout } = branch; const reg = /\*\D(.+)\D/g; branch = (reg.exec(stdout) as any[])[1]; fs.writeFile(path.join(__dirname, '../package.json'), String(JSON.stringify(pkg)), 'utf8', async (error) => { if (error) { return; } //... }); }) }

按顺序执行命令

TypeScript
const onSelectVersion = async () => { //.. inquirer.prompt([{ //... }]).then(async ({ list }) => { //... fs.writeFile(path.join(__dirname, '../package.json'), String(JSON.stringify(pkg)), 'utf8', async (error) => { if (error) { return; } await $`git add .`; await $`git commit -m ${list}`; await $`git tag ${list}`; await $`git push origin ${list}`; await $`git push origin ${branch}`; await $`npm run build&&npm publish`; }); }) }

zx方法$ 原理是使用了 child_process 子进程模块中spawn 方法

到此,一个简简单单的脚本就完成了,算上空行一共就50+行。

最后

实现逻辑非常简单,没有什么难点。工作中肯定也会有一些需要反复做的事件,我们需要多去思考能否将其简化,学会做一个"会偷懒"的工具人。

感谢阅读,文章涉及的代码已开源,欢迎下载尝试release.ts

本文作者:凌览

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!