背景
拆分出的子工程具备了相同的目录结构,一致的技术栈,为脚手架提供的基础;新创建的子工程,每次都要手动改固定文件文件的配置,搭建脚手架很有必要。换句话,就是人为手动改配置正确率达不到 100%
。
思路
说简单一些,脚手架是下载模板(clone),改文件内容(手动改),安装启动(install,run)
等重复劳动整合,最后通过简单指令让电脑完成上述劳动的一个方法。
stateDiagram-v2
state 开发 {
执行clone模板-->改文件内容
改文件内容-->install安装依赖
install安装依赖-->run启动
}
[*] --> 开发:无脚手架
开发 --> 浏览器
浏览器 --> [*]
state 脚手架{
自动clone模板-->自动改文件内容
自动改文件内容 --> 自动install安装
自动install安装--> 自动run启动
}
[*] --> 新开发:安装脚手架
新开发-->脚手架: 执行脚手架命令
脚手架-->浏览器
通过上述流程对比,使用脚手架命令可以最大限度解放开发,将重复内容交给电脑,保证修改稳定性。
实施
准备工作
简单了解:commander,inquirer,child_process,cmd
- commander提供自定义命令
- inquirer提供交互方式
- child_process提供执行cmd的环境
步骤
-
npm init
初始化package.json,并为脚手架起一个响亮的名字(暂定t-cli
),回车到底。 -
npm install commander inquirer child_process
安装t-cli需要用到的包,安装成功后,pacaagek.json内容如下:{ "name": "t-cli", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "child_process": "^1.0.2", "commander": "^8.2.0", "inquirer": "^8.2.0" } }
-
package.json同级目录下,手动创建
bin.js
作为t-cli的入口,bin.js内容如下:#!/usr/bin/env node const {Command} = require('commander'); //引入commander const program = new Command(); //new command实例 //添加版本号为package.json中的版本 const {version} = require('./package.json'); program.version(version) //定义使用方式 program.usage('<command> [options]') //自定义命令 program .command('init') //定义命令init .description('初始化项目模板') //添加命令描述 .alias('i') //给init命令添加别名i,可以i启动init .action(async(opt,cmd)=>{ //使用命令init执行的操作 console.log('实际执行的操作') }) //传入环境变量 program.parse(process.argv)
-
node bin.js init
或者node bin.js i
运行,走到对应的action中表示成功。 -
在package.json中添加bin选项,然后在package.json同级目录使用
npm link
链接成全局命令//package.json { "name": "t-cli", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "bin": { "t-cli":"./bin.js" }, "author": "", "license": "ISC", "dependencies": { "child_process": "^1.0.2", "commander": "^8.2.0", "inquirer": "^8.2.0" } }
-
使用
t-cli init
验证全局指令 -
在action的方法中,使用
inquirer
增加用户交互const inquirer = require('inquirer'); //action方法 let answer = await inquirer.prompt([{ type: 'list', message: '请选择模版:', name: 'tplName', choices: ['模板1','模板2'] }, { type: 'input', message: `请输入模板名称:`, name: 'name', }] console.log(answer);
执行结果:
-
使用
child_process
,调用git clone下载模板文件。const {exec} = reuqire('child_process'); let bat = exec('git clone http://*********.git',function(error){ if(error){ console.log(error) }else{ console.log('done') } }) bat.stdout.on('data', (data) => { console.log(data.toString()); }); bat.stderr.on('data', (data) => { console.log(data.toString()); }); bat.on('exit', (code) => { console.log(`Child exited with code ${code}`); });
-
通过fs动态调整模板文件内容
总结
- commander的版本不同用法也不一样,新版本需要new一个commander
- child_process.exec是开启一个调用命令的进程,可执行cmd,bash,window相关命令
常用命令 | 说明 |
---|---|
npm link | unlink -f | 全局挂载 | 卸载包 |