使用 Yeoman 40行代码实现简单版 vue-cli

1,035 阅读3分钟

40行代码实现简单版 vue-cli

cli 效果

使用 cli 创建一个 Vue3.x 项目

image.png

image.png

image.png

image.png

实现流程

实现之前,我们先简单了解一下 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。

image.png

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

image.png 成功!正常输入我们的选择。

然后我们开始通过用户选择的配置进行 vue 项目的创建(文件读写)

思路:

  • 准备 vue 项目模版文件
  • 根据用户选择的配置进行对应文件读写和内容替换
  1. 我们的 Generator 支持不同版本的 Vue,所以我们需要分别准备 2.x 和 3.x 的 Vue 项目模版。

image.png 2. 读取对应版本模版 -> 内容替换 -> 输出到指定目录

image.png

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 模版中的变量
      }
    )
  }
}

image.png 到此我们便完成了简单版的 Vue 脚手架。

最后,如果想了解更多关于 Yeoman 的内容。可以关注以下文档。