# 打造属于自己的脚手架
# 初始化项目
mkdir aotu-cli
npm init -y
npm install eslint husky -D
初始化 eslint 配置文件
npm eslint --init
依次选择
To check syntax and find problems
CommonJS (require/exports)
None of these
Does your project use TypeScript?(Y/n) n
Where does your code run? Node
What format do you want your config file to be in? JSON
配置完后,项目根目录会生成 .eslintrc.json
# 添加配置文件
创建 bin\www 文件 全局命名执行根文件, 写入以下:
#!/usr/bin/env node
console.log('aotu-cli')
#!/usr/bin/env node 表示我要用系统中的这个目录/user/bin/env的node环境来执行此文件,且需要注意必须放在文件开头
在 package.json 中添加如下配置:
"bin": {
"aotu": "./bin/www"
}
# npm link
link 将一个任意位置的 npm 包链接到全局执行环境,从而在任意位置使用命令行都可以直接运行该npm包。 npm link命令通过链接目录和可执行文件,实现npm包命令的全局可执行
npm link
在终端 执行 aotu
发现 屏幕输出了 aotu-cli
# 编写 Cli
在 bin/www 文件 引入 main.js 作为我们项目入口
#!/usr/bin/env node
require('../src/main.js')
# 使用 commander
commander 是npm依赖排名前十之一的模块,主要作用为命令行辅助
安装模块
npm install commander
在 src/main.js 写些东西
const program = require('commander');
const _version = require('../package.json').version;
const program = require('commander');
program.version(_version)
.parse(process.argv);
在终端中执行 aotu-cli -help,发现有两个命名命名执行下 aotu-cli -V
发现打印了 版本号 1.0.0
下面我们来玩点花的 🐶
安装 figlet 生成一些特殊的文字
npm install figlet
安装 @darkobits/lolcatjs 生成颜色
npm install @darkobits/lolcatjs
修改 main.js
const figlet = require('figlet');
const versionStr = figlet.textSync('Aotu');
const Printer = require('@darkobits/lolcatjs')
program.version(
Printer.default.fromString(
` \n 席坤的手架${_version}\n www.47.98.161.153:8082 \n${versionStr}`
))
program.parse(process.argv);
让我们再执行一次 auto -v
发现控制台生成了 花里胡哨 🐶
接下来让我们开始接受用户命令行的输入
# 新建命名
npm install inquirer chalk ora shelljs download-git-repo
inquirer 交互式命令行,可以和用户进行交互
chalk node终端样式库
ora Node.js 终端加载动画效果
shelljs Nodejs使用ShellJS操作目录文件
download-git-repo 从git仓库下载代码
我们来自定义一些命名
program.option('init', '初始化项目🔧', 'blue')
.option('json2ts', '输入接口地址,自动生成TypeScript类 🥱')
接收命名
program
.usage(`${chalk.green('<cmd>')} <options>`)
.arguments('<cmd> [env]')
.action(function (cmd, ages) {
const handler = bindHandler[cmd];
if (typeof handler === 'undefined') {
ora(chalk.red(`命令${cmd}:`) + chalk.red('暂未支持')).fail();
} else {
handler(ages);
}
});
使用 inquirer 定义一些操作
const prompt = [
{
type: 'input',
name: 'projectName',
message: '请输入项目命名😄',
filter: function (val) {
return val
}
},
{
type: 'list',
name: 'jskind',
message: '请选择使用的模板',
default: 0,
choices: [
{
name: 'ECMAScript6',
value: 'es6',
url: '123'
}, {
name: 'TypeScript',
value: 'ts',
url: '456'
}
]
}
]
封装 bindHandler 对对应的命名就是操作
const bindHandler = {
init() {
inquirer.prompt(questions).then(answers => {
projectName = answers.projectName
const _pwd = process.cwd();
// 用户全路径
projectPath = `${_pwd}/${projectName}`;
// 检查路径是否存在
checkAppName(projectPath, projectName)
const spinner = ora(`⏰ ${chalk.red('downloading template')}`).start();
// 项目模版地址
const url = `direct:https://github.com/LiLixikun/${answers.jskind}.git`;
// 执行下载任务
download(url, projectPath, { clone: true }, function (err) {
spinner.stop();
if (err) {
console.log(chalk.red('下载失败 😭'));
process.exit(-1)
} else {
spinner.succeed(`${chalk.green('下载成功 😄')}`)
// 修改项目名称
shell.sed(
'-i',
'aotu',
projectName,
projectPath + '/package.json'
);
}
});
}).catch(error => {
console.log(chalk.red('脚手架出现异常,请联系 xx 📧'));
})
},
json2ts() {
createServer()
}
}
现在我们在终端来验证下
如何依赖某个库但是发布的时候不发布它呢? 配置 pack.json
"peerDependencies": {
"react": "^0.14.0 || ^15.0.0 || ^16.0.0",
"react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0"
}
下一章节我们介绍如何搭建可视化界面操作