效果展示
- 使用commander命令式效果
- 使用inquirer交互式效果
初始化操作
- 使用
npm init -y
命令快速生成 package.json 文件 - 设置
name
和main
值
{
"name": "mycli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
- 创建
index.js
文件,输入内容#!/usr/bin/env node
指定以node环境运行
#!/usr/bin/env node
console.log('hello mycli!')v
- 使用
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), 为我们提供了便利,我们主要进行操作就是提供我们自己的脚手架模板