专栏首页前端劝退师「Vue进阶」一篇文章,教你学会Vue-CLI 插件开发

「Vue进阶」一篇文章,教你学会Vue-CLI 插件开发

1. 什么是 CLI plugin

如果你正在使用Vue框架,那么你肯定知道 VueCLI是什么。 Vue-CLI3,它是Vue.js 开发的标准工具(脚手架),提供项目支架和原型设计。

除了日常构建打包项目, VueCLI3 的一个重要部分是 cli-plugins,插件开发。它可以修改内部webpack配置并将命令注入到vue-cli-service。一个很好的例子是 @vue/cli-plugin-typescript:当你调用它时,它会 tsconfig.json为你的项目添加一个并更改 App.vue类型,整个过程不需要手动执行。

插件非常有用,但有很多不同的情况: Electron构建器,添加 UI库,如 iviewElementUI ....如果你想为某个特定的库提供一个插件但却不存在呢?这时候,构建一个属于自己项目的插件就是个不错的选择。

vue ui

在本文中,我们将构建一个 vue-cli-plugin-rx。它允许我们向项目添加 vue-rx库,并在我们的Vue应用程序中获得 RxJS支持。

2. Vue-cli插件目录结构

CLI 插件是一个可以为 @vue/cli项目添加额外特性的 npm 包。它应该始终包含:

  • 一个 Service插件作为其主要导出
  • 可选的包含一个 Generator 和一个 Prompts 文件。
.
├── README.md
├── generator.js  # generator (可选)
├── prompts.js    # prompt 文件 (可选)
├── index.js      # service 插件
└── package.json

如果你需要在插件安装的同时,通过命令行来选择是否创建一些示例组件,那么目录可以改为:

.
├── README.md
├── generator
│   └── index.js  # generator
├── prompts.js    # 命令行提示安装
├── index.js      # service 插件
└── package.json

2.1 GeneratorAPI

一个发布为 npm 包的 CLI 插件可以包含一个 generator.jsgenerator/index.js 文件。插件内的 generator 将会在两种场景下被调用:

  • 在一个项目的初始化创建过程中,如果 CLI 插件作为项目创建 preset 的一部分被安装。
  • 插件在项目创建好之后通过 vue invoke 独立调用时被安装。

GeneratorAPI允许一个 generatorpackage.json 注入额外的依赖或字段,并向项目中添加文件。

2.2 Service 插件

Service插件接收两个参数的函数:一个 PluginAPI实例和一个包含项目本地选项的对象。它可以扩展/修改不同环境的内部 webpack配置,并为其注入其他命令 vue-cli-service

但在这里,我们只想在必要时添加一些依赖项和示例组件。所以我们的 index.js长这样:

module.exports = (api, opts) => {}

如果你想改变内部 webpack配置或其它操作,请在官方Vue CLI文档中阅读本节

2.3 Package.json

直接通过 npm init初始化

keywords 指定了在库中搜索时能够被哪些关键字搜索到,所以一般这个会多写一些项目相关的词在这里,是一个字符串的数组。

{
  "name": "vue-cli-plugin-rx",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "keywords": [
    "vue",
    "vue-cli",
    "rxjs",
    "vue-rx"
  ],
  "author": "",
  "license": "ISC"
}

3. 通过generator添加依赖项

generator可帮助我们添加依赖项并更改项目文件。所以,我们需要的第一步是让我们的插件添加两个依赖项: rxjsvue-rx

// generator/index.js
module.exports = (api, options, rootOptions) => {
  api.extendPackage({
    dependencies: {
      'rxjs': '^6.3.3',
      'vue-rx': '^6.1.0',
    },
  });
}

generator 导出一个接收三个参数的函数: GeneratorAPI实例,生成器选项和 - 如果用户使用某个预设创建项目 - 整个预设将作为第三个参数传递。

api.extendPackage方法将会修改项目的 package.json

在本文的例子中,我们将两个依赖项添加到 dependencies

现在我们需要更改 main.js文件。为了使 RxJS能在Vue组件中工作,我们需要导入 VueRx和调用 Vue.use(VueRx)

  • 首先,我们创建一个想要添加的字符串到主文件:
