原文地址html
引用官方的一段話:vue
CLI 插件是一個能夠爲
@vue/cli
項目添加額外特性的 npm 包。它應該始終包含一個 Service 插件做爲其主要導出,且可選的包含一個 Generator 和一個 Prompt 文件。webpack
一般咱們須要將本身的一些配置/公用組件抽出來,以供各個項目使用,在其餘使用cli
建立的工程可使用vue add oview
的方式自動引入。git
一個典型的 CLI 插件的目錄結構看起來是這樣的:github
.
├── README.md
├── generator.js # generator (可選)
├── prompts.js # prompt 文件 (可選)
├── index.js # service 插件
└── package.json
複製代碼
若是你須要在插件安裝的同時,經過命令行來選擇是否建立一些示例組件,那麼目錄能夠改成:web
.
├── README.md
├── generator
|——-——template
│ └── index.js # generator
├── prompts.js # 命令行提示安裝
├── index.js # service 插件
└── package.json
複製代碼
一個發佈爲 npm 包的 CLI 插件能夠包含一個 generator.js
或 generator/index.js
文件。插件內的 generator 將會在兩種場景下被調用:vue-cli
在一個項目的初始化建立過程當中,若是 CLI 插件做爲項目建立 preset 的一部分被安裝。npm
插件在項目建立好以後經過 vue invoke
獨立調用時被安裝。json
package.json
注入額外的依賴或字段,並向項目中添加文件ejs
渲染 generator/template 下的文件。示例:api
module.exports = (api, options, rootOptions) => {
// 修改 `package.json` 裏的字段
api.extendPackage({
scripts: {
test: "vue-cli-service test"
}
});
// 複製並用 ejs 渲染 `./template` 內全部的文件
api.render("./template");
if (options.foo) {
// 有條件地生成文件
}
};
複製代碼
一個 generator/index 應該導出一個函數,這個函數接收三個參數:
一個 GeneratorAPI
實例:
這個插件的 generator 選項。使用prompts.js
建立對話的參數,或從一個保存在 ~/.vuerc
中的 preset 中加載。例如,若是保存好的 ~/.vuerc
像以下的這樣:
{
"presets": {
"foo": {
"plugins": {
"@vue/cli-plugin-foo": { "option": "bar" }
}
}
}
}
複製代碼
若是用戶使用 preset foo
建立了一個項目,那麼 @vue/cli-plugin-foo
的 generator 就會收到 { option: 'bar' }
做爲第二個參數。
對於一個第三方插件來講,該選項將會解析自對話或用戶執行 vue invoke
時的命令行參數中 (詳見第三方插件的對話)。
整個 preset (presets.foo
) 將會做爲第三個參數傳入。
全部 API 詳情請見這裏,此處列出經常使用的 API
入參
{function}
回調函數Usage: 當插件文件寫入磁盤後的回調函數,經常用來在安裝依賴完成以後,作自定義插件使用操做。例如 在 src/main.js 中寫入import oView from "oview";Vue.use(oView)
api.onCreateComplete(() => {
let oview = `\nimport oView from 'oview';\n\nVue.use(oView);`;
const fs = require("fs");
const mainPath = api.resolve("./src/main.js");
// 獲取內容
let contentMain = fs.readFileSync(mainPath, {
encoding: "utf-8"
});
if (contentMain.indexOf("oview") === -1) {
const lines = contentMain.split(/\r?\n/g).reverse();
// 注入import
const lastImportIndex = lines.findIndex(line => line.match(/^import/));
lines[lastImportIndex] += oview;
// 修改應用
contentMain = lines.reverse().join("\n");
fs.writeFileSync(mainPath, contentMain, {
encoding: "utf-8"
});
}
});
複製代碼
入參
{object | () => object}
使用說明: 在package.json
中新增依賴。 除非傳遞{merge:false}
,不然嵌套字段是深度合併的。 還解決了插件之間的依賴衝突。 在將文件寫入磁盤以前,能夠將工具配置字段提取到獨立文件中。
入參
{string | object | FileMiddleware}
- 能夠是一下三者中的某個
./template
;{sourceTemplate:targetFile}
映射的對象哈希;{object} [additionalData]
- 模板可用的其餘數據{object} [ejsOptions]
- ejs 額外參數Usage: 使用ejs
渲染文件到項目結構中
入參
{string} _path
- 相對於工程根目錄目錄返回值
{string}
- 文件絕對路徑使用說明: 獲取一個文件/文件夾的絕對路徑
判斷是否已經存在某個插件了。
入參
{string} id
- 插件 id, 能夠省略(@vue/|vue-|@scope/vue)-cli-plugin- 前綴{string} version
- 版本範圍, 可選值返回值
{boolean}
使用此插件的@vue/cli
版本
使用此插件的@vue/cli-service
版本。
vue-cli-service [name]
的命令{
description: string,
usage: string,
options: { [string]: string }
}
複製代碼
vue-cli-service serve 的例子
module.exports = (api, options) => {
api.registerCommand('serve', {
description: 'start development server',
usage: 'vue-cli-service serve [options] [entry]',
options: {
'--open': `open browser on server start`,
'--copy': `copy url to clipboard on server start`,
'--mode': `specify env mode (default: development)`,
'--host': `specify host (default: ${defaults.host})`,
'--port': `specify port (default: ${defaults.port})`,
'--https': `use https (default: ${defaults.https})`,
'--public': `specify the public network URL for the HMR client`,
'--skip-plugins': `comma-separated list of plugin names to skip for this run`
}
}, async function serve (args) {
}
複製代碼
什麼是 chainWebpack?請見這裏
//一個例子:修改默認的index.html文件
api.chainWebpack(function(config) {
config.plugin("html").tap(args => {
args[0].template = "/Users/username/proj/app/templates/index.html";
return args;
});
});
複製代碼
configureWebpack 修改 webpack 配置有兩種方式。vue 的 configureWebpack 介紹
Object
類型時,是合併配置到 webpack 中api.configureWebpack: {
plugins: [
new MyAwesomeWebpackPlugin()
]
}
複製代碼
function
類型時,是直接修改 webpack 配置api.configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
// 爲生產環境修改配置...
} else {
// 爲開發環境修改配置...
}
}
複製代碼
獲得修改以後的 webpack 配置,一般咱們在使用api.configureWebpack
或者api.chainWebpack
以後須要獲得修改以後的 webpack 值,那麼可使用
api.chainWebpack(webpackConfig => {
//.....
});
//獲得修改以後的webpack值
const webpackConfig = api.resolveWebpackConfig();
複製代碼
返回一個鏈式的 chainWebpack 配置,resolveWebpackConfig 是直接返回 webpack 的配置,可是 resolveChainableWebpackConfig 返回的一個 chainWebpack
當前使用的 cli @vue/cli-service
的版本。
當前工做目錄
@vue/|vue-|@scope/vue
前綴;建立新項目或向現有項目添加新插件時,須要提示來處理用戶的選擇。全部提示邏輯都存儲在 prompts.js 文件內.
vue 中的 prompt 是使用的Inquirer;
當用戶經過調用初始化插件時 vue invoke,若是插件prompts.js
的根目錄中包含,則會在調用期間使用它。該文件應導出將由 Inquirer.js 處理的一系列問題。
prompt.js 導出能夠有兩種方式:
prompt.js導出的結果將會成爲generator/index.js的第二個參數options
。
在介紹以上兩種以前,須要簡單的介紹一下Inquirer.js
的使用
一個問題其實就是一個對象:
{
type: "input|number|confirm|list|rawlist|expand|checkbox|password|editor".//默認值爲輸入:input
name: String,//此問題的id,在後面查找此問題的結果時能夠直接使用options.example取到此問題的值
message:String | Function,//要打印的問題。若是定義爲函數,則第一個參數將是當前查詢者會話答案。缺省值爲name(後跟冒號)
default:String | Number | Boolean | Array | Function,//若是未輸入任何內容,則使用默認值,或者返回默認值的函數。若是定義爲函數,則第一個參數將是當前查詢者會話答案,
choices:Array|Function,//(Array | Function)Choices數組或返回choices數組的函數。若是定義爲函數,則第一個參數將是當前查詢者會話答案。數組值能夠是simple numbers,strings或objects包含name(顯示在列表中),value(保存在上面講的name中和short(選擇後顯示)屬性
validate:Function,//校驗輸入的值是否符合要求
filter:Function,//接收用戶輸入並返回要在程序內部使用的過濾值,過濾的值將會返回到`Answers `中,詢問用戶是否正確
when:Boolean|Function,//接收當前用戶的答案哈希,並應返回true或false取決因而否應詢問此問題
pageSize:Number,//當使用list,rawList,expand,checkbox的時候可能存在分頁
prefix:String,//更改默認的前綴消息
suffix:String//更改默認的後綴消息
}
複製代碼
module.exports = [
{
type: "input",
name: "locale",
message: "The locale of project localization.",
validate: input => !!input,
default: "en"
}
// ...
];
複製代碼
// 入參爲package.json
module.exports = pkg => {
const prompts = [
{
type: "input",
name: "locale",
message: "The locale of project localization.",
validate: input => !!input,
default: "en"
}
];
// 動態添加問題
if ("@vue/cli-plugin-eslint" in (pkg.devDependencies || {})) {
prompts.push({
type: "confirm",
name: "useESLintPluginVueI18n",
message: "Use ESLint plugin for Vue I18n ?"
});
}
return prompts;
};
複製代碼
此實例作什麼?
npm init
# 而後輸入vue-cli-plugin-oview
複製代碼
新建 index.js
因爲不須要註冊命令那麼只須要編寫默認導出便可。
module.exports = (api, opts) => {};
複製代碼
編寫 generator 生成模板
文件目錄爲:
├─generator
│ ├─index.js
│ └─template
│ └─src
│ ├─components
│ │ └─Line.vue
│ └─mock
│ └─data.js
├─index.js
├─package.json
├─prompts.js
└─README.md
複製代碼
template 目錄中方的是示例模板,cli 會使用 ejs 進行渲染。
// prompts.js
module.exports = [
{
name: "example",
type: "confirm",
message: "是否添加示例組件到項目components目錄?",
default: false
}
];
複製代碼
// generator/index.js
module.exports = (api, options, rootOptions) => {
//在package.json中新增依賴
api.extendPackage({
dependencies: {
oview: "^1.1.2"
}
});
// 當文件寫入磁盤時,讀取main.js並在main.js中寫入import oView from "oview"; Vue.use(oView)
api.onCreateComplete(() => {
let oview = `\nimport oView from 'oview';\n\nVue.use(oView);`;
const fs = require("fs");
const mainPath = api.resolve("./src/main.js");
// 獲取內容
let contentMain = fs.readFileSync(mainPath, {
encoding: "utf-8"
});
if (contentMain.indexOf("oview") === -1) {
const lines = contentMain.split(/\r?\n/g).reverse();
// 注入import
const lastImportIndex = lines.findIndex(line => line.match(/^import/));
lines[lastImportIndex] += oview;
// 修改應用
contentMain = lines.reverse().join("\n");
fs.writeFileSync(mainPath, contentMain, {
encoding: "utf-8"
});
}
});
//prompt.js傳遞的參數
if (options.example) {
//渲染template下的模板
api.render("./template", {
...options
});
}
};
複製代碼
vue create demo
# 如下路徑換成本身的
npm install --save-dev C:\Users\mrgao\Desktop\demo\vue-cli-plugin-oview
# 上面步驟完成,你能夠在package.json中查看到此依賴
vue invoke vue-cli-plugin-oview
# 如今你能夠看到一個命令,提示你是否添加文件,若是一切OK,那麼就能夠在package.json中發現oview的依賴,而且main.js中有oview
複製代碼
1、設置倉庫地址爲npm官方倉庫地址(國內大部分都使用阿里淘寶鏡像,若是沒改publish會失敗)
npm config set registry https://registry.npmjs.org/
2、登錄npm,用戶名密碼郵箱須要所有匹配
npm login
Username: 你的npm用戶名
Password:
Email: (this IS public) 你的郵箱
3、登錄完能夠publish了,執行如下命令
npm publish
輸出如下信息說明發布成功
+ ngx-xxx@0.0.1
這時登陸https://www.npmjs.com/能夠看到本身發佈的項目
複製代碼
給個讚唄!原文地址
若是以爲此文對您有用歡迎來個Star: mrgaogang.github.io