編寫vue-cli遠程Preset

1.什麼是 vue-cli 插件?

Vue CLI 使用了一套基於插件的架構。如果你查閱一個新創建項目的 package.json,就會發現依賴都是以 @vue/cli-plugin- 開頭的。插件可以修改 webpack 的內部配置,也可以向 vue-cli-service 注入命令。在項目創建的過程中,絕大部分列出的特性都是通過插件來實現的。

基於插件的架構使得 Vue CLI 靈活且可擴展。如果你對開發一個插件感興趣,請翻閱插件開發指南

提示

你可以通過 vue ui 命令使用 GUI 安裝和管理插件。

下面plugins裏面就是常用的vue-cli 插件:

{
  "useConfigFiles": true,
  "plugins": {
    "@vue/cli-plugin-babel": {},
    "@vue/cli-plugin-eslint": {
      "config": "standard",
      "lintOn": [
        "save"
      ]
    },
    "@vue/cli-plugin-unit-mocha": {}
  },
  ....
  ....
  ....  
}

@vue/cli-plugin-babel : 給項目添加babel的配置、 依賴 和 對應的代碼

@vue/cli-plugin-router: 給項目添加router的配置、依賴 和 集成到項目的案例代碼

編寫一個獨立的vue-cli插件:

https://cli.vuejs.org/zh/dev-guide/plugin-dev.html#cli-%E6%8F%92%E4%BB%B6

CLI 插件是一個可以爲 @vue/cli 項目添加額外特性的 npm 包。它應該始終包含一個 Service 插件作爲其主要導出,且可選的包含一個 Generator 和一個 Prompt 文件

一個典型的 CLI 插件的目錄結構看起來是這樣的:

├── README.md
├── generator.js  # generator (可選)
├── prompts.js    # prompt 文件 (可選)
├── index.js      # service 插件
└── package.json

2. 什麼是vue-cli 的Preset?

vue create新建項目時保存的Preset :

一個 Vue CLI preset 是一個包含創建新項目所需預定義選項和插件的 JSON 對象,讓用戶無需在命令提示中選擇它們( 一個preset選項可以自定義 vue create 新建項目的目錄結構,項目的依賴,項目的配置等等 )

vue create 過程中保存的 preset 會被放在你的 home 目錄下的一個配置文件中 (~/.vuerc)。你可以通過直接編輯這個文件來調整、添加、刪除保存好的 preset。

window 系統電腦的 .vuerc文件 在 C:\Users\電腦名稱\ .vuerc

這裏有一個本地 preset 的示例:

{
  "useConfigFiles": true,
  "cssPreprocessor": "sass",
  "plugins": {
    "@vue/cli-plugin-babel": {},
    "@vue/cli-plugin-eslint": {
      "config": "airbnb",
      "lintOn": ["save", "commit"]
    },
    "@vue/cli-plugin-router": {},
    "@vue/cli-plugin-vuex": {}
  }
}

Preset 的數據會被插件生成器(generator)用來生成相應的項目文件。除了上述這些字段,你也可以爲集成工具添加配置:

{
  "useConfigFiles": true,
  "plugins": {...},
  "configs": {
    "vue": {...},
    "postcss": {...},
    "eslintConfig": {...},
    "jest": {...}
  }
}

這些額外的配置將會根據 useConfigFiles 的值被合併到 package.json 或相應的配置文件中。例如,當 "useConfigFiles": true 的時候,configs 的值將會被合併到 vue.config.js 中。

遠程的Preset :

你可以通過發佈 git repo 將一個 preset 分享給其他開發者。這個 repo 應該包含以下文件:

  • preset.json: 包含 preset 數據的主要文件(必需)。
  • generator.js: 一個可以注入或是修改項目中文件的 Generator
  • prompts.js 一個可以通過命令行對話爲 generator 收集選項的 prompts 文件

發佈 repo 後,你就可以在創建項目的時候通過 --preset 選項使用這個遠程的 preset 了:

# 從 GitHub repo 使用 preset
vue create --preset username/repo my-project

GitLab 和 BitBucket 也是支持的。如果要從私有 repo 獲取,請確保使用 --clone 選項:

