「Vue進階」5分鐘擼一個Vue CLI 插件

前言

若是你正在使用Vue框架,那麼你確定知道Vue CLI是什麼。Vue-cli 3,它是Vue.js 開發的標準工具(腳手架),提供項目支架和原型設計。html

除了平常構建打包項目,Vue CLI3 的一個重要部分是cli-plugins,插件開發。前端

本文將教你如何科學的建立一個Vue-CLI 插件,以及項目獨立npm包。vue

1. 什麼是CLI plugin

它能夠修改內部webpack配置並將命令注入到vue-cli-service。一個很好的例子是@vue/cli-plugin-typescript:當你調用它時,它會tsconfig.json爲你的項目添加一個並更改App.vue類型,整個過程不須要手動執行。webpack

插件很是有用,但有不少不一樣的狀況: Electron構建器,添加UI庫,如iviewElementUI ....若是你想爲某個特定的庫提供一個插件但卻不存在呢?這時候,構建一個屬於本身項目的插件就是個不錯的選擇。web

在本文中,咱們將構建一個vue-cli-plugin-rx。它容許咱們向項目添加vue-rx庫,並在咱們的Vue應用程序中得到RxJS支持。面試

2. Vue-cli插件目錄結構

CLI 插件是一個能夠爲 @vue/cli項目添加額外特性的 npm 包。它應該始終包含:vue-router

  • 一個Service插件做爲其主要導出
  • 可選的包含一個 Generator 和一個 Prompt 文件。
.
├── README.md
├── generator.js  # generator (可選)
├── prompts.js    # prompt 文件 (可選)
├── index.js      # service 插件
└── package.json
複製代碼

若是你須要在插件安裝的同時,經過命令行來選擇是否建立一些示例組件,那麼目錄能夠改成:vuex

.
├── README.md
├── generator
│   └── index.js  # generator
├── prompts.js    # 命令行提示安裝
├── index.js      # service 插件
└── package.json
複製代碼

2.1 GeneratorAPI

一個發佈爲 npm 包的 CLI 插件能夠包含一個 generator.jsgenerator/index.js 文件。插件內的 generator 將會在兩種場景下被調用:vue-cli

  • 在一個項目的初始化建立過程當中,若是 CLI 插件做爲項目建立 preset 的一部分被安裝。
  • 插件在項目建立好以後經過 vue invoke 獨立調用時被安裝。

GeneratorAPI容許一個 generatorpackage.json 注入額外的依賴或字段,並向項目中添加文件。typescript

2.2 Service 插件

Service 插件接收兩個參數的函數:一個PluginAPI實例和一個包含項目本地選項的對象。它能夠擴展/修改不一樣環境的內部webpack配置,併爲其注入其餘命令vue-cli-service

但在這裏,咱們只想在必要時添加一些依賴項和示例組件。因此咱們的index.js長這樣:

module.exports = (api, opts) => {}
複製代碼

若是你想改變內部webpack配置或其它操做,請在官方Vue CLI文檔中閱讀本節

2.3 Package.json

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 test-app
複製代碼

cd到項目文件夾並安裝咱們新建立的插件:

cd test-app
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 <name>vue invoke <name> 安裝下來。

你只須要在package.json中添加描述description,以及在插件項目根目錄下建立logo.png

接下來就是註冊npmjs.com

二、設置倉庫地址爲npm官方倉庫地址(國內大部分都使用阿里淘寶鏡像,若是沒改publish會失敗)
npm config set registry https://registry.npmjs.org/

三、登錄npm,用戶名密碼郵箱須要所有匹配
npm whoami
npm login
Username: xxxxx
Password:
Email: (this IS public) xxx@gmail.com
Logged in as xxxxx on https://registry.npmjs.org/.

四、登錄完能夠publish了,執行如下命令
cd dist && npm publish && cd ../
或npm publish dist
輸出如下信息說明發布成功
+ ngx-xxx@0.0.1
這時登陸https://www.npmjs.com/能夠看到本身發佈的項目
複製代碼

完事。

總結

Vue-CLI插件開發,對於不少項目,當你須要引入一些本身之前編寫過的組件或功能,卻不想復刻一遍main.jsPackage.json,學會了這招,開發賊快。當有人問你如何組織項目的組件庫時,嘖嘖...你說你都是安裝本身寫的插件。

做者掘金文章總集

公衆號

相關文章
相關標籤/搜索