为什么我要搞个脚手架
因为喜欢用sass,喜欢用命令行生成模板文件(angular
有提供)。当然这不是全部的原因,最根本的原因,应该是,如果要开始一个项目,我希望能快速地进入开发状态,而不是将时间用在各种库的脚手架生成基本项目后又配sass,搬运模板文件,搬运一些基本配置上面。而且,这种工具类的项目能通过自己改造,跟随自身技术进步而进化的。最适合自己的,还是得自己去调校啊。
怎么搞脚手架
1. 自定义输入脚手架名字
首先,我们看到脚手架是这样输入的:
vue init hello-world
所以我们开发的脚手架,假如我们叫它 my-cli
,那么我们应该也是这样输入:
my-cli init hello-cli
而不是这样输入:
node main.js init hello-cli
当然不是说这样输入就不行,该优雅的时候还是得优雅,而且如果发布出去了,难道也要这样输入吗?太掉价了啊,我等之辈,当生而雅。
node
天生支持命令,我们分几步完成这个步骤:
-
package.json
添加bin
字段{ ... "bin" : { "my-cli": "bin/main.js" }, ... }
bin/main.js
是执行文件的路径,你大可以自定义。 -
编辑
main.js
#!/usr/bin/env node require("../src/main.js");
../src/main.js
这个是脚手架的主要逻辑文件的路径,也可大方自定义。 -
npm link
这样就链接到全局环境了,然后就可以
my-cli init xxx
2. 接受输入的参数
仔细一看,其实人家是这样的:
vue init hello-world
接收到一个动作 init
,一个参数值 hello-world
。那做一个脚手架,肯定是要根据输入的参数来做一些处理,然后生成一个项目的。要不然,还不如直接 copy
来的痛快呢。
想到接收参数,是不是会想起 process.args
,当然这个是一个可行的办法,但是跟 commander
相比,就像刀耕火种的原始跟飞机大炮的现代一样。当然可能差距不会那么大,但是明显地, commander
是一个比较好的选择。
var commander = require('commander');
commander
.version('0.0.1', '-v, --version')
.usage('搭建自定义的脚手架')
.description('To make myself cli');
commander
.command('init [name]')
.action((name, value) => {
init(name)
});
commander.parse(process.argv);
function init(name) {
console.log(name);
}
此处附上一个网站是关于 commander
的 API
的学习的:Commander.js中文文档
这个时候,可以输入:
my-cli init hello
// hello
这里输入参数的问题,应该解决了,具体的脚手架的代码,我完成后,会放到git上面去,这里只做一些基础的记录。
3. 友好提示输入
如果你输入了 my-cli init hello-world
,下面应该是要生成一些模板,比如记录 author
,比如提示要用到哪一个框架(假如是可输入的),用到哪些组件(sass, antd)等,是不是需要一些有好的提示,方便完成项目的搭建呢。这里也可以提供一个想法,当然是很原始的,但是,是最容易想到的,就是 console.log
后监听输入。刚才只是说了一下笑,我们当然不能这样干啊,我们要将目光尽可能地聚焦在主要逻辑上。所以我们可以选用 inquirer
,当然,不是唯一的选择,只是刚好我知道这个,所以就用了。
var inquirer = require('inquirer');
inquirer.prompt([{
name: 'projectName',
message: 'Please enter the project name'
}, {
name: 'projectType',
message: 'Please enter the project type'
}]).then(answers => {
console.log(answers);
});
输入命令 my-cli
就会出现 Please enter the project name
回车后进入下一个问题,当所有问题答完,将会得到 answers
my-cli
// ? Please enter the project name hello
// ? Please enter the project type vue
// answers: { projectName: 'hello', projectType: 'vue' }
这里的代码,并不承接上文的(与 commander
部分代码无关),只是为了说明,刚好有一个组件能完成我们想要的功能而已。
4. 可选组件上下选择
当你有一些可选的组件,比如:scss,less或直接就css的时候,你的脚手架,是不是需要一个上下选择的功能呢?未研究,待解决。
5. 下载模板的进度显示
当填写完成信息,挑选完组件后,是不是应该下载对应的模板文件来组成一个项目了,这时候,下载的模板应该是远程的,所以应该有一个进度显示,表明程序正在下载模板文件,而不是卡死了,或者躺着不动了。所以,推荐用 ora
来完成这个功能。
var ora = require('ora');
let loading = ora('downloading template ...');
loading.start();
setTimeout(() => {
loading.succeed();
}, 2000);
6. 下载依赖
当模板文件下载好了之后,对应的依赖,应当是自动下载,当然也可以提示他:
cd xxx and npm install and npm start
友好点的话,应该是自己下载依赖(你的脚手架长大了,应该要学会自动下载依赖了,不要学我的花呗,现在还不会自己还)。这方面还没研究,待解决。
7. 配置好对应的项目
未解决。
需要用到的插件
npm i --save inquirer ora commander