效果展示
- 使用commander命令式效果
- 使用inquirer交互式效果
初始化操作
使用 npm init -y 命令快速生成 package.json 文件
设置上 name 和 main 的值
需要加上bin的配置项,否则可能会执行全局命令无效,bin 字段:可以自定义脚手架工具的命令,例如下面的 mycli ,而 mycli 后面的就是命令的执行脚本。
{
"name": "mycli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
"mycli": "bin/index.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}
创建 index.js 文件,输入内容 #!/usr/bin/env node 指定以node环境运行
#!/usr/bin/env node
#!/usr/bin/env node console.log('hello mycli!')
使用 npm link 命令创建全局module,会在全局node变量下自动生成文件 /node_modules/mycli/index.js,就可以在本地对脚手架工具进行调试了
安装依赖 npm install chalk shelljs inquirer --save
- chalk:是一个node输出log的样式库
- shelljs:见名知义是执行shell命令的库
- inquirer:交互式命令库
目录结构
- mycli
- node_modules
- template
- vue
- vue.html
- h5
- h5.html
...
- createProject.js
- index.js
- package.json
- node_modules:脚手架所需要依赖
- template:该目录下存放的是cli需要的模板, 用户使用脚手架生成的最终项目就是从这里copy出去的
- createProject.js:拉去项目的代码都在这里
- index.js:脚手架入口文件
- package.json:对项目及模块的描述
具体代码
index.js
#!/usr/bin/env node
let program = require('commander')
let createProject = require('./createProject')
// 设置版本号和参数,通过 mycli --help 查看
program.version('1.0.0')
.option('-t, --type <name>', 'project type')
.option('-n, --type <name>', 'project type')
// 捕获命令和参数 eg: mycli create test -t vue
program
.command('create <name>')
.action(function(name) {
createProject(name, program.type)
})
program.parse(process.argv)
createProject.js
let chalk = require('chalk'); // node终端样式库
let fs = require('fs');
let path = require('path');
let inquirer = require('inquirer');
require('shelljs/global'); // 执行shell脚本
let log = function(txt) {
console.log(chalk.green.bold(txt))
}
async function createProject(name, type) {
let p = process.cwd() // 获取当前路径
cd(p) // shell cd
// 检测是否存在文件夹, 如果存在,是否需要删除后安装
if(fs.existsSync(name)) {
log('project exists, please rename it');
var questions = [
{
type: 'confirm',
name: 'isRemoveDir',
message: `delete ${name} ?`,
default: false,
}
]
const answer = await inquirer.prompt(questions).then((answers) => {
return answers
});
if(!answer.isRemoveDir) {
process.exit();
}
rm('-rf', name); // shell rm
log(`delete ${name} success`)
}
let np = path.join(__dirname, 'template', type);
cp('-R', np+'/', name) // shell cp
log(`拉取 '${type}' 项目成功!`)
cd(name) // shell cd
log('设置淘宝镜像源 --- npm config set registry http://registry.npm.taobao.org')
exec('npm config set registry http://registry.npm.taobao.org') // 执行自定义的shell命令 npm config set registry http://registry.npm.taobao.org
log('安装模块 --- npm install')
log('安装模块中...')
log('安装耗时可能会很长,请耐心等待,您也可以通过 ctrl+c停止安装, 手动 npm install')
exec('npm install') // 执行自定义的shell命令 npm install
// 这里的逻辑是自定义的,根据需求自己完成
if(type != 'jquery') {
log('正在启动项目')
exec('npm start') // 执行自定义的shell命令 npm start
}
log('脚手架初始化完成')
process.exit()
}
module.exports = createProject
使用方式
mycli --help: --help是commander自带的命令, 可以输出脚手架的命令
mycli create demo -t vue: 这是我们自定义的命令, 创建一个demo文件夹,以vue作为模板
项目改造
使用commander命令操作太过繁琐,并且记不住参数,我们使用inquirer改造成彻底的交互式脚手架
- 修改 index.js
#!/usr/bin/env node
const createProject = require('./createProject')
const inquirer = require('inquirer');
const fs = require('fs');
const path = require('path');
const promptList = [
{
type: 'input',
message: '请输入项目名',
name: 'name',
default: 'my-project',
},
{
type: 'list',
message: '请选择项目类型',
name: 'type',
choices: fs.readdirSync(path.join(__dirname,'template')) // 通过fs模块读取tempate目录下的目录列表
}
]
inquirer.prompt(promptList).then((answers) => {
createProject(answers.name, answers.type)
});
启动命令 `mycli`, 不用记住繁琐的参数选项,直接通过提示进行操作
总结
自定义脚手架依靠node环境,通过node提供的fs模块,进行文件操作。npm上也提供了各类的命令库(commander , shelljs )和交互式的库(inquirer), 为我们提供了便利,我们主要进行操作就是提供我们自己的脚手架模板。