目录
1、脚手架
1. 基础概念
- bin文件夹:存储可执行文件
- lib文件夹:存储程序运行所需的共同文件(共享相同代码的文件)
--options -o
:都是算到options里- 全局安装
@vue/cli
时发生了什么?- 从npm下载
@vue/cli
的包,安装到node
下的lib
文件夹中 - 解析
package.json
的bin属性
- 如果有
bin属性
,就会在bin
文件夹生成软连接
,指向的是bin属性
对应的值
- 从npm下载
package.json
的main
属性,如果当前项目作为包,main指向入口文件
2. 脚手架开发流程
-
脚手架创建
- 创建项目
test-build
- 初始化项目
npm init -y
package.json
中添加bin
属性:"bin": {"imooc-build": "bin/imooc-build.js"},
- 创建脚手架入口文件:
bin/imooc-build.js
- 入口文件首行添加:
#!/usr/bin/env node
- 创建项目
-
脚手架开发
- 分包:将复杂的系统拆分成若干个模块
- 参数解析
-
调试脚手架
- 链接本地库文件:
- cd your-cli-dir(脚手架目录)
npm link
:创建软链接
- cd your-lib-dir(项目目录)
npm link your-lib
:使用上一步创建的软链接(安装到node_modules中)- 添加
"dependencies": {包名:版本号}
- cd your-cli-dir(脚手架目录)
- 取消本地库文件:
- cd your-lib-dir(项目目录)
npm unlink your-cli
:删除项目node_modules中的包
- cd your-cli-dir
npm unlink your-cli
:删除软连接
- 删除全局
C:\Users\mashize\AppData\Roaming\npm
下的记录npm remove -g 脚手架名称A
:删除本地的包
- cd your-lib-dir(项目目录)
- 链接本地库文件:
-
脚手架发布
npm publish
-
注意:windows下没有
#!/usr/bin/env node
,这个是Linux下的,可以通过bash命令行操作,cmd和shell都会报错windows script host
错误 -
开发脚手架框架
- yargs
- commander
- oclif
3. Commander.js基础使用
// const { program } = require('commander') // 单例模式
const {
Command } = require('commander');
const program = new Command(); // 多例模式,单独创建一个program(程序)实例
// // 单例模式--demo
// program
// .option('--first') // 设置option,option只有boolean和string两个格式类型,只有一个参数时就是boolean,两个参数就是string
// .option('-s, --separator <char>')
// program.parse() // 解析程序
// const options = program.opts() // 获取options
// const limit = options.first ? 1 : undefined;
// console.log(program.args[0].split(options.separator, limit)); // program.args[0]获取所有的参数
//多例模式
program
.name('imooc-build') // 脚手架名称
.description('CLI description')// 脚手架描述
.version('0.0.1'); // 脚手架版本
program
.option('-d, --debug', 'debugging'); // 全局的option
// 具体的指令(方式一)
program
.command('split') // 脚手架具体的命令(指令)
.description('指令的描述') // 指令的描述
.argument('<arguments>', '紧跟指令后面的参数') // 指令后面的参数
.option('--first', 'option的描述') // 当前指令下的option
.option('-s, --separator <char>', 'option的描述', ',') // option三个参数,参数1是option,参数2是描述,参数3是默认值
.option('-a, --add [char]', 'option的描述', ',') // <char>和[char]区别,<>是必填,[]是选填
.action((args, options)=>{
// 当输入当前command命令时,执行的回调函数
console.log(program.commands[0].optsWithGlobals()); // 当前指令下,以及全局的options
console.log('args, options:', args, options) // args获取的是argument,options获取的是option,都是当前指令下的
})
// addCommand 注册子命令
const service = new Command('service'); // 创建第二个指定姓名为'service'脚手架
service // 跟主命令的选项一样。注意不能连写command注册多个命令,这个是跟主命令的区别
.command('start [port]')
.description('子指令的描述') // 子指令的描述
.action((port)=>{
console.log('开启执行service start 命令', port)
})
// 在imooc-build下注册了service的子命令(子脚手架)
program.addCommand(service);
// 使用:
// imooc-build service start 8080
// 是执行imooc-build脚手架下的service子脚手架的start命令
program.parse()
// opts:获取当前实例的options,比如全局program获取的就是全局options,subcommand获取的就是局部options
// optsWithGlobals:获取全部options,比如全局program获取的就是全局options,subcommand获取的是【全局+局部】options
const options = program.opts(); //获取全局的options
const globalOptions = program.optsWithGlobals(); //也可以获取全局的options
4. 命令行UI显示
- 命令行渲染标准
- ANSI escape code
- 脚手架常用UI库
-
chalk:颜色渲染
- 基本用法
- chalk-cli使用技巧:快速生成chalk
import chalk from "chalk"; console.log(chalk.red('hello imooc')); console.log(chalk.red('hello imooc')+ "!"+ chalk.yellow('hello imooc!')); console.log(chalk.red.bgYellow.bold('hello imooc')); console.log(chalk.red('hello','imooc')); console.log(chalk.red('hello',chalk.underline('imooc!'))); console.log(chalk.rgb(255,255,0).underline('hello imooc!')); console.log(chalk.hex('#ff0000').bold('hello imooc!')); console.log(chalk.hex('#ff0000')('hello', 'imooc!')); const error = (...text)=> console.log(chalk.bold.hex('#ff0000')(text)) const warning = (...text)=> console.log(chalk.hex('#ffa500')(text)) error('Error!') warning('Warning!') const customChalk = new Chalk({ level:3}) // 0-3,0不支持所有颜色,1-3颜色支持越来越多 console.log(customChalk.blue('hello'));
-
ora:loading状态加载
- 基本用法
- cli-spinners
// node --experimental-modules .\src\ora.mjs import ora from 'ora' const spinner = ora().start() let percent = 0 spinner.color = 'red' // loading颜色 spinner.text = 'Loading' + percent + '%' // 显示的文本 spinner.prefixText = "Downloading chalk" // 显示文本的前缀信息 let interval = setInterval(() => { percent += 10 spinner.text = 'Loading' + percent + '%' if (percent === 100) { spinner.stop() // 结束loading spinner.succeed("Download finish!") // 回调,显示状态 clearInterval(interval) } }, 500);
-
5. 命令行交互
- 相关技术点
- 键盘输入监听(readline)
- 命令行窗口尺寸运算
- 清屏
- 光标移动
- 输出流静默
- 输入输出流(stream)
- 事件库(events)
- ansi escaped code
- 重点内容
- readline库
- inquirer库
// node --experimental-modules .\src\inquirer.js
import inquirer from 'inquirer';
inquirer
.prompt([
/* Pass your questions in here */
{
type:'input',
name:'yourName', // 返回信息的key
message:'请输入你的姓名', // 交互信息的显示的内筒
default:'noname', // 默认信息
validate: function (v) {
// 校验参数,只有结果为true时才会继续执行
return typeof v === 'string';
},
transformer: function (v) {
// 类似于提示信息,不会影响最终的answers
return v + '(input your name)'
},
filter: function (v) {
// 过滤,会影响最终的answers
return 'name[' + v + ']'
}
},
{
type:'number',
name:'num',
message:'请输入数字',
},
{
type:'confirm', // Boolean类型
name:'choice',
message:'your choice',
default: false,
},
{
type:'list', // Boolean类型
name:'list',
message:'your list',
default: 0, // 对应的是list 的顺序(索引,从0开始)
choices: [
{
value:1, name:'zs'},
{
value:2, name:'ls'},
]
},
{
type:'checkbox', // Boolean类型
name:'checkbox',
message:'your checkbox',
choices: [
{
value:1, name:'zs'},
{
value:2, name:'ls'},
]
}
])
.then((answers) => {
// Use user feedback for... whatever!!
console.log('获取输入结果answers:', answers)
})
.catch((error) => {
if (error.isTtyError) {
// Prompt couldn't be rendered in the current environment
} else {
// Something else went wrong
}
});
6. 多package管理
- lerna
- workspaces
6.1 lerna使用
npx lerna -v
:查看lerna版本npx lerna init
:项目初始化npx lerna create <name>
:生成一个项目npx lerna create --help
:查看命令的帮助信息lerna add <package>[@version] [--dev] [--exact] [--peer]
:安装依赖npx lerna link
:生成软连接npx lerna bootstrap
:所有依赖的安装和更新npx lerna publish
:发布package.json
添加publishConfig
属性"publishConfig": { "access": "public" }
- 其他常用命令:https://lerna.js.org/docs/api-reference/commands
7. 通用脚手架封装
7.1 主要实现功能
(1)创建初始化项目+集成通用代码(例如:登录)
(2)快速生成base页面并配置路由
(3)集成通用代码(常用utils封装、el二次封装组件,常用页面)
(4)常用业务层功能页面的集成
8. 安装和卸载
安装:npm install @msz-cli/cli -g
卸载:npm uninstall @msz-cli/cli -g
相关命令:
创建项目模板:msz create -t project projectname
创建模块模板:msz create -t module modulename
获取物料(utils/components/pages):msz get utils/components/pages