40行代码实现简单版 vue-cli
cli 效果
使用 cli 创建一个 Vue3.x 项目
实现流程
实现之前,我们先简单了解一下 Yeoman。 Yeoman 是一款通用型脚手架工具,没有独立创建项目的能力,需要配合对应的 Generator 才可以完成。举个例子,如果我们需要创建一个 node 项目,我们就需要一个 node 的 Generator,然后通过 Yeoman 快速创建出一个 node 项目
## 安装 Yeoman
npm i yo -g
## 安装 generator-node
npm i generator-node -g
## 创建 node 项目
yo node
Generator 的名称格式都是 generator-[name],使用时 yo + name 即可。 更多Genenrator
了解了 Yeoman 是如何使用之后,我们开始实现自己的 Generator 来完成 Vue 的项目创建。
首先我们初始化一下我们的 Generator,这里我们将其命名 generator-vue。
Yeoman 配合 Generator 创建项目时,会以 generators/app/index 作为程序入口文件 而 geneartors/router/index 会作为子生成器的入口文件(此次不会用,忽略)
然后我们开始便编写生成器代码
// 生成器父类
const Generator = require('yeoman-generator')
// 导出生成器 Yeoman 会根据其进行项目创建
module.exports = class extends Generator {
prompting() {
// 用户输入
}
writing() {
// 文件写入
}
end() {
// 生成器执行完成
}
}
这里 prompting 和 writing 会在 Yeoman 创建项目的特定时期执行,类型 Vue 中的生命周期函数。除了 prompting、writing 和 end 之外,yeoman-generator 还存在以下方法(依次执行)。
- initializing 初始化方法(检查当前项目状态、获取配置等)
- prompting 提示用户选项
- configuring 保存配置和配置项目
- default 其他原型上的方法
- writing 编写生成器特定文件
- conflicts 处理冲突的地方
- install 安装运行的地方
- end 说再见的地方
我们现从用户提示开始
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
async prompting() {
// 用户输入
this.answer = await this.prompt([
{
type: 'input', // 用户提示类型 存在 input | list | checkbox | confirm ...
message: '项目名称?', // 用户提示
name: 'projectName', // 用户回答对应的字段名(通过 this.answer.projectName 便可拿到用户回答)
default: 'vue-project', // 默认值
},
{
type: 'list',
message: '项目的 Vue 版本',
name: 'version',
choices: ['2.x', '3.x'], // 选项
default: '2.x',
},
])
}
writing() {
// 文件写入 输出用户回答
this.log('projectName', this.answer.projectName)
this.log('version', this.answer.version)
}
}
由于我们 Generator 并没有发布到 npm 上,全局的 Yeoman 还访问不到我们我们写的 generator-vue,所有我们还需要将自己的包链接到本地
## 根目录
npm link
yo vue
成功!正常输入我们的选择。
然后我们开始通过用户选择的配置进行 vue 项目的创建(文件读写)
思路:
- 准备 vue 项目模版文件
- 根据用户选择的配置进行对应文件读写和内容替换
- 我们的 Generator 支持不同版本的 Vue,所以我们需要分别准备 2.x 和 3.x 的 Vue 项目模版。
2. 读取对应版本模版 -> 内容替换 -> 输出到指定目录
const Generator = require('yeoman-generator')
module.exports = class extends Generator {
async prompting() {
// 用户输入
this.answer = await this.prompt([
{
type: 'input', // 用户提示类型 存在 input | list | checkbox | confirm ...
message: '项目名称?', // 用户提示
name: 'projectName', // 用户回答对应的字段名(通过 this.answer.projectName 便可拿到用户回答)
default: 'vue-project', // 默认值
},
{
type: 'list',
message: '项目的 Vue 版本',
name: 'version',
choices: ['2.x', '3.x'], // 选项
default: '2.x',
},
])
}
writing() {
const { projectName, version } = this.answer
this.fs.copyTpl(
// templatePath 方法以 Generator 入口文件下的 templates 为基础路径进行拼接
this.templatePath(version),
// 以 Yeoman 执行的当前目录为基础路径进行拼接
this.destinationPath(projectName),
{
projectName, // ejs 模版中的变量
}
)
}
}
到此我们便完成了简单版的 Vue 脚手架。
最后,如果想了解更多关于 Yeoman 的内容。可以关注以下文档。