本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-02-26
CLI 插件是一个可以为 @vue/cli
项目添加额外特性的 npm 包。它应该始终包含:
目录:
.
├── README.md
├── generator.js # generator(可选)
├── generator # 同上 不同的形式而已
│ ├─── index.js
│ └─── template
├── index.js # service 插件
├── package.json
├── prompts.js # prompt 文件(可选)
└── ui.js # Vue UI 集成(可选)
一个发布为 npm 包的 CLI 插件可以包含一个 generator.js
或 generator/index.js
文件。
插件内的 generator 将会在两种场景下被调用:
vue invoke
独立调用时被安装。功能:GeneratorAPI允许一个 generator 向 package.json
注入额外的依赖或字段,并向项目中添加文件。
Service 插件接收两个参数的函数:
vue.config.js
内指定的项目本地选项的对象,或者在 package.json
内的 vue 字段。功能:它可以扩展/修改不同环境的内部webpack配置,并为其注入其他命令vue-cli-serve。
该文件是必须的,如果插件不是为了实现这部分功能,可以这样写:
module.exports = () => {}
修改 webpack 配置:
// plugin/index.js
const VueAutoRoutingPlugin = require('vue-auto-routing/lib/webpack-plugin')
module.exports = (api, options) => {
api.chainWebpack(webpackConfig => {
webpackConfig
.plugin('vue-auto-routing')
.use(VueAutoRoutingPlugin, [
{
pages: 'src/pages',
nested: true
}
])
})
}
注入其他命令,请参考项目本地的插件。
需要注意的是,如果一个已注册的插件命令需要运行在特定的默认模式下,则该插件需要通过 module.exports.defaultModes
以 { [commandName]: mode }
的形式来暴露:
// plugin/index.js
module.exports = api => {
api.registerCommand('build', () => {
// ...
})
}
module.exports.defaultModes = {
build: 'production'
}
// plugin/package.json
{
"name": "vue-cli-plugin-rx",
"version": "1.0.0",
"description": "",
"main": "index.js",
"keywords": [
"vue",
"vue-cli",
"rxjs",
"vue-rx"
],
"author": "",
"license": "ISC"
}
keywords 指定了在库中搜索时能够被哪些关键字搜索到,所以一般这个会多写一些项目相关的词在这里,是一个字符串的数组。
name 必须以vue-cli-plugin
开头。
generator可帮助我们添加依赖项并更改项目文件。所以,我们需要的第一步是让我们的插件添加依赖项。
// /plugin/generator/index.js
module.exports = (api, options, rootOptions) => {
// 注入依赖 api.extendPackage`方法将会修改项目的`package.json
api.extendPackage({
dependencies: {
rxjs: '^6.3.3',
'vue-rx': '^6.1.0'
}
})
}
module.exports.hooks = (api) => {
// api.entryFile 返回项目的主文件(main.js 或 main.ts)
const mainPath = api.entryFile
const rxLine = 'import VueRx from \'vue-rx\';'
// 如果只是引入依赖可使用 injectImports API
// injectImports 用于添加新的导入到主文件中
// api.injectImports(mainPath, rxLine)
// 在这里 需要引入依赖并使用use 这个钩子将在插件被文件被写入硬盘之后被调用
api.afterInvoke(() => {
const { EOL } = require('os')
const fs = require('fs')
const contentMain = fs.readFileSync(api.resolve(mainPath), { encoding: 'utf-8' })
const lines = contentMain.split(/\r?\n/g).reverse() // reverse之后 findIndex 就是找到最后一行的import了
const lastImportIndex = lines.findIndex(line => line.match(/^import/)) // 找到最后一行import语句
lines[lastImportIndex] += `${EOL}${rxLine}${EOL}${EOL}Vue.use(VueRx);` // 加入 use 语句
fs.writeFileSync(mainPath, lines.reverse().join(EOL), { encoding: 'utf-8' })
})
}
generator 导出一个接收三个参数的函数:
~/.vuerc
载入预设时被解析。如果有创建项目时使用的 preset (参考 preset ) 如下:
{
"presets" : {
"foo": {
"plugins": {
"@vue/cli-plugin-foo": { "option": "bar" }
}
}
}
}
那么 @vue/cli-plugin-foo
的 generator 就会收到 { option: 'bar' }
作为第二个参数。
# 插件指向的绝对路径 例: /Users/xxx/project/hello-pro/plugin
npm install --save-dev file:/full/path/to/your/plugin
vue invoke <your-plugin-name>
.
├── generator
│ ├─── index.js
│ └─── template
│ └─── src
│ └─── components
│ └─── RxExample.vue
模板创建完之后,你应该在 generator/index.js
文件中添加 api.render
调用:
// plugin/generator/index.js
module.exports = api => {
api.render('./template')
}
当你调用api.render('./template')
时,generator将会使用 EJS 渲染 ./template
中的文件 (相对于 generator中的文件路径进行解析)。
在插件安装过程中,我们可以向 prompts.js
添加提示代码,以供用户在命令行选择:
// plugin/prompts.js
module.exports = [
{
name: 'addExample',
type: 'confirm',
message: '是否添加示例组件到项目components目录?',
default: false,
},
];
// 或者返回一个函数
// 将 `package.json` 作为参数传入函数
module.exports = pkg => {
const prompts = [
{
name: 'addExample',
type: 'confirm',
message: '是否添加示例组件到项目components目录?',
default: false,
}
]
// 添加动态对话
if ('@vue/cli-plugin-eslint' in (pkg.devDependencies || {})) {
prompts.push({
type: 'confirm',
name: 'useESLintPluginVueI18n',
message: 'Use ESLint plugin for Vue I18n ?'
})
}
return prompts
}
这时我们需要修改下 generator/index.js
module.exports = (api, options) => {
if (options.addExample) {
api.render('./template', {
...options,
});
}
}
你必须遵循 vue-cli-plugin-<name>
或者 @scope/vue-cli-plugin-<name>
这样的命名惯例 的命名约定将其发布到 npm 上。插件遵循命名约定之后就可以,这样你的插件才能够:
vue add <name>
或者 vue invoke <name>
安装。为了能够被用户在搜索时更好的发现,可以将插件的关键描述放到 package.json 文件的 description 字段中。
你应该在 homepage 或者 repository 字段添加创建插件的官网地址或者仓库的地址,这样你的插件详情里就会出现一个 查看详情 按钮:
{
"repository": {
"type": "git",
"url": "git+https://github.com/Akryum/vue-cli-plugin-apollo.git"
},
"homepage": "https://github.com/Akryum/vue-cli-plugin-apollo#readme"
}
发布步骤参考 发布npm模块