我们经常使用create-react-app、vue-cli来快速生成一个新的react或者vue项目,它们的原理是什么,下面就带使用node来开发一个简单的react-cli工具,来揭开其神秘的面纱。
以下是一个简单的 Node.js 的脚本:
#!/usr/bin/env node
console.log('Hello CLI');
复制代码
为了更好的和命令行界面交互,我们选择使用commander
传送门
yarn install commander
复制代码
然后编写cli需要实现的功能
import * as commander from "commander";
commander
.version(version, "-V, --version")
.usage("[Options] | [Commands] <file>")
commander
.command('init')
.description('generation a webpack project')
.option('dir')
commander
.command('view')
.description('generation a react component')
.option('<file>')
commander.on('--help', function(){
console.log('\n Examples:');
console.log('');
console.log(' $ snake -h');
console.log(' $ snake init snake-demo ');
console.log('');
});
commander.parse(process.argv);
复制代码
此时,在控制台里执行node index.js -h
,会出现以下界面
为了遵循"用户即爸爸"原则,我们添加辅助函数,当用户没输入任何参数,即执行node index.js
时,显示帮助信息
function help () {
commander.parse(process.argv)
if (commander.args.length < 1) return commander.help()
}
help()
复制代码
为了获取用户输入,我们选择使用inquirer
传送门
yarn add inquirer
复制代码
编写init函数
在这里需要注意的是,node的版本需要>=8,如果在小于8版本的环境下执行,会得到以下结果
在这里我们写了个setProjectName方法
来获取需要创建项目的名称
export async function setProjectName(dir?: string) {
const { projectName } = await inquirer.prompt({
name: 'projectName',
message: 'input project name',
});
global['projectName'] = projectName
if (!projectName) {
console.log('\n please input dir'.green + '\n');
await setProjectName();
} else if (fs.existsSync(projectName)) {
console.log('\n the dir has exists, please input another one'.green + '\n');
await setProjectName();
} else {
return projectName;
}
}
复制代码
执行 snake init snake-demo
(ps: 如果init后面没有项目名,则会提示新建)
在这里我维护了两套react模板供选择,放在src目录下去,大家可以根据需求修改或者选择自己的,当然,可以忽略该目录,毕竟该博文主要是介绍如何用nodejs开发一个cli工具的,并不是react教程,哈哈。 选择其中一项之后,就会出现以下提示
在我们生产的项目目录下执行snake view Test
,就会在src/view
目录下面自动生成一个Test.jsx
的react component
ps: 可以在package.json配置bin字段,bin项用来指定各个内部命令对应的可执行文件的位置。
"bin": {
"snake": "bin/index.js"
},
复制代码
上述代码即 snake
命令对应的可执行文件为 bin 子目录下的bin/index.js
,npm会寻找这个文件,在node_modules/.bin/
目录下建立符号链接。由于node_modules/.bin/
目录会在运行时加入系统的PATH变量,因此在运行npm时,就可以不带路径,直接通过命令来调用这些脚本
至此,我们的cli工具开发完成,意犹未尽者,可移步 github。