脚手架简介
脚手架本质是一个操作系统的客户端,它是通过命令行执行。最常用的脚手架有:npm、vue-cli、create-react-app、webpack-cli等。
实际工作中,我们往往需要借助脚手架来做各种流程的自动化,可以帮助我们开发各种提效工具,帮助企业大幅度节约研发成本。
脚手架命令分析
我们拿vue的脚手架举例:
bash
vue create vue-test-project
上面这条命令由 3 个部分组成:
- 主命令: vue
- command: create
- command 的 param: vue-test-project
它表示创建一个 vue 项目,项目的名称为vue-test-project。 我们也可以携带参数:
bash
vue create vue-test-project --force
--force 叫做 option,用来辅助脚手架确认在特定场景下用户的选择。
脚手架执行原理
简单总结为以下几点:
- 在终端输入vue-test-project
- 终端解析出 vue 命令,并在环境变量中找到 vue 命令
- 终端根据 vue 命令链接到实际文件 vue.js
- 终端利用 node 执行 vue.js
- vue.js 解析 command / options , 并执行 command
- 执行完毕,退出执行
什么是 Bash 和 CLI
这里简单介绍一下:
- Shell 是操作系统提供的接口程序,用于接收用户输入的命令,交给操作系统内核执行并接收响应结果
- Bash 是 Shell 的一个实现,用于执行用户输入的命令
- CLI 是 Bash 的运行环境,CLI 接收用户键盘输入,交给 Bash 执行,并将程序处理结果结果以文本形式进行显示
为什么需要脚手架框架
简单总结就是包括以下两点:
- 提升开发效率,大幅提升脚手架命令创建、修改的速度
- 简化开发过程,大幅提升代码的可读性和可维护性
脚手架开发流程
脚手架创建
使用npm init初始化项目。
bash
npm init
脚手架开发
参数解析:可以使用 commander.js 这个库来解析用户的命令。
脚手架调试
本地调试
bash
npm link
npm link:将当前项目链接到 node 全局 node_modules 中作为一个库文件,并解析 bin 配置创建可执行文件。
脚手架发布
bash
npm publish
实现下载代码脚手架
目标:实现一个可交互的下载代码脚手架。
项目目录
- bin/cli.js:脚手架入口文件
- lib/core
- action.js:执行操作文件
- download.js:执行文件下载
- help.js:帮助命令
- myCommander.js:命令文件
- config.js:配置文件
安装依赖
bash
npm i chalk
npm i commander
npm i download-git-repo
npm i inquirer
npm i ora
- chalk:是一个可以修改终端输出字符样式的 npm 包。
- commander:是一个命令行框架,提供了用户命令行输入和参数解析功能。
- download-git-repo:从node下载并提取git存储库。
- inquirer:命令行提示器。
- ora:loading状态。
项目开发
代码比较简单,大家可以按照项目目录实现一遍。
package.json文件
这里需要强调bin命令,它的作用就是去执行bin/cli.js文件。
javascript
// package.json
{
"name": "cli",
"version": "0.0.1",
"description": "",
"main": "index.js",
"bin": {
"cli": "bin/cli.js" // 执行bin/cli.js
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^4.1.2",
"commander": "^9.1.0",
"download-git-repo": "^3.0.2",
"inquirer": "^8.2.1",
"ora": "^5.4.1"
}
}
cli文件
加入 #! /usr/bin/env node
的目的是系统看到这一行的时候,首先会到env设置里查找node的安装路径,再调用对应路径下的解释器程序完成操作。
javascript
// bin/cli.js
#! /usr/bin/env node
const { program } = require('commander');
const myhelp = require('../lib/core/help');
myhelp(program);
const myCommander = require('../lib/core/myCommander');
myCommander(program); // 执行命令
program.parse(process.argv); // 解析参数
help文件
创建提示命令:
javascript
// lib/core/help.js
const help = function(program){
program.option('-f --framwork <framwork>','设置框架')
}
module.exports = help
myCommander文件
执行命令文件:
javascript
// lib/core/myCommander.js
const myaction = require('./action')
const myCommander = function (program) {
program
.command('create <project> [other...]') // 命令
.alias('crt') // 别名
.description('创建项目')
.action(myaction) // 执行
}
module.exports = myCommander
action文件
javascript
// lib/core/action.js
var inquirer = require('inquirer')
var config = require('../../config')
var downloadFun = require('./download')
const myAction = async (project) => {
const answer = await inquirer.prompt([
{
type: 'list',
name: 'framwork',
choices: config.framwork,
message: '请选择你所使用的框架'
}
])
// 下载代码模板
downloadFun(config.foramworkUrl[answer.framwork],project)
}
module.exports = myAction
download文件
选择模板,下载对应的代码文件。
javascript
// lib/core/download.js
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
config文件
配置文件地址:
javascript
module.exports = {
// 可选择的框架
framwork: ['umi', 'other'],
// 框架对应的下载地址
foramworkUrl: {
umi: 'https://gitee.com/mirrors/umi.git',
other: 'xxx', // 自己添加
},
};
本地使用
挂载全局
cd到项目目录,执行 npm link:
bash
npm link
可以看到将当前项目链接到 node 全局 node_modules 中。
安装依赖
bash
npm install
执行脚手架命令
bash
cli create umi
实现效果
总结
至此,一个简单的工程脚手架就完成了。可以继续关注此专栏,之后会增加功能完善的脚手架。