nodejs利用readline提示输入内容实例代码
前言
最近进行小版本发包测试时忘记修改版本号了,进而想到在打包前提示输入版本号,然后把版本号打进版本说明内。最终效果为双击bat文件在终端内提示输入版本号,输入完成后保存版本号。
虽说批处理也可以做这事,但用js来写更得心应手点,故选用js处理。
过程分为四步
- bat执行js
- 终端提示输入版本号、执行打包命令
- 修改版本号文件
- gulp读取版本号json文件
简单来说是用bat文件触发打包命令进行打包。
1. bat执行js
首先创建两个文件buildVersion.bat、buildVersion.js。
buildVersion.bat中使用node运行js文件
@echo off set curpath=%~dp0 %curpath%nodejs\node.exe %curpath%buildVersion.js pause
%~dp0为当前目录。也可以在js后面传参数,如--buildType default
2. 终端提示输入版本号、执行打包命令
使用readline实现问答效果,再用child_process执行打包命令行。
进入buildVersion.js文件,先写简单的提示输入效果。
const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.question(`请输入新版本号: `, (name) => { });
这样达不到效果。我们先显示之前的版本号,然后再提示输入新版本号,而且输入为空时沿用上次版本号。
// 获取版本信息,具体实现在第三步 var versionInfo; const versionInfoUrl = './src/config/version/version.js'; function getVersion() { var buildVersion = ""; try { versionInfo = require(versionInfoUrl); buildVersion = versionInfo.version; } catch (error) { } return buildVersion; }
提示输入变成这样
const chalk = require('chalk'); // 引入颜色库 rl.question(`${chalk.cyan("当前版本号: ")}${chalk.bold.red(getVersion())} \n请输入新版本号: `, (name) => { !name && (name=versionInfo?versionInfo.version:""); console.log(`${chalk.cyan("新版本号是: ")}${chalk.bold.yellow(name)}`);
在终端上效果为
有时版本号前会有固定前缀,我们在提示输入时把前缀显示出来,可以随意删除
// 写入默认值 rl.write("Version ")
接下来是运行打包命令。当前项目使用gulp打包。要在终端中显示gulp的提示信息,选用child_process.spawn
// 解析bat运行传入的参数 var minimist = require('minimist'); var argv = minimist(process.argv.slice(2), { string: ["name"] }); const child_process = require('child_process'); rl.question(`${chalk.cyan("当前版本号: ")}${chalk.bold.red(getVersion())} \n请输入新版本号: `, (name) => { !name && (name=versionInfo?versionInfo.version:""); console.log(`${chalk.cyan("新版本号是: ")}${chalk.bold.yellow(name)}`); // 记录新版本号 changeVersion(name); var buildType = argv.buildType || "build" // 命令为gulp中配置好的 var gulpCmd = `gulp ${buildType} --buildVersion "${name}" --color --f ${__dirname}/gulpfile.js`; console.log(gulpCmd); let spawnProcess = child_process.spawn(gulpCmd, [], { shell: true }); spawnProcess.stdout.on('data', (data) => { console.log(`${data.toString()}`); }); spawnProcess.stderr.on('data', (data) => { console.log(`stderror: ${data}`); }); spawnProcess.on('close', (code) => { if (code !== 0) { console.log(`close: $[code]`); } }); spawnProcess.on('exit', (code) => { // console.log(`exit: ${code.toString()}`); console.log(chalk.bold.yellow("----------------- 完成 --------------------")); }); }); function changeVersion(params) { if (versionInfo && versionInfo.changeVersion) { versionInfo.changeVersion(params); } }
在终端上效果为
使用其他打包工具可以这样
let exec = require('child_process').execSync; exec('vue-cli-service --mode dev build', { stdio: 'inherit' });
3. 修改版本号文件
修改文件我想到的事用fs.writeFile写文件,但这样对json格式很好处理,对js文件处理很不方便。所以我把版本信息单独存在json文件中。创建两个文件version.js、version.json。
var VersionInfoJson; // 考虑到可能会在html中引用,做了区分 if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { getVersionInfo(true); } else { if (typeof define === 'function' && define.amd) { getVersionInfo(false); } else { getVersionInfoLocal(); } } function getVersionInfo(isModule) { try { VersionInfoJson = require("./version.json"); } catch (error) { VersionInfoJson = {}; } VersionInfoJson.buildTime = getNowFormatDate(); VersionInfoJson.changeVersion = changeVersion; if (isModule) { module.exports = VersionInfoJson; }else{ define([], function () { return VersionInfoJson; }); } } async function getVersionInfoLocal() { try { VersionInfoJson = await getVersionJson(); } catch (error) { VersionInfoJson = {}; } VersionInfoJson.buildTime = getNowFormatDate(); window.VersionInfo = VersionInfoJson; } function getVersionJson() { return new Promise((resolve, reject)=>{ var request = new XMLHttpRequest(); request.open("get", "config/version/version.json"); request.send(null); request.onload = function () { if (request.status == 200) { var json = JSON.parse(request.responseText); resolve(json); }else{ var json = {}; resolve(json); } } }); } function changeVersion(version) { var copyVersion = cloneObj(VersionInfoJson); copyVersion.version = version; if (copyVersion.hasOwnProperty("changeVersion")) { delete copyVersion["changeVersion"] } // console.log(copyVersion, __dirname, __filename) let fs = require('fs'); fs.writeFile(__dirname + "/version.json", JSON.stringify(copyVersion), (err) => { }); } // 1、用new obj.constructor ()构造函数新建一个空的对象,而不是使用{}或者[],这样可以保持原形链的继承; // 2、用obj.hasOwnProperty(key)来判断属性是否来自原型链上,因为for..in..也会遍历其原型链上的可枚举属性。 // 3、上面的函数用到递归算法,在函数有名字,而且名字以后也不会变的情况下,这样定义没有问题。但问题是这个函数的执行与函数名 factorial 紧紧耦合在了一起。为了消除这种紧密耦合的现象,需要使用 arguments.callee。 function cloneObj(obj) { if (obj === null) return null if (typeof obj !== 'object') return obj; if (obj.constructor === Date) return new Date(obj); if (obj.constructor === RegExp) return new RegExp(obj); var newObj = new obj.constructor(); //保持继承链 for (var key in obj) { if (obj.hasOwnProperty(key)) { //不遍历其原型链上的属性 var val = obj[key]; newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合 } } return newObj; } function getNowFormatDate() { var date = new Date(); var seperator1 = "-"; // 年月日间隔 var seperator2 = ":"; // 时分秒间隔 var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate + " " + date.getHours() + seperator2 + date.getMinutes() + seperator2 + date.getSeconds(); return currentdate; }
4. gulp读取版本号json文件
这一步就简单了。可以直接引用json。
const versionInfo = require('./src/config/version/version.js');
也可以从gulp命令中拿到版本号。
var minimist = require('minimist'); var argv = minimist(process.argv.slice(2), { string: ["name"] }); console.log(argv.buildVersion)
做近一步的处理。