vue create --preset gitlab:username/repo --clone my-project
vue create --preset bitbucket:username/repo --clone my-project

加載文件系統(本地)的 Preset :

當開發一個遠程 preset 的時候,你必須不厭其煩的向遠程 repo 發出 push 進行反覆測試。爲了簡化這個流程,你也可以直接在本地測試 preset。如果 --preset 選項的值是一個相對或絕對文件路徑,或是以 .json 結尾,則 Vue CLI 會加載本地的 preset:

# ./my-preset 應當是一個包含 preset.json 的文件夾
vue create --preset ./my-preset my-project

# 或者,直接使用當前工作目錄下的 json 文件:
vue create --preset my-preset.json my-project

4.如何編寫遠程/本地的Preset?

1.新建 vue-cli-plugin-vbpm 項目:

vue-cli-plugin-vbpm
.
|-- generator.js
|-- preset.json
|-- prompts.js
`-- template
    |-- base-web2
    |-- mob-web4
    |-- pc-web3
    `-- vue-web1

|-- preset.json Vue CLI preset 是一個包含創建新項目所需預定義選項和插件的 JSON 對象, 默認自動安裝裏面的插件,依賴,配置等。
|-- prompts.js 內建插件對話,進行安裝時提示用戶的操作流程
|-- generator.js 允許一個向 package.json 注入額外的依賴或字段,並向項目中添加 template 中的文件。
`-- template 模板文件,裏面的文件會直接被拷貝到項目中(其中有使用 ejs 模板引擎)

2.編寫 Preset,prompts 和 generator

1.preset.json 文件

一個 Vue CLI preset 是一個包含創建新項目所需預定義選項和插件的 JSON 對象,讓用戶無需在命令提示中選擇它們。當執行vue create默認會自動安裝裏面的插件,依賴,配置 和 vue項目的基本目錄等。

preset 的示例:

{
  "useConfigFiles": true,
  "plugins": {
    "@vue/cli-plugin-babel": {},
    "@vue/cli-plugin-eslint": {
      "config": "standard",
      "lintOn": [
        "save"
      ]
    },
    "@vue/cli-plugin-unit-mocha": {}
  },
  "router": true,
  "routerHistoryMode": true,
  "vuex": true,
  "cssPreprocessor": "node-sass"
}

plugins 是指在執行vue create新建項目的時候默認執行的vue-cli的哪些插件。

router 是指在執行vue create新建項目的時候默認是否集成router

Preset 的數據會被插件生成器(generator)用來生成相應的項目文件。例如:router:true 最終會被cli-plugin-router插件的生成器生成相應的Home.vue,About.vue,router/index.js等文件。

Preset 除了上述這些字段,你也可以爲集成工具添加配置:
例如:configs 配置

{
  "useConfigFiles": true,
  "plugins": {...},
  "configs": {
    "vue": {...},
    "postcss": {...},
    "eslintConfig": {...},
    "jest": {...}
  }
}

這些額外的配置將會根據 useConfigFiles 的值被合併到 package.json 或相應的配置文件中。例如,當 "useConfigFiles": true 的時候,configs 的值將會被合併到 vue.config.js 中。

2.prompts.js 文件

是一個內建對話配置文件,進行安裝時提示用戶的操作流程。

type 的類型有: list checkbox input confirm

// let chalk = require('chalk')
/**
 * 本質上是一個對話配置文件
 */
module.exports = [
  {
    type: 'list', // 即類型爲 選擇項
    name: 'project', // 名稱,作爲下面 generator.js導出 函數 options 的鍵
    message: '請選擇你要生成的項目類型', // 提示語
    choices: [
      { name: 'vue-web', value: 'vue-web' },
      { name: 'base-web', value: 'base-web' },
      { name: 'pc-web', value: 'pc-web' },
      { name: 'mo-web', value: 'mo-web' }
    ],
    default: 'vue-web',
  },
  {
    type: 'input', // 類型爲 輸入項
    name: 'projectName', // 名稱,作爲下面 generator.js導出 函數 options 的鍵
    message: '請輸入項目的名稱', // 提示語
    default: 'vue-web'
  },
  // {
  //   type: 'confirm',
  //   name: 'testConfirm',
  //   // 該項目唯一安裝的依賴 chalk; 目的是使用控制檯輸出 chalk.yellow('xxx') xxx 文字有顏色
  //   // ? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)
  //   message: `Use history mode for router? ${chalk.yellow(`(Requires proper server setup for index fallback in production)`)}`,
  //   description: `Using History API, the URLs don't need  '#' character.`
  // }
]

