一键publish的node脚本
需求背景
公司有8个前端项目,共使用四个公共包,基础包(baqi)、医生公共包(baqi-doctor)、患者公共包(baqi-patient)、聊天包(baqi-chat)。
开发分支上使用file引入公共包(file引入的方式可以查看这一篇),到测试和生产上需要使用版本号来引入这几个公共包。这就需要一个方便的publish公共包的工具,写了一个node脚本publish.js
实现
主流程:
- 计算下一个版本号
- 设置npm代理为淘宝
- 设置baqi包、baqi-xxx包中package.json的version号
- publish baqi包和baqi-xxx包
- 替换前端8个项目引入baqi包和baqi-xxx包的版本号
- 判断是否安装cnpm,若没安装cnpm,则安装
- 新开4个进程,执行cnpm sync命令,同步新发布的包到淘宝代理
- 新开8个进程,进入8个前端项目执行npm install
需要注意的是:
- 可以使用http的get请求获取npm包的信息,url为http://registry.npm.taobao.org/baqi/latest,其中baqi为包名
- 需要设置taobao的npm代理,不然执行npm命令进程偶尔会卡住
- 设置taobao代理后无法publish,在publish时指定registry为npmjs官方url
- publish和进入各项目执行npm install时可以开多个进程执行,提高效率,使用
await Promise.all(promiseArr)
保证执行顺序 - 如在linux下使用,路径会错误,可以使用
path.sep()
来代替路径的斜杠 - 使用
process.cwd()
来代替__dirname
,减少因路径带来的问题
package.json增加执行脚本
"scripts": {"pb": "node bin/publish.js"
},
使用方法
npm run pb <version>
version可选,若输入version,按照指定的版本号publish,若不输入version,自动计算版本号
代码
主流程代码
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const { getRequest, execCmdSync, execCmd } = require('./util')const cwd = process.cwd()
const modules = ['baqi', 'baqi-chat', 'baqi-doctor', 'baqi-patient']
const projects = ['doctor_web','patient_web','heart-doctor','heart-patient','tumour-doctor','tumour-patient','mini-hospital','mh-doctor'
]
let version = process.argv[2]main()async function main () {if (version === undefined) {console.log('查找版本号!')version = await computeVersion()console.log('版本号为:' + version)}console.log('设置npm代理')execCmdSync('npm config set registry https://registry.npm.taobao.org')console.log('替换baqi包、baqi-xxx包的version号\n将baqi-xxx包中引入baqi的方式替换成version引入')for (let i = 0; i < modules.length; i++) {replaceVersionAndImport(modules[i])}console.log('publish baqi包和baqi-xxx包')const publishArr = []for (let i = 0; i < modules.length; i++) {console.log('正在publish ' + modules[i])const cdPath = path.join(cwd, '../' + modules[i])publishArr.push(execCmd('cd ' + cdPath + ' && npm publish --registry http://registry.npmjs.org'))}await Promise.all(publishArr) // 不catch,报错就中断console.log('将baqi-xxx包中引入baqi的方式替换成file引入')for (let i = 1; i < modules.length; i++) {replaceImportToFile(modules[i])}console.log('替换所有项目引入baqi包和baqi-xxx包的版本号')for (let i = 0; i < projects.length; i++) {replaceImport(projects[i])}console.log('判断是否安装cnpm')checkCnpm()console.log('新开4个进程,同步cnpm')let cnpmSyncArr = []for (let i = 0; i < modules.length; i++) {cnpmSyncArr.push(execCmd('cnpm sync ' + modules[i]))}await Promise.all(cnpmSyncArr) // 不catch,报错就中断console.log('新开8个进程,进入各项目执行npm install')const npmInstallArr = []for (let i = 0; i < projects.length; i++) {const lockFilePath = path.join(cwd, '../' + projects[i] + '/package-lock.json')if (fs.existsSync(lockFilePath)) {console.log('删除文件' + lockFilePath)fs.unlinkSync(lockFilePath)}const cdPath = path.join(cwd, '../' + projects[i])npmInstallArr.push(execCmd('cd ' + cdPath + ' && npm install'))}try {await Promise.all(npmInstallArr)} catch (e) {console.error(e)}console.log('----------搞定了----------')
}
其他函数代码
function checkCnpm () {try {const out = execCmdSync('where cnpm')if (out.startsWith('信息')) {execCmdSync('npm install -g cnpm')}} catch (e) {execCmdSync('npm install -g cnpm')}
}async function computeVersion () {let maxVersion = ''for (let i = 0; i < modules.length; i++) {const moduleInfo = await getRequest('http://registry.npm.taobao.org/' + modules[i] + '/latest')const packageVersion = moduleInfo.versionif (packageVersion > maxVersion) {maxVersion = packageVersion}}let lastVersion = parseInt(maxVersion.substring(maxVersion.lastIndexOf('.') + 1)) + 1maxVersion = maxVersion.substring(0, maxVersion.lastIndexOf('.') + 1) + lastVersionreturn maxVersion
}function replaceImportToFile (moduleName) {let filePath = path.join(cwd, '../' + moduleName + '/package.json')let fileStr = readPackageJson(filePath)fileStr = fileStr.replace(/("baqi"\s*:\s*").*?(")/g, '$1file:../baqi$2')writePackageJson(filePath, fileStr)
}function replaceImport (projectName) {let filePath = path.join(cwd, '../' + projectName + '/package.json')let fileStr = readPackageJson(filePath)fileStr = fileStr.replace(/("baqi.*\s*:\s*").*?(")/g, '$1' + version + '$2')writePackageJson(filePath, fileStr)
}function replaceVersionAndImport (moduleName) {let filePath = path.join(cwd, '../' + moduleName + '/package.json')let fileStr = readPackageJson(filePath)fileStr = fileStr.replace(/("version": ").*?(")/, '$1' + version + '$2')fileStr = fileStr.replace(/("baqi.*\s*:\s*").*?(")/, '$1' + version + '$2')writePackageJson(filePath, fileStr)
}function writePackageJson (packageJsonPath, str) {fs.writeFileSync(packageJsonPath, str, 'utf8')
}function readPackageJson (packageJsonPath) {const fileStr = fs.readFileSync(packageJsonPath, 'utf8')return fileStr
}
util.js
const http = require('http')
const execSync = require('child_process').execSync
const exec = require('child_process').execfunction execCmdSync (cmdStr) {console.log('执行:' + cmdStr)const out = execSync(cmdStr, { encoding: 'utf8' })return out
}
function execCmd (cmdStr) {return new Promise((resolve,rejcect) => {console.log('执行:' + cmdStr)exec(cmdStr, { encoding: 'utf8' }, function (error, stdout, stderr) {error ? rejcect(error) : resolve(stdout)})})
}
function getRequest (url) {return new Promise(resolve => {console.log('请求URL:' + url)http.get(url, res => {let html = ''res.on('data', function (data) {html += data})res.on('end', function () {console.log('返回:' + html)try {resolve(JSON.parse(html))} catch (e) {resolve(html)}})})})
}
module.exports = {exec,execCmd,getRequest
}
结语
实现了一键发布4个公共包并且修改引用的功能,但有时候只改动某一个地方确要发布4个公共包,下一步计划增加只发布某一个公共包的功能
一键publish的node脚本相关推荐
- JAVA包可以构建一个子系统_Windows 10 用于 Linux 子系统的一键构建、打包脚本「 Node、Gradle 项目」...
最近正在开发一个 Java & Vue.js 全栈项目,该项目由以下几部分组成:Java 后端服务器.基于 Vue.js 的单页应用.基于 JavaFX 的 GUI 客户端以及其他辅助工具等. ...
- rancher 一键安装集群脚本
rancher 一键安装集群脚本 注意:操作系统任意如果是centos8需要更换yum源 cd /etc/yum.repos.d/sed -i 's/mirrorlist/#mirrorlist/g' ...
- android批处理脚本,BAT批处理一键生成APK包脚本分享
BAT批处理一键生成APK包脚本分享 将本bat放到cocos2dx目录下你的工程的project.android下(需修改变量). ASmaker 用来将Resources文件夹下的lua文件批量加 ...
- (压缩包在本地目录或由链接请求)使用jszip解压文件或compressing解压文件到指定目录,写个node脚本
使用jszip解压文件与compressing解压zip文件到指定目录 一.介绍jszip和compressing模块 jszip和compressing模块都是可以压缩和解压缩zip文件,都可以通过 ...
- centos 一键安装配置nginx脚本
centos 一键安装配置nginx脚本 installNginx.ssh 用vi或则vim编辑 installNginx.ssh #!/bin/bash # author:kwin # Email: ...
- 一键部署LNMP平台脚本
分享一个一键部署LNMP平台脚本,设置通过systemd管理Nginx服务,好用! #!/bin/bash yum -y install gcc openssl-devel pcre-devel ta ...
- Linux系统一键安全加固shell脚本编写思路
本次分享一下个人在对Linux系统一键安全加固shell脚本编写时的一些思路: Linux系统一键安全加固shell脚本编写思路 1.编写须知 1.1 脚本使用说明 1.2 主要功能说明: 1.3隐藏 ...
- 表妹求我写个node脚本,把java错误码表转成excel并翻译成英文
java原始代码部分如下 public static final int ERR_ONLINE_DECLINED = 1025; //交易联机拒绝//public static final int E ...
- 一键系统优化15项脚本
一键系统优化15项脚本,适用于Centos6.x 按 Ctrl+C 复制代码 #!/bin/sh ################################################ #A ...
最新文章
- LeetCode简单题之石头与宝石
- float python_Python中float('INF')的使用
- QQ号码采集及邮件发送系统2009
- 【CodeForces - 215B 】Olympic Medal (数学,公式推导)
- Android深入浅出之Binder机制(转)
- ajax get post
- hibernate和struts实现分页
- Halcon:立体匹配
- python爬虫可以做哪些好玩的地方_如何快速的找到好玩的旅游景点信息?Python爬虫帮你轻松解决...
- 简单的时间间隔调度任务
- 织梦内核PHP在线教育知识付费课程分销网站源码 带手机端+集成支付功能
- android 蓝牙耳机 找不到驱动程序,bluetooth外围设备,详细教您bluetooth外围设备找不到驱动程序怎么解决...
- 5.5 设置UITableView单元格背景色 [原创iOS开发-Xcode教程]
- 转自随风飘荡自由飞翔 SQL技巧:快速把握一些异常精妙的SQL语句
- 在 Android 设备上搭建 Web 服务器
- 超赞 不愧是美团内部的JVM学习手册,从头到尾全是精华
- 牛客网-密码检查-小明同学最近开发了一个网站,在用户注册账户的时候,需要设置账户的密码,为了加强账户的安全性,小明对密码强度有一定要求:。。。。。
- 帝国推送插件-免费帝国CMS实时推送插件
- 【已解决】App unavailable Unfortunately, Claude is only available in certain countries and regions
- IO接口标准(3):HCSL和LPHCSL
热门文章
- try/except...else
- Git 实现原理,你真的了解吗?
- ip68级防水可以泡多久_IP68级别的防水遇水就废,明明只防水溅,为什么还大肆宣传防水!...
- idea自动补全对象或方法返回的对象
- 英雄联盟手游国服内测服务器维护,英雄联盟手游国服内测资格怎么获得 国服内测资格获取方法一览...
- PS 滤镜——极坐标变换到平面坐标
- C语言打印输出杨辉三角案例讲解
- 备忘录系统——需求篇
- elementui 表格表头竖着显示_elementUI Table表格表头自定义
- Face Alignment in Full Pose Range: A 3D Total Solution(3DDFA)论文与项目学习