1. 前言
一个CLI插件其实就是一个npm包,它可以为Vue CLI创建的项目添加额外功能,这些内容包括:
-
修改项目webpack配置
-
添加vue-cli-service命令
-
扩展package.json
-
在项目中创建新文件或修改老文件内容
-
提供用户选项
2. 主要结构
├── README.md
├── generator.js # generator(可选)
├── index.js # service 插件
├── package.json
├── prompts.js # prompt 文件(可选)
└── ui.js # Vue UI 集成(可选)
- README.md
插件介绍及使用文档
- generator.js
一个发布为npm包的Vue CLI插件可以包含一个generator.js或者generator/index.js文件。它在以下两种场景会被调用:
1.在一个项目初始化创建过程中,如果CLI插件作为项目创建preset的一部分被安装。
2.插件在项目创建好之后通过vue invoke独立调用时被安装。
- index.js
Service插件通俗理解主要起修改webpack配置所用。
- package.json
不过多阐述
- prompts.js
prompt选项配置
- ui.js
Vue UI相关配置
3. Generator
介绍
Generator部分是当你想要为当前Vue CLI创建的项目添加项目扩展包、创建新文件或者编辑已存在的文件时需要。
参数
一个generator应该导出一个接受三个参数的函数:
-
一个GeneratorAPI实例;
-
插件的generator选项。使用
prompts.js创建对话的参数,或者从一个保存在~/.vuerc中的preset中加载。
例如:
{
"presets": {
"foo": {
"plugins": {
"@vue/cli-plugin-foo": { "option": "bar" }
}
}
}
}
如果用户使用preset foo创建了一个项目,那么@vue/cli-plugin-foo的generator就会收到{ option: 'bar' }作为第二个参数。
- 整个
preset(presets.foo)将会作为第三个参数传入。
GeneratorAPI
-
extendPackage
-
入参
- { object | () => object }
-
使用说明:在package.json中增加依赖。除非传递
{ merge:false },否则嵌套字段是深度合并的,还解决插件间的依赖冲突。
-
-
render
-
入参
-
{ string | object | FileMidderware } 可以是某个文件夹的相对路径、自定义文件中间件函数、
{ sourceTemplate: targetFile }映射的对象哈希 -
{ object }[additionalData] 模版可用的其他数据
-
{ object }[ejsOptions] ejs额外参数
-
-
使用说明:使用ejs渲染文件到项目结构中
-
-
resolve
-
入参
- { string }相对于工程根目录的目录
-
返回值
- { string }文件绝对路径
-
使用说明
- 获取一个文件/文件夹的绝对路径
-
4. Service插件
介绍
Service插件会在一个Service实例被创建时自动加载——比如每次执行vue-cli-service命令时被调用。
此外@vue/cli-service的内建命令和配置模块也全部以service插件实现的。
参数
一个service插件应该导出一个函数,这个函数接受两个参数
-
一个PluginAPI实例
-
一个包含
vue.config.js内指定的项目本地选项对象,或者在package.json内的vue字段。
PlguinAPI
-
registerCommand
-
作用:在cli中注册一个类似于
vue-cli-service [name]的命令 -
入参:
-
name(命令名称)
-
args(可选参数)
-
-
{
description: string,
usage: string,
options: { [string]: string }
}
以vue-cli-service build为例
module.exports = (api, options) => {
api.registerCommand('serve', {
description: 'start development server',
usage: 'vue-cli-service serve [options] [entry]',
options: {
'--open': `open browser on server start`,
'--copy': `copy url to clipboard on server start`,
'--mode': `specify env mode (default: development)`,
'--host': `specify host (default: ${defaults.host})`,
'--port': `specify port (default: ${defaults.port})`,
'--https': `use https (default: ${defaults.https})`,
'--public': `specify the public network URL for the HMR client`,
'--skip-plugins': `comma-separated list of plugin names to skip for this run`
}})
}
-
chainWebpack
-
作用:通过链式的方式修改webpack相关配置
-
入参:callback
-
-
configureWebpack
- 作用:修改webpack配置,注意如果
configureWebpack为Object,是merge配置操作!如果configureWebpack为Function,是直接修改配置!
- 作用:修改webpack配置,注意如果
module.exports = (api, projectOptions) => {
api.chainWebpack(webpackConfig => {
// 通过webpack-chain修改webpack配置
})
api.configureWebpack(webpackConfig => {
// 修改webpack配置
// 或者返回webpack-merge合并的配置对象
})
api.registerCommand('test', args => {
// 注册 vue-cli-service test
})
}
// 如果已经注册的插件命令需要运行在特定的模式下,需要module.exports.defaultModes({ key: value })的形式暴露
module.exports.defaultModes = { build: 'production' }
-
resolveWebpackConfig
- 作用:得到使用过
api.configureWebpack或者api.chainWebpack之后到修改后的webpack值
- 作用:得到使用过
-
getCwd
- 作用:当前工作目录
-
version
- 作用:当前使用cli的
@vue/cli-service版本
- 作用:当前使用cli的
-
resolve
-
作用:返回指定目录的绝对路径
-
入参:相对于根目录的目录
-
5. Prompts
大家是否还记得vue create创建项目或者vue add插件添加插件的时候,需要用户处理一些选择。所有的逻辑均在prompts.js中进行实现。
当用户初始化插件时,如果插件的根目录存在prompts.js时,则会对其进行调用。
prompts.js导出可以有两种方式:
-
导出一个数组
-
导出一个函数
其中导出结果将为generator/index.js的第二个参数
导出数组的结构
{
// 默认值为输入:input
type: "input | number | confirm | list | rawlist | expand | checkbox | password | editor",
// 可以通过generator/index.js的第二个参数进行获取
name: String,
// 问题内容。如果定义为函数,则第一个参数将是当前查询者会话答案。缺省值为name(后跟冒号)
message: String | Function,
// 当前问题默认值,如果定义为函数,则第一个参数将是当前查询者会话答案。
default: String | Number | Boolean | Array | Function,
// Choices数组或返回choices数组的函数。如果定义为函数,则第一个参数将是当前查询者会话答案
choices: Array | Function,
// 校验输入的值是否符合要求
validate:Function,
// 接收用户输入并返回要在程序内部使用的过滤值
filter: Function,
// 接收当前用户的答案哈希,并应返回true或false取决于是否应询问此问题
when: Boolean | Function,
// 当使用list, rawList, expand, checkbox的时候可能存在分页
pageSize: Number,
// 更改默认的前缀消息
prefix: String,
// 更改默认的后缀消息
suffix: String
}