如果你正在使用Vue框架,你可能已经知道什么是Vue CLI了。它是一个用于快速开发Vue.js的完整系统,提供项目脚手架。
CLI的一个重要部分是cli-plugins。它们可以修改内部的webpack配置并向vue-cli服务注入命令。
一个很好的例子是 @vuecli-plugin-typescript :当你调用它时,它会给你的项目添加一个tsconfig.json,并改变App.vue的类型,所以你不需要手动去做。
插件是非常有用的,但如果你想有一个用于某些特定库的插件而它不存在呢?嗯,当我们是这样子的情况时……我们决定自己建立它。
在这篇文章中,我们将建立一个vue-cli-plugin-tiantian。它允许我们将vue-rx库添加到我们的项目中,并在我们的Vue应用程序中获得RxJS支持。
让我们来看看整个的大致流程吧。
Vue-CLI插件结构
首先,什么是CLI插件?它只是一个具有一定结构的npm包。关于文档,它必须有一个服务插件作为其主要出口,并可以有额外的功能,例如生成器和提示文件。
目前,绝对不清楚什么是服务插件或生成器,但不用担心–以后会有解释的!
当然,像任何npm软件包一样,CLI插件在其根文件夹中必须具有package.json,并且最好具有一些说明的README.md。
因此,让我们从以下结构开始。
.
├── README.md
├── index.js # service plugin
└── package.json
现在让我们来看看可选部分。生成器可以在package.json中注入额外的依赖关系或字段,并向项目中添加文件。我们需要它吗?
当然,我们想把rxjs和vue-rx作为我们的依赖项。更确切地说,我们想创建一些示例组件,如果用户想在安装插件时添加它。
因此,我们需要添加 generator.js 或 generatorindex.js。我更喜欢第二种方式。现在的结构看起来是这样的:
.
├── README.md
├── index.js # service plugin
├── generator
│ └── index.js # generator
└── package.json
还有一件事要添加,就是一个提示文件。我希望我的插件能够询问用户是否想拥有一个示例组件。我们将需要在根目录下有一个prompts.js文件来实现这一行为。所以,现在的结构是这样的:
服务插件(Service plugin)
一个服务插件应该输出一个函数,它接收两个参数:一个PluginAPI实例和一个包含项目本地选项的对象。
它可以针对不同的环境扩展修改内部的webpack配置,并向vue-cli-service注入额外的命令。
让我们想一想:我们是否想以某种方式改变webpack配置或创建一个额外的npm任务?
答案是否定的,我们只想在必要时添加一些依赖项和示例组件。因此,我们需要在index.js中改变的是:
module.exports = (api, opts) => {}
如果您的插件需要更改Webpack配置,请阅读Vue官方CLI文档中的本节。
https://cli.vuejs.org/dev-guide/plugin-dev.html#service-plugin
通过生成器添加依赖项
如上所述,CLI插件生成器可以帮助我们添加依赖性和改变项目文件。
因此,第一步我们需要做的是为我们的插件添加两个依赖项:Rxjs和vue-rx:
module.exports = (api, options, rootOptions) => {
api.extendPackage({
dependencies: {
'rxjs': '^6.3.3',
'vue-rx': '^6.0.1',
},
});
}
一个生成器应该输出一个函数,该函数接收三个参数:一个GeneratorAPI实例,生成器选项和–如果用户使用某些预设创建一个项目–整个预设将作为第三个参数传递。
api.extendPackage方法扩展了项目的package.json。嵌套的字段会被深度合并,除非你把**{ merge: false }**作为一个参数。在我们的例子中,我们要添加两个依赖项到依赖项部分。
现在我们需要改变一个main.js文件。为了让RxJS在Vue组件中工作,我们需要导入一个VueRx并调用Vue.use(VueRx)。
首先,让我们创建一个我们想要添加到主文件的字符串:
let rxLines = `\nimport VueRx from 'vue-rx';\n\nVue.use(VueRx);`;
现在我们要使用api.onCreateComplete 钩子函数。当文件被写入磁盘时,它被调用:
api.onCreateComplete(() => {
// inject to main.js
const fs = require('fs');
const ext = api.hasPlugin('typescript') ? 'ts' : 'js';
const mainPath = api.resolve(`./src/main.${ext}`);
};
这里我们要找的是主文件:如果是TypeScript项目,会是main.ts,否则就是main.js文件。fs这里是文件系统。