npm指令执行前执行自定义代码

1、基本逻辑

npm start执行前执行node ./bin/wb-handle

"scripts": {
    "wb": "node ./bin/wb-handle; npm start"
},

wb-handle源码,删除deleteNodeModules配置的最后一级目录文件

#!/usr/bin/env node --max-old-space-size=4096 --optimize-for-size --max_old_space_size=4096 --optimize_for_size

"use strict";

var deleteNodeModules = "abab/efg";

var fs = require("fs");

function deleteFolderRecursive(path) {
    if( fs.existsSync(path) ) {
        fs.readdirSync(path).forEach(function(file) {
            var curPath = path + "/" + file;
            if(fs.statSync(curPath).isDirectory()) { // recurse
                deleteFolderRecursive(curPath);
            } else { // delete file
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(path);
    }
};

deleteFolderRecursive(`./node_modules/${deleteNodeModules}`)


2、推包到npm

接下来我们代码推包到npm使用

{
  "name": "wb-handle",
  "version": "1.0.2",
  "description": "delete mode_modules file",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "bin": {
    "wbhandle": "./bin/wb-handle.js"
  },
  "keywords": [
    "node"
  ],
  "author": "wangb",
  "license": "ISC"
}

wb-handle.js改进代码,可以在项目package.json配置deleteModule自动删除nodel_modules中的包

#!/usr/bin/env node --max-old-space-size=4096 --optimize-for-size --max_old_space_size=4096 --optimize_for_size

"use strict";


const path = require('path');
var fs = require("fs");


const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
var packagePath = resolveApp("package.json")
var packageJson = require(packagePath);
var deleteModule = packageJson && packageJson.deleteModule;
if (!deleteModule) {
    console.log("请在package.json中输入deleteModule");
    return;
} 
function deleteFolderRecursive(path) {
    if( fs.existsSync(path) ) {
        fs.readdirSync(path).forEach(function(file) {
            var curPath = path + "/" + file;
            if(fs.statSync(curPath).isDirectory()) { // recurse
                deleteFolderRecursive(curPath);
            } else { // delete file
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(path);
    }
};

deleteFolderRecursive(`./node_modules/${deleteModule}`)


1

3、使用
yarn add wb-handle -D

配置项目命令

"scripts": {
  "start": "wbhandle;react-scripts start --port 3000",
},
4、继续改进可以读取命令行参数执行指令
#!/usr/bin/env node --max-old-space-size=4096 --optimize-for-size --max_old_space_size=4096 --optimize_for_size

"use strict";

const path = require("path");
var fs = require("fs");
const args = process.argv.slice(2);
const scriptIndex = args.findIndex((x) => x === "delete");
const script = scriptIndex === -1 ? args[0] : args[scriptIndex];

if (script.indexOf("delete") !== -1) {
  const appDirectory = fs.realpathSync(process.cwd());
  const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
  var packagePath = resolveApp("package.json");
  var packageJson = require(packagePath);
  var deleteModule = packageJson && packageJson.deleteModule;
  if (!deleteModule) {
    console.log("请在package.json中输入deleteModule");
    return;
  }
  function deleteFolderRecursive(path) {
    if (fs.existsSync(path)) {
      fs.readdirSync(path).forEach(function (file) {
        var curPath = path + "/" + file;
        if (fs.statSync(curPath).isDirectory()) {
          // recurse
          deleteFolderRecursive(curPath);
        } else {
          // delete file
          fs.unlinkSync(curPath);
        }
      });
      fs.rmdirSync(path);
    }
  }

  deleteFolderRecursive(`./${deleteModule}`);
}

5、创建delete和copy命令

Wb-handle.js代码

#!/usr/bin/env node --max-old-space-size=4096 --optimize-for-size --max_old_space_size=4096 --optimize_for_size

"use strict";
const path = require("path");
var fs = require("fs");

const args = process.argv.slice(2);
const scriptIndex = args.findIndex((x) => x === "delete");
const script = scriptIndex === -1 ? args[0] : args[scriptIndex];

const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
var packagePath = resolveApp("package.json");
var packageJson = require(packagePath);

if (script.indexOf("delete") !== -1) {
  var deleteModule = packageJson && packageJson.deleteModule;
  if (!deleteModule) {
    console.error("请在package.json中输入deleteModule");
    return;
  }
  if (Array.isArray(deleteModule)) {
    deleteModule.forEach((item) => {
      require("../script/delete")(`./${item}`);
    });
  } else {
    require("../script/delete")(`./${deleteModule}`);
  }
} else if (script.indexOf("copy") !== -1) {
  var copy = packageJson && packageJson.copyModule;
  if (Array.isArray(copy)) {
    copy.forEach((item) => {
      // 复制文件
      require("../script/copy")(`./${item.from}`, `./${item.to}`);
    });
  } else {
    console.error("copy必须是数组格式");
  }
}


script/copy代码如下

const path = require("path");
var fs = require("fs");
var copyFile = function (srcPath, tarPath, cb) {
  var rs = fs.createReadStream(srcPath);
  rs.on("error", function (err) {
    if (err) {
      console.error("read error", srcPath);
    }
    cb && cb(err);
  });

  var ws = fs.createWriteStream(tarPath);
  ws.on("error", function (err) {
    if (err) {
      console.error("write error", tarPath);
    }
    cb && cb(err);
  });
  ws.on("close", function (ex) {
    cb && cb(ex);
  });

  rs.pipe(ws);
};
var copyFolder = function (srcDir, tarDir, cb) {
  fs.readdir(srcDir, function (err, files) {
    var count = 0;
    var checkEnd = function () {
      ++count == files.length && cb && cb();
    };

    if (err) {
      checkEnd();
      return;
    }
    if (!fs.existsSync(tarDir)) {
      fs.mkdirSync(tarDir);
    }

    files.forEach(function (file) {
      var srcPath = path.join(srcDir, file);
      var tarPath = path.join(tarDir, file);

      fs.stat(srcPath, function (err, stats) {
        if (stats.isDirectory()) {
          fs.mkdir(tarPath, function (err) {
            if (err) {
              console.error(err);
              return;
            }

            copyFolder(srcPath, tarPath, checkEnd);
          });
        } else {
          copyFile(srcPath, tarPath, checkEnd);
        }
      });
    });

    //为空时直接回调
    files.length === 0 && cb && cb();
  });
};
 // 复制文件
 function wbCopyFile(orgfilepath, desdirpath) {
  if (fs.lstatSync(orgfilepath).isDirectory()) {
    // 目录到指定目录
    copyFolder(orgfilepath, desdirpath);
  } else {
    // 文件到指定目录
    if (fs.existsSync(orgfilepath)) {
      if (!fs.existsSync(desdirpath)) {
        fs.mkdirSync(desdirpath);
        fs.copyFileSync(
          orgfilepath,
          `${desdirpath}/${path.basename(orgfilepath)}`
        );
      } else {
        fs.copyFileSync(
          orgfilepath,
          `${desdirpath}/${path.basename(orgfilepath)}`
        );
      }
    } else {
      console.error(
        Date().toString() +
          "FolderAndFileOperation_copyFile: org file not existed." +
          " org path: " +
          orgfilepath.toString()
      );
    }
  }
}
module.exports = wbCopyFile;

script/delete代码如下

var fs = require("fs");

function deleteFolderRecursive(path) {
  if (fs.existsSync(path)) {
    fs.readdirSync(path).forEach(function (file) {
      var curPath = path + "/" + file;
      if (fs.statSync(curPath).isDirectory()) {
        // recurse
        deleteFolderRecursive(curPath);
      } else {
        // delete file
        fs.unlinkSync(curPath);
      }
    });
    fs.rmdirSync(path);
  }
}
module.exports = deleteFolderRecursive;

6、支持创建模版文件

wb-handle代码修改为下面

#!/usr/bin/env node --max-old-space-size=4096 --optimize-for-size --max_old_space_size=4096 --optimize_for_size

"use strict";
const path = require("path");
var fs = require("fs");

const args = process.argv.slice(2);
const scriptIndex = args.findIndex(
  (x) => x === "delete" || x === "copy"  || x === "tem"
);
const script = scriptIndex === -1 ? args[0] : args[scriptIndex];

const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
var packagePath = resolveApp("package.json");
var packageJson = require(packagePath);

if (script.indexOf("delete") !== -1) {
  var deleteModule = packageJson && packageJson.deleteModule;
  if (!deleteModule) {
    console.error("请在package.json中输入deleteModule");
    return;
  }
  if (Array.isArray(deleteModule)) {
    deleteModule.forEach((item) => {
      require("../script/delete")(`./${item}`);
    });
  } else {
    require("../script/delete")(`./${deleteModule}`);
  }
} else if (script.indexOf("copy") !== -1) {
  var copy = packageJson && packageJson.copyModule;
  if (Array.isArray(copy)) {
    copy.forEach((item) => {
      // 复制文件
      require("../script/copy")(`./${item.from}`, `./${item.to}`);
    });
  } else {
    console.error("copy必须是数组格式");
  }
} else if (script.indexOf("tem") !== -1) {
  const list = args.findIndex((x) => x === "list");
  const nameIndex = args.findIndex((x) => x.indexOf("name=") !== -1);
  if (nameIndex === -1) {
    console.error("template必须输入name=");
    return;
  }
  const nameArr = args[nameIndex].split("=");
  const name = nameArr[1];
  if (list !== -1) {
    require("../script/template")(name, true); // 列表
  } else {
    require("../script/template")(name, false); // 视图
  }
}

新增template.js

var fs = require("fs");
const path = require("path");

function firstToUpper(str) {
  return str.trim().toLowerCase().replace(str[0], str[0].toUpperCase());
}
function create(name, list) {
  var template;
  var templateModel;
  var templateDir = path.resolve(__dirname, '../template');
  if (list) {
    template = fs.readFileSync(templateDir +"/template.list.tsx");
    templateModel = fs.readFileSync(templateDir + "/template.model.ts");
  } else {
    template = fs.readFileSync(templateDir +"/template.tsx");
    templateModel = fs.readFileSync(templateDir +"/template.model.ts");
  }

  var templateStr = template
    .toString()
    .replace(/ModuleName/g, firstToUpper(name))
    .replace(/moduleName/g, name);
  var templateModelStr = templateModel
    .toString()
    .replace(/ModuleName/g, firstToUpper(name))
    .replace(/moduleName/g, name);

  if (list) {
    fs.writeFileSync("./" + name + ".list.tsx", templateStr);
  } else {
    fs.writeFileSync("./" + name + ".tsx", templateStr);
  }
  fs.writeFileSync("./" + name + ".model.tsx", templateModelStr);
}
module.exports = create;

7、支持创建通用模版

模版里支持配置的变量

/**
 * 模版里支持配置的变量
 * T_Name (name会自动转首字母大写)
 * T_name
 * T_classname
 * T_id
 * T_key
 * T_content
 */

实现

#!/usr/bin/env node --max-old-space-size=4096 --optimize-for-size --max_old_space_size=4096 --optimize_for_size

"use strict";
const path = require("path");
var fs = require("fs");

const args = process.argv.slice(2);
const scriptIndex = args.findIndex(
  (x) => x === "delete" || x === "copy" || x === "tem"
);
const script = scriptIndex === -1 ? args[0] : args[scriptIndex];

/**
 * 获取命令行参数并返回对象
 * @returns {Object} 参数对象
 */
function getOption() {
  const arr = process.argv.slice(2); // 获取命令行参数数组
  const r = arr.reduce((pre, item) => { // 使用reduce方法对参数数组进行处理
    if (item.indexOf("=") !== -1) { // 判断参数是否有等号
      return [...pre, item.split("=")]; // 将带有等号的参数进行分割并添加到结果数组中
    }
    return pre; // 否则返回原结果数组
  }, []);
  const params = Object.fromEntries(r); // 将结果数组转化为参数对象
  return params; // 返回参数对象
}
if (script.indexOf("delete") !== -1) {
  const appDirectory = fs.realpathSync(process.cwd());
  const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
  var packagePath = resolveApp("package.json");
  var packageJson = require(packagePath);

  var deleteModule = packageJson && packageJson.deleteModule;
  if (!deleteModule) {
    console.error("请在package.json中输入deleteModule");
    return;
  }
  if (Array.isArray(deleteModule)) {
    deleteModule.forEach((item) => {
      require("../script/delete")(`./${item}`);
    });
  } else {
    require("../script/delete")(`./${deleteModule}`);
  }
} else if (script.indexOf("copy") !== -1) {
  const appDirectory = fs.realpathSync(process.cwd());
  const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath);
  var packagePath = resolveApp("package.json");
  var packageJson = require(packagePath);

  var copy = packageJson && packageJson.copyModule;
  if (Array.isArray(copy)) {
    copy.forEach((item) => {
      // 复制文件
      require("../script/copy")(`./${item.from}`, `./${item.to}`);
    });
  } else {
    console.error("copy必须是数组格式");
  }
} else if (script.indexOf("tem") !== -1) {
  const obj = getOption();
  if (!obj.name) {
    console.error("template必须输入name=");
    return;
  }
  require("../script/template")(obj); // 列表
}

var fs = require("fs");
const path = require("path");

/**
 * 模版里支持配置的变量
 * T_Name (name会自动转首字母大写)
 * T_name
 * T_param
 * T_key
 * T_content
 * T_classname
 * T_id
 */
function firstToUpper(str) {
   var firstLetter = str.charAt(0).toUpperCase() + str.slice(1);
  return firstLetter;
}
function create(obj = {}) {
  var templateDir = path.resolve(__dirname, "../tem");
  fs.readdirSync(templateDir).forEach((file) => {
    const filePath = path.join(templateDir, file);
    if (fs.statSync(filePath).isFile()) {
      const fileContent = fs.readFileSync(filePath, "utf8");
      var templateStr = fileContent
        .toString()
        .replace(/T_Name/g, obj.name ? firstToUpper(obj.name) : "")
        .replace(/T_name/g, obj.name)
        .replace(/T_param/g, obj.content)
        .replace(/T_key/g, obj.key)
        .replace(/T_content/g, obj.content)
        .replace(/T_classname/g, obj.classname)
        .replace(/T_id/g, obj.id);

      if (!fs.existsSync("./temOutput")) {
        fs.mkdirSync("./temOutput");
      }
      const newFile = file.replace("tem", obj.name);
      fs.writeFileSync("./temOutput/" + newFile, templateStr);
    }
  });
}
module.exports = create;

8、最终版本使用

使用在项目package.json配置如下

"scripts": {
    "start": "wbhandle delete;react-scripts start --port 3000",
    "tem": "wbhandle tem"
},
"deleteModule": [
    "node_modules/busynessbill1",
    "node_modules/busynessbill2",
    "node_modules/busynessbill3"
]
// 或者
"deleteModule": "test/package.json" // 删除指定文件夹
"copyModule": [
  {
    "from": "package.json", // 复制文件到指定目录
    "to": "test"
  },
  {
    "from": "image", // 复制文件夹到指定目录
    "to": "test"
  }
],

创建模版文件执行

npm run tem name=ceshiwenjian
npm run tem name=ceshiwenjian list // 列表模版
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值