如何构建 Vue CLI 插件
本文转载自ITNEXT
如果你正在使用 Vue 框架,你可能已经知道什么是 Vue CLI。它是一个用于快速开发 Vue.js 的完整系统,提供项目脚手架和原型设计。
CLI 的一个重要组成部分是 cli-plugins。它们可以修改内部 webpack 配置并将命令注入到vue-cli-service
。一个很好的例子是@vue/cli-plugin-typescript
:当你调用它时,它会将 添加tsconfig.json
到你的项目中,并更改App.vue
为 类型,因此你无需手动执行此操作。
插件非常有用,如今市面上有很多插件,适用于各种场景——GraphQL + Apollo支持、Electron 构建器、添加 UI 库(例如Vuetify或ElementUI)等等。但是,如果你想为某个特定的库添加插件,而它又不存在,该怎么办呢?嗯,我就是这种情况😅……所以我决定自己动手做一个。
在本文中,我们将构建一个vue-cli-plugin-rx 插件vue-rx
。它允许我们在项目中添加一个库,并在 Vue 应用程序中获得 RxJS 支持。
🎛️ Vue-cli 插件结构
首先,什么是 CLI 插件?它只是一个具有特定结构的 npm 包。关于docs,它必须以服务插件作为主要导出,并且可以包含其他功能,例如生成器和提示文件。
目前还不清楚什么是服务插件或生成器,但不用担心 - 稍后会解释!
当然,与任何 npm 包一样,CLI 插件必须package.json
在其根文件夹中有一个,并且最好有一个README.md
带有一些描述的。
那么,让我们从以下结构开始:
.
├── README.md
├── index.js # service plugin
└── package.json
现在我们来看看可选部分。生成器package.json
可以向项目注入额外的依赖项或字段,并添加文件。我们需要它吗?当然,我们想添加rxjs
和vue-rx
作为依赖项!更确切地说,我们希望创建一些示例组件,以便用户在插件安装过程中添加它。因此,我们需要添加generator.js
或generator/index.js
。我更喜欢第二种方式。现在的结构如下所示:
.
├── README.md
├── index.js # service plugin
├── generator
│ └── index.js # generator
└── package.json
还有一件事需要添加,那就是一个提示文件:我希望我的插件能够询问用户是否需要示例组件。我们需要prompts.js
在根文件夹中创建一个文件来实现这个功能。所以,目前的结构如下:
├── README.md
├── index.js # service plugin
├── generator
│ └── index.js # generator
├── prompts.js # prompts file
└── package.json
⚙️ 服务插件
服务插件应该导出一个函数,该函数接收两个参数:一个 PluginAPI 实例和一个包含项目本地选项的对象。它可以扩展/修改内部 webpack 配置以适应不同的环境,并注入额外的命令vue-cli-service
。让我们想一想:我们是否想以某种方式更改 webpack 配置或创建一个额外的 npm 任务?答案是否定的,我们只想在必要时添加一些依赖项和示例组件。因此,我们需要做的更改如下index.js
:
module.exports = (api, opts) => {}
如果您的插件需要更改 webpack 配置,请阅读官方 Vue CLI 文档中的此部分。
🛠️ 通过生成器添加依赖项
如上所述,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 }
dependencies
现在我们需要修改一个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
这是一个文件系统。
现在让我们更改文件内容
api.onCreateComplete(() => {
// inject to main.js
const fs = require('fs');
const ext = api.hasPlugin('typescript') ? 'ts' : 'js';
const mainPath = api.resolve(`./src/main.${ext}`);
// get content
let contentMain = fs.readFileSync(mainPath, { encoding: 'utf-8' });
const lines = contentMain.split(/\r?\n/g).reverse();
// inject import
const lastImportIndex = lines.findIndex(line => line.match(/^import/));
lines[lastImportIndex] += rxLines;
// modify app
contentMain = lines.reverse().join('\n');
fs.writeFileSync(mainPath, contentMain, { encoding: 'utf-8' });
});
};
这里发生了什么?我们读取主文件的内容,将其分成几行并还原它们的顺序。然后,我们搜索包含import
语句的第一行(第二次还原后,它将是最后一行),并rxLines
在那里添加我们的语句。之后,我们反转行数组并保存文件。
💻 本地测试 cli-plugin
让我们添加一些关于插件的信息package.json
,并尝试在本地安装进行测试。最重要的信息通常是插件名称和版本(这些字段在将插件发布到 npm 时是必需的),但您可以随意添加更多信息!完整的package.json
字段列表可以在这里找到。以下是我的文件:
{
"name": "vue-cli-plugin-rx",
"version": "0.1.5",
"description": "Vue-cli 3 plugin for adding RxJS support to project using vue-rx",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/NataliaTepluhina/vue-cli-plugin-rx.git"
},
"keywords": [
"vue",
"vue-cli",
"rxjs",
"vue-rx"
],
"author": "Natalia Tepluhina <my@mail.com>",
"license": "MIT",
"homepage": "https://github.com/NataliaTepluhina/vue-cli-plugin-rx#readme"
}
现在是时候检查我们的插件是如何工作的了!为此,让我们创建一个简单的 vue-cli 项目:
vue create test-app
转到项目文件夹并安装我们新创建的插件:
cd test-app
npm install --save-dev file:/full/path/to/your/plugin
插件安装完成后,需要调用它:
vue invoke vue-cli-plugin-rx
现在,如果您尝试检查该main.js
文件,您会发现它已更改:
import Vue from 'vue'
import App from './App.vue'
import VueRx from 'vue-rx';
Vue.use(VueRx);
devDependencies
此外,您还可以在测试应用程序部分找到您的插件package.json
。
📂 使用生成器创建新组件
太棒了,插件成功了!现在是时候扩展一下它的功能,让它能够创建一个示例组件了。Generator API 使用了一个render
方法来实现这个目的。
首先,让我们创建这个示例组件。它应该.vue
位于项目文件夹中。在组件中src/components
创建一个文件夹,然后在其中模拟以下整个结构:template
generator
你的示例组件应该……嗯,只是一个 Vue 单文件组件!我不会在本文中深入讲解 RxJS,但我创建了一个由 RxJS 驱动的简单点击计数器,其中包含两个按钮:
它的源代码可以在这里找到。
现在我们需要指示我们的插件在调用时渲染这个组件。为此,我们将以下代码添加到generator/index.js
:
api.render('./template', {
...options,
});
这将渲染整个template
文件夹。现在,当插件被调用时,一个新的文件RxExample.vue
将被添加到src/components
文件夹中。
我决定不覆盖原有的组件,
App.vue
而是让用户自行添加示例组件。不过,您可以替换现有文件的部分内容,请参阅文档中的示例。
⌨️ 通过提示处理用户选择
如果用户不想使用示例组件怎么办?让用户在插件安装过程中自行决定,岂不是明智之举?这就是提示存在的原因!
之前,我们prompts.js
在插件根文件夹中创建了一个文件。该文件包含一个问题数组:每个问题都是一个对象,包含一组特定的字段,例如、name
、message
等。choices
type
名称很重要:我们稍后会在生成器中使用它来创建渲染示例组件的条件!
提示符可以有不同的类型,但在 CLI 中最广泛使用的有checkbox
和confirm
。我们将使用后者来创建一个有是/否答案的问题。
因此,让我们将提示代码添加到prompts.js
!
module.exports = [
{
name: `addExample`,
type: 'confirm',
message: 'Add example component to components folder?',
default: false,
},
];
我们有一个addExample
提示,询问用户是否要将组件添加到组件文件夹。默认答案是No
。
让我们回到生成器文件并进行一些修复。将 out api.render
call 替换为
if (options.addExample) {
api.render('./template', {
...options,
});
}
我们正在检查是否addExample
有肯定的答案,如果是,则渲染该组件。
每次更改后,请不要忘记重新安装并测试插件!
📦 公开!
重要提示:在发布插件之前,请检查其名称是否符合模式vue-cli-plugin-<YOUR-PLUGIN-NAME>
。这样您的插件才能被 发现@vue/cli-service
并通过 进行安装vue add
。
我还希望我的插件在 Vue CLI UI 中看起来美观,所以我添加了描述、标签和仓库名称,package.json
并创建了一个 logo。logo 图片应该命名logo.png
并放置在插件根文件夹中。最终,我的插件在 UI 插件列表中显示如下:
现在我们可以发布了。你需要注册一个npmjs.com,并且显然你应该已经安装了 npm。
要发布插件,请转到插件根文件夹并npm publish
在终端中输入。瞧,您刚刚发布了一个 npm 包!
现在你应该可以使用vue add
命令安装插件了。试试看!
当然,本文中描述的插件非常基础,但我希望我的说明能够帮助某人开始 cli-plugins 开发。
你缺少哪种 CLI 插件?欢迎在评论区分享你的想法🤗
鏂囩珷鏉ユ簮锛�https://dev.to/n_tepluhina/how-to-build-a-vue-cli-plugin-3b6b