let rxLines = `\nimport VueRx from 'vue-rx';\n\nVue.use(VueRx);`;
  • 使用 api.onCreateCompletehook。在文件写入磁盘时调用它:
api.onCreateComplete(() => {
    const fs = require('fs');
    const mainPath = api.resolve(''./src/main.js');
};
  • 现在我们修改文件内容:
api.onCreateComplete(() => {
    const fs = require('fs');
    const mainPath = api.resolve('./src/main.js');
    // 获取内容
    let contentMain = fs.readFileSync(mainPath, { encoding: 'utf-8' });
    const lines = contentMain.split(/\r?\n/g).reverse();
    // 注入import
    const lastImportIndex = lines.findIndex(line => line.match(/^import/));
    lines[lastImportIndex] += rxLines;
    // 修改应用
    contentMain = lines.reverse().join('\n');
    fs.writeFileSync(mainPath, contentMain, { encoding: 'utf-8' });
  });
};

4. 本地测试cli-plugin

首先我们创建一个简单的Vue-cli项目:

vue create hello-world

cd到项目文件夹并安装我们新创建的插件:

cd hello-world
npm install --save-dev file://Users/hiro/练习/测试/vue-plugin

安装插件后,需要调用它:

vue invoke vue-cli-plugin-rx

现在,你查看 test-app项目的 main.js,将会看到:

import Vue from 'vue'
import App from './App.vue'
import VueRx from 'vue-rx';
Vue.use(VueRx);

同时,查看 package.json将会发现:

"dependencies": {
    "core-js": "^2.6.5",
    "rxjs": "^6.3.3",
    "vue": "^2.6.10",
    "vue-router": "^3.0.3",
    "vue-rx": "^6.1.0",
    "vuex": "^3.0.1"
  }

5. 通过generator创建示例组件

经过上面的验证,插件已有效。此时,我们可以扩展一下它的功能,创建示例组件,方便其他人理解和使用。

5.1 编写示例组件

我们创建的这个示例组件。它应该是位于项目 src/components文件夹中的文件。

于是我们可以在 generator目录下,创建 /template/src/components:

这一个简单的 RxJS驱动的计数器,带有两个按钮

源码如下:

<template>
    <section>
        <h1>Click on 'Count' button to count your clicks</h1>
        <button v-stream:click="count$">Count clicks</button>
        <button @click="clearCounter">Clear counter</button>
        <p>{{result$}}</p>
    </section>
</template>

<script>
import {
  filter,
  bufferWhen,
  debounceTime,
  map,
  startWith,
} from 'rxjs/operators';
export default {
  domStreams: ['count$'],
  subscriptions() {
    return {
      result$: this.count$.pipe(
        filter(event => !!event),
        bufferWhen(() => this.count$.pipe(debounceTime(400))),
        map(clicks => clicks.length),
        startWith(0),
      ),
    };
  },
  methods: {
    clearCounter() {
      this.count$.next(null);
    },
  },
};
</script>

<style>
button {
  padding: 10px;
  font-size: 14px;
  margin-right: 10px;
  border-radius: 4px;
  outline: none;
}
</style>

这里我们不需要关心 RxJS做了什么(反正我也没看懂),引入 就 vans了。

此时我们需要改动 generator/index.js,使它可以识别并写入文件夹。

api.render('./template', {
  ...options,
});

当你调用 api.render('./template')时,generator将会使用 EJS渲染 `./template `中的文件 (相对于 generator`中的文件路径进行解析)

5.2 命令行提示安装

如果用户是个老手,不想拥有示例组件,该怎么办?在插件安装过程中,我们可以向 prompts.js添加提示代码,以供用户在命令行选择:

module.exports = [
  {
    name: `addExample`,
    type: 'confirm',
    message: '是否添加示例组件到项目components目录?',
    default: false,
  },
];

询问用户是否要将示例组件添加到项目 components目录下。默认是: false

这时我们需要修改下 generator/index.js:

if (options.addExample) {
    api.render('./template', {
      ...options,
    });
}

此时我们撤回安装,重新运行

yarn add --save-dev file://Users/hiro/练习/测试/vue-plugin

vue invoke vue-cli-plugin-rx

将会看到:

此时你查看项目components目录,将会发现多了示例组件文件

6.如何发布插件

来自官方文档

为了让一个 CLI 插件能够被其它开发者使用,你必须遵循 vue-cli-plugin-<name> 的命名约定将其发布到 npm 上。插件遵循命名约定之后就可以:

  • 被 @vue/cli-service 发现;
  • 被其它开发者搜索到;
  • 通过 vue add 或 vue invoke 安装下来。

你只需要在 package.json中添加描述 description,以及在插件项目根目录下创建 logo.png

接下来就是注册npmjs.com

2、设置仓库地址为npm官方仓库地址(国内大部分都使用阿里淘宝镜像,如果没改publish会失败)
npm config set registry https://registry.npmjs.org/

3、登陆npm,用户名密码邮箱需要全部匹配
npm whoami
npm login
Username: xxxxx
Password:
Email: (this IS public) xxx@gmail.com
Logged in as xxxxx on https://registry.npmjs.org/.

4、登陆完可以publish了,执行以下命令
cd dist && npm publish && cd ../
或npm publish dist
输出以下信息说明发布成功
+ ngx-xxx@0.0.1
这时登录https://www.npmjs.com/可以看到自己发布的项目

完事。

总结

Vue-CLI插件开发,对于很多项目,当你需要引入一些自己以前编写过的组件或功能,却不想复刻一遍main.jsPackage.json,学会了这招,开发贼快。当有人问你如何组织项目的组件库时,啧啧...你说你都是安装自己写的插件。

本文分享自微信公众号 - 前端劝退师(quantuishi),作者:前端劝退师

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-04-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 腾讯CDC团队:前端异常监控解决方案

    前端监控包括行为监控、异常监控、性能监控等,本文主要讨论异常监控。对于前端而言,和后端处于同一个监控系统中,前端有自己的监控方案,后端也有自己等监控方案,但两者...

    前端劝退师
  • 「中高级前端」窥探数据结构的世界- ES6版

    数据结构是在计算机中组织和存储数据的一种特殊方式,使得数据可以高效地被访问和修改。更确切地说,数据结构是数据值的集合,表示数据之间的关系,也包括了作用在数据上的...

    前端劝退师
  • Vue 3.0前的 TypeScript 最佳入门实践

    然鹅最近的一个项目中,是 TypeScript+ Vue,毛计喇,学之...…真香!

    前端劝退师
  • 学点vue.js的东西,什么都得学点,面试时说不定对方会问什么

    说vue呢也是关注视图层的框架,它嫌react太绕了,redux太麻烦了,然后就说自己很简单,说自己还有双向绑定,好的很,不是小好,是大好。那我今天就写点vue...

    web前端教室
  • flag - 4-5月份预整理总结的文章目录

    xing.org1^
  • Vue创建项目配置

      安装VS Code,开始vue的学习及编程,但是总是遇到各种各样的错误,控制台语法错误,格式错误。一股脑的袭来,感觉创建个项目怎么这个麻烦。这里就讲一下vu...

    小世界的野孩子
  • vue2.0做移动端开发用到的相关插件和经验总结

    Daotin
  • [技术地图] vue-cli

    这是一个新开的’实验性’文章系列,如其名‘技术地图’,这个系列计划剖析一些前端开源项目,可能会探讨这些项目的设计和组织、整理他们使用到技术栈。 首先拿vue-c...

    _sx_
  • 学界 | 康奈尔大学说对抗样本出门会失效,被OpenAI怼回来了!

    AI科技评论按:看来,我们还是不能对对抗样本问题掉以轻心。 上周,康奈尔大学的一篇论文表示,当图像识别算法应用于实际生活场景下(比如自动驾驶)时,可能不需要那么...

    AI科技评论
  • 罗永浩双喜临门!锤子融资后京东又为坚果Pro举办百日宴

    近日锤子科技的融资引发行业不小关注, 10亿元新融资的助力也必将让老罗的业务越来越顺。不仅如此,日前京东也特意为坚果Pro举办百日宴,可谓双喜临门。看样子罗永浩...

    罗超频道

扫码关注云+社区

领取腾讯云代金券