最近上班摸鱼的时候,看到公司项目的文件夹,由于项目是基于DDD进行开发的,所以目录结构基本是一致的,想到每次创建新模块的时候需要每个文件去创建,为什么不能写个脚本工具去帮助我快速生成新的目录结构和文件呢。
先创建个目录
mkdir xx-cli
cd xx-cli
npm init -y
本来想着用ts来开发的,想了想这个简易的工具其实代码不会特别多,直接js梭哈了,还省了编译这一步。
下面就得理清我们的需求,我们是想通过命令行工具帮我们快速创建文件目录,类似nest/cli那样,所以commander.js这个包肯定是需要的,至于模板引擎相关的工具,这个项目暂时用不到。
下面就是安装依赖,然后创建下项目目录
npm i commander
mkdir src
cd src
echo index.js
mkdir utils
好了之后,可以先改一下package.json的内容,把版本号(version),作者(author),模块(type),这里是在node环境下,type就用commonjs,然后是入口文件(main),由于我们是命令行工具,还需要配置bin,至于命令是什么,自己取个喜欢的名字就好了,后续就可以直接在终端输入xx ,就能看到命令行信息了。
"bin": {
"xx": "src/index.js"
},
基本工具基本做完了,下面就是开始写代码了,首先在index.js中引如commander,然后通过commander来帮助我们创建一个新的命令
// 引入commander
const program = require('commander');
// 加入版本号
program.version("0.0.1");
// 创建命令
program
.command("create <name>")
.description("create a new project")
.action((name)=>{
console.log('文件名:',name)
})
这样就已经创建好了命令了,在命令行输入node index.js xx create demo,就能看到打印文件名:demo了。
到这一步命令有了,文件名有了,下面就是我们创建文件的逻辑,创建文件肯定就需要nodejs的fs模块的帮助了。 在utils文件夹中新增两个文件
cd utils
// 创建文件的函数
echo createFile.js
// 存放目录文件信息
echo fileList.js
这里先把我们要的文件目录结构确定
// type dir表示目录,file表示文件,如果后续有需要可以加入template,来引用模板地址,暂时这里用不到
const generateFiles = (projectName) => {
return [
{
name: projectName,
type: 'dir',
children: [{
name: 'api',
type: 'dir',
children: [{
name: 'command',
type: 'dir',
}, {
name: `${projectName}API.ts`,
type: 'file',
},
{
name: `${projectName}Assembler.ts`,
type: 'file',
}
]
}, {
name: 'app',
type: 'dir',
children: [{
name: `${projectName.replace(/^./, projectName[0].toUpperCase())}App.ts`,
type: 'file',
}
]
}, {
name: 'constant',
type: 'dir',
},
{
name: 'domain',
type: 'dir',
}, {
name: 'exception',
type: 'dir',
children: [{
name: `${projectName.replace(/^./, projectName[0].toUpperCase())}Exception.ts`,
type: 'file',
}]
}, {
name: 'plugins',
type: 'dir',
}, {
name: 'view',
type: 'dir',
}]
}
]
}
module.exports = {
generateFiles
}
目录结构确定了,下面就是根据目录结构来编写创建文件的函数了
const fs = require("fs");
const path = require("path");
// 接受两个参数,basePath就是我们当前目录的路径,files就是我们的目录结构
const createFiles = (basePath, files) => {
for (const file of files) {
// 这里每次获取当前目录的完整路径
const filePath = path.join(basePath, file.name);
if (file.type === "dir") {
// 如果是文件夹,使用mkdirSync直接创建文件夹
fs.mkdirSync(filePath);
if (file.children) {
createFiles(filePath, file.children);
}
} else if (file.type === "file") {
// 如果是file类型,在当前目录下,创建一个空文件
fs.writeFileSync(filePath, "");
}
}
};
module.exports = {
createFiles
}
这两个工具方法写好后,这个简易工具逻辑就基本实现了,下面完善下index.js就可以了
#!/usr/bin/env node
const program = require('commander');
const { generateFiles } = require("./utils/fileName");
const { createFiles } = require("./utils/createFiles");
program.version("0.0.1");
program
.command("create <name>")
.description("create a new project")
.action((name) => {
const files = generateFiles(name)
const basePath = process.cwd()
createFiles(basePath, files)
}
);
program.parse(process.argv);
这里如果想通过命令行来运行命令的话,文件开头需要加上 #!/usr/bin/env node,表示使用node解释器来执行脚本。 如果想要使用命令的话,还需要发布到npm上,然后下载到全局才可以使用这个命令,但是在本地测试可以不用这么复杂,直接运行npm link,这个可以在我们本地上创建一个软链接,可以让我们在本地直接引入这个包进行使用。 现在直接运行xx create demo,就可以创建一个完整目录了。
这个简易脚手架工具的编写到这里就结束,如果想要发布到npm上,需要有一个npm账号,我的密码现在不记得了,就不想发布私包了。