可通過安裝 npm install chalk ,使用 chalk.yellow( xxx )修改控制檯輸出字體的顏色

3.generator.js 文件

允許一個向 package.json 注入額外的依賴或字段,並向項目中添加 template中的文件。template下的文件默認拷貝到vue項目中,拷貝時如果文件的路徑和文件名相同則覆蓋,否則是疊加。template下的模板文件可以定義變量,底層使用ejs模板引擎進行渲染。

/**
 * api : 一個 GeneratorAPI 實例
 * options: 可以先簡單理解爲 prompts 問題數組的用戶輸入 組合成的選項對象
 * rootOptions: 整個 preset.json 對象
 */
module.exports = (api, options, rootOptions) => {
  // options.project 可以訪問上面問題數組的第一個對象的值,默認爲: 'vue-web'
  console.log(`Your choice is ${options.project}`)
  console.log(`Your input is ${options.projectName}`)

  // 1.判斷控制檯用戶的輸入
  if (options.project === 'vue-web') {  
    // render函數把該路徑下的 ./template/vue-web1 文件拷貝到默認的vue項目中。
    // 如果文件的路徑和文件名稱相同的則覆蓋,否則是疊加
    api.render('./template/vue-web1', { InputOptions:{ ...options} })
  }

  if (options.project === 'base-web') { 
    // 2.拷貝文件並傳遞變量。例如:InputOptions對象中的屬性/變量會覆蓋掉該./template/base-web2路勁下html,js,json等文件對應的屬性/變量
    api.render('./template/base-web2', { InputOptions:{ ...options} })
  }

  if (options.project === 'pc-web') { 
    // 3.如果該./template/pc-web3 路徑下的內容爲空,會使用vue-cli中提供的默認的模板 
    api.render('./template/pc-web3', { InputOptions:{ ...options} })
  }

  if (options.project === 'mob-web') { 
    // 4.如果該 render 沒有執行,會使用 vue-cli 中提供的默認的模板 
    // api.render('./template/mob-web4', { InputOptions:{ ...options} })
  }

  // 3.修改 `package.json` 裏的字段
  api.extendPackage({
    // 4.添加第三庫的依賴
    dependencies: {
      // 'normalize.css': '^8.0.1'
    },
    // 4.添加第三庫的依賴
    devDependencies: {
      // 'normalize.css': '^8.0.1'
    },
    // 5.添加自定義的腳本
    scripts: {
      // 'dev': 'vue-cli-service serve'
    },
    config: {
      
    }
  })
}

參考模板引擎的寫法

https://github.com/vuejs/vue-cli/blob/dev/packages/%40vue/cli-plugin-router/generator/template/src/App.vue

// 1.語法1: if else
<%_ if (InputOptions.project) { _%>
<script>
    // 2.語法2: 插值
console.log('<%= InputOptions.projectName %>')
    // 3.語法3: 插值
console.log('<%%= InputOptions.projectName %%>')
export default {
  name: 'App',
  components: {
    
  }
}
</script>
<%_ } else { _%>
<script>
  console.log('false')
</script>
<%_ } _%>

3.使用該 preset 新建vue項目

當開發一個遠程 preset 的時候,你必須不厭其煩的向遠程 repo 發出 push 進行反覆測試。爲了簡化這個流程,你也可以直接在本地測試 preset。如果 --preset 選項的值是一個相對或絕對文件路徑,或是以 .json 結尾,則 Vue CLI 會加載本地的 preset:

# ./vue-cli-plugin-vbpm 應當是一個包含 preset.json 的文件夾, my-vue-project是vue項目名稱
vue create --preset ./vue-cli-plugin-vbpm my-vue-project

發佈了106 篇原創文章 · 獲贊 93 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章