背景
在我司的所有项目中,有一类增删改查的页面出现率都是极其高的,我想做一个简单的脚手架来帮助大家能快速生成页面,在其上面进行具体业务修改进而提高开发效率。
选用依赖
开发命令行工具,TJ的”commander”是非常好的选择
日志,选用”winston3.x”和”dayjs”配合
模板,选用熟悉的”ejs”
“fs-extra”,文件操作的封装与扩展
“jest”,做一些简单的测试
其他,”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函数