nodejs脚手架开发:通过命令行利用模板生成文件

背景

在我司的所有项目中,有一类增删改查的页面出现率都是极其高的,我想做一个简单的脚手架来帮助大家能快速生成页面,在其上面进行具体业务修改进而提高开发效率。

选用依赖

  1. 开发命令行工具,TJ的”commander”是非常好的选择

  2. 日志,选用”winston3.x”和”dayjs”配合

  3. 模板,选用熟悉的”ejs”

  4. “fs-extra”,文件操作的封装与扩展

  5. “jest”,做一些简单的测试

  6. 其他,”eslint”语法检查以及插件,还有一些commit信息检查的支持

开始开发

大致目录结构

这类工具,首先是配置好用户的命令怎么去输入,那么第一步则是bin文件的开发:

// bin/index.js
#!/usr/bin/env node
'use strict';
const program = require('commander');
const packageJson = require('../package.json');
const handle = require('../util/handle');
program
  .version(packageJson.version)
  .option('-c, --config <configPath>', 'required, the path of the JSON configuration')
  .option('-p, --path <filePath>', 'The path(include name) of the file you want to generate')
  .parse(process.argv);

// 处理逻辑
handle(program.config, program.path);
  • bin文件加上shebang头,告诉系统使用nodejs执行这一段脚本。
  • 这里是让用户采用argv的形式传入参数执行文件,“commander”默认会-h生成帮助,我们同时需要编写每个option的帮助语句。这里我是让用户传入json配置路径(相对执行命令目录)与需要生成文件路径(相对执行命令目录,可不写,默认当前目录)
  • “commander”还支持其他命令,例如“command”模板语句加“command”的操作,具体文档我们可以在github/commanderjs中看到。
  • 然后我们在package.json加上下面这一段
{
  "bin": {
    "crud-init": "bin/index.js"
  }
 } 

然后 我们就可以拿到参数开发业务逻辑了:

'use strict';
const fs = require('fs');
const fse = require('fs-extra');
const path = require('path');
const assert = require('assert');
const log = require('./logger');
const ejs = require('ejs');
const exec = require('child_process').exec;

/**
 * @param {string} configPath json配置路径
 * @param {string} filePath 生成文件路径(相对执行命令目录,包含文件名)
 */
module.exports = (configPath, filePath) => {
  assert(configPath, '-c <config> or --config <config>,The JSON configuration path must exist');
  assert(!filePath || /\.vue$/.test(filePath), '-p <path> or --path <path>,The path must end with .vue');
  const startTime = Date.now();

  const cPath = path.join(process.cwd(), configPath);
  const fPath = path.join(process.cwd(), filePath || 'Unknown.vue');

  let config;
  try {
    config = fse.readJsonSync(cPath);
  } catch (e) {
    assert.ifError(e);
  }
  const tplPath = path.join(__dirname, '../template/Crud.ejs');
  const str = ejs.render(fs.readFileSync(tplPath, 'utf-8'), config);
  if (fse.pathExists(fPath)) {
    // 文件路径存在则先删除原文件
    fse.removeSync(fPath);
  }
  // 确保文件被创建
  fse.ensureFileSync(fPath);
  fs.writeFileSync(fPath, str);
  log.info(`生成位置:${fPath}`);
  const cmdStr = `${path.join(process.cwd(), 'node_modules/.bin/eslint')} --fix ${fPath}`;
  exec(cmdStr, err => {
    if (err) {
      log.warn('eslint修复失败,请检查是否在根目录执行命令以及eslint是否安装');
    }
    log.info(`执行结束,用时${(Date.now() - startTime) / 1000}s`);
  });
};
  • 这里我采用的是ejs模板生成了文件,然后执行当前工程的eslint进行修复。具体ejs模板怎么写在这就不贴出来了,大家如果还是做这个功能的话,按照自己实际情况去写即可。
  • 以下是日志的简单配置,只是为了好看,不用日志工具用console也是可以的。
// util/logger.js
'use strict';
const { createLogger, format, transports } = require('winston');
const { combine, colorize, timestamp, printf } = format;
const day = require('dayjs');

const myFormat = printf(info => {
  return `${day(info.timestamp).format('YYYY-MM-DD HH:mm:ss:SSS')} ${info.level}: ${info.message}`;
});

module.exports = createLogger({
  level: 'info',
  format: combine(
    colorize(),
    timestamp(),
    myFormat
  ),
  transports: [ new transports.Console() ],
});
  • 调试的时候,使用 npm link 可以模拟全局安装,就能使用命令了。如果修改了package.json文件,则需要重新执行npm link
  • 写了简单的测试执行handle函数

猜你喜欢

转载自blog.csdn.net/CaanDoll/article/details/81429217