1.自定义脚手架概述
1.全局命令行工具
2.创建项目初始化代码文件及目录
脚手架基本能力有哪些?
1.全局命令行执行能力
2.命令行交互能力(比如说会询问你的项目名,需要哪个版本等等..)
3.初始化下载代码的能力
如何实现自己的一个脚手架工具?
1.创建自定义全局命令
2.命令行参数接收处理
3.终端交互
- 可以浅试一下通过vite创建vue项目
npm i -g create-vite-app // 全局安装vite脚手架工具
create-vite-app vite-project(项目名自定义)
2.创建自定义全局指令
1.在你的项目目录中新建一个文件夹bin/vite.js
2.然后在项目目录下执行 npm init
{
"name": "my-vite",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
// 会生成一个这样的命令
"bin": {
"my-vite": "bin/vite.js"
}
}
3.执行npm link(挂载的意思) 就可以把我们当前的命令(my-vite)挂载到全局命令行工具当中
4.然后就可以在任意项目下执行my-vite
5.那么如何获取到命令行的交互参数?
1.在vite.js中
#! /usr/bin/env node
if (process.argv[2] === '--help') {
console.log('我获取到了命令行参数');
}
console.log('my-vite');
console.log(process.argv); // [
'D:\\node\\node.exe',
'C:\\Users\\fllni\\AppData\\Roaming\\npm\\node_modules\\my-vite\\bin\\vite.js',
'--help'
]
3.使用commander命令参数处理工具
- --help 使用方式1: github.com/tj/commande…
使用方式2: www.npmjs.com/package/com…
npm i commander
const { program } = require('commander');
program
// <> 意思就是如果使用了-f 那么后面必须要跟对应的参数 否则会报错
// 第二个参数表示对此命令的描述
.option('-f --first <first>', 'First');
.option('-s, --separator <char>');
program.parse(process.argv); // 命令行所有的参数选项
4.处理自定义指令选项
const {program} = require('commander')
program.option('-f --framwork <framwork>','设置框架')
program
.command('create <project> [other...]') // 命令选项
.alias('crt') // 给命令选项别名
.description('创建项目') // 描述
.action((project,args)=>{
// 命令行的执行逻辑代码
console.log(project);
console.log(args);
})
program.parse(process.argv)
5.逻辑代码,模块化拆分
- 新建一个文件夹 lib/core(核心代码)
- 将自定义指令选项进行抽离以模块化的方式展现
const myaction = require('./action')
const mycommander = function (program) {
program
.command('create <project> [other...]')
.alias('crt')
.description('创建项目')
.action(myaction)
}
module.exports = mycommander
6.命令行问答交互
- 安装问答交互工具
npm i inquirer - 配置文件
config
module.exports = {
// 可选择的框架
framwork:['express', 'koa', 'egg'],
// 框架对应的下载地址
foramworkUrl:{
express:'git@gitee.com:beiyaoyaoyao/express-template.git',
koa:'git@gitee.com:beiyaoyaoyao/koa-template.git',
egg:'git@gitee.com:beiyaoyaoyao/egg-template.git'
}
}
命令行执行逻辑
var inquirer = require('inquirer')
var config = require('../../config')
const myAction = async (project, args) => {
const answer = await inquirer.prompt([
{
type: 'list',
name: 'framwork',
choices: config.framwork,
message: '请选择你所使用的框架'
}
])
// console.log(answer);
}
module.exports = myAction
7.下载远程仓库模板代码
需要工具
npm i download-git-reponpm i ora// 交互提示npm i chalk// 命令行样式渲染输出
- 下载
- 下载过程交互提示
- 命令行样式输出
const download = require('download-git-repo')
const ora = require('ora')
const chalk = require('chalk')
const downloadFun = function (url, project) {
const spinner = ora().start()
spinner.text = '代码正在下载……'
download('direct:' + url, project, { clone: true }, (err) => {
if (!err) {
spinner.succeed('代码下载成功')
console.log(chalk.blue.bold('Done!'), chalk.bold('you run:'));
console.log('cd ' + project);
console.log('npm install ');
console.log('npm run dev ');
} else {
spinner.fail('代码下载失败')
}
})
}
module.exports = downloadFun
// 命令行触发执行逻辑
var inquirer = require('inquirer')
var config = require('../../config')
var downloadFun = require('./download')
const myAction = async (project, args) => {
// 命令行的执行逻辑代码
// console.log(project);
// console.log(args);
// express koa egg
const answer = await inquirer.prompt([
{
type: 'list',
name: 'framwork',
choices: config.framwork,
message: '请选择你所使用的框架'
}
])
// console.log(answer);
// 下载代码模板
downloadFun(config.foramworkUrl[answer.framwork],project)
}
module.exports = myAction
8.自定脚手架项目总结
- 全局命令行工具
- 命令参数接收处理
- 终端交互
- 下载远程仓库代码
- 项目初始化完成提示