最近进行小版本发包测试时忘记修改版本号了,进而想到在打包前提示输入版本号,然后把版本号打进版本说明内。最终效果为双击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.jsversion.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)
    

    做近一步的处理。

    完毕

    分类:
    前端
  •