vue-cli3插件初體驗

vue-cli3發布自2018年8月,距離現在還不是特別久,最好搭建項目剛好用到,所以寫下這篇文章,記錄一下踩坑經歷。

vue的作者說過,vue-cli的本質是模

版的拉取,太多的配置導致了模版的難以維護,所以重構后的版本提供了插件的功能,一個插件對應一個功能,這樣避免了多個模版,也使得cli維護性得到提高,這也是本篇文章的核心介紹內容。

我對cli3的理解是,一方面擴展了cli2的核心能力 ,一方面封裝了webpack邏輯和配置。在過去要去做一個cli,通常需要閱讀cli2的代碼,cli2的核心模塊分別是 generator,prompts,template,git-repo,并用同樣的方法去做一個cli,這樣其實成本不小,cli3的插件就是提供了這樣一種能力,你用他的規則,去做一個npm包,并發到倉庫,就可以獲得這種能力。

首先,先介紹一下vue-cli3,他的發布帶了哪些新功能呢?我總結一下,大概有以下5點:

1.功能豐富。這點相信大家都很好理解,他實在太好用了,模版里包含了大多數業界比較新的功能,可以一鍵集成typescripts等類型定義工具, eslint/tslint等語法檢驗工具,風格規范,prettier,husky等格式化工具,還有postcss、pwa、vue-cli-server等等。

2.提高封裝性和擴展性。這點指的是vue-cli-server,在過去webpack的邏輯和配置在項目里獨立維護,各個項目之間就像孤島,vue-cli-server就像一個紐帶,連接起了各個項目,為項目升級webpack提供便利性,并且通過一份配置,提供個性化配置。

這里順帶扯一下vue.config.js, 這個東西就是用來個性化配置webpack的,他提供了很多的配置項,具體可以看官方文檔:

https://cli.vuejs.org/zh/config/

我們挑幾個常用的來講:

configureWebpack,這個幾乎是用的比較多的,簡單的方法,可以通過配置的方式配置,如下所示:

module.exports = {configureWebpack: {plugins: [new MyAwesomeWebpackPlugin()]}
}復制代碼


這份配置,最終會被合并到原來的配置里,不會覆蓋。

復雜的方法,可以往這個字段傳一個函數,如下所示:

module.exports = {configureWebpack: config => {if (process.env.NODE_ENV === 'production') {// 為生產環境修改配置...} else {// 為開發環境修改配置...}}
}復制代碼

這樣就可以在一個函數里做一些簡單的邏輯,config是webpack config,你可以直接修改config對象,也可以返回一個對象,這個對象最終也會被合并會webpack對象。

第三種方式,是通過webpack-chain來鏈式調用,代碼如下所示:

module.exports = {chainWebpack: config => {config.module.rule('vue').use('vue-loader').loader('vue-loader').tap(options => {// 修改它的選項...return options})}
}復制代碼

3.提供圖形化管理界面,最所周知,gui易懂,cli高效,vue在降低學習門檻這方面,已經是非常好了。

通過vue ui指令,可以查看編譯各個模塊的情況,模塊依賴情況,插件的情況,非常便于管理。

4.便捷性。vue-cli-server不僅支持項目的編譯,也支持單文件的編譯,具體的方法可以看官網介紹。

5.提供了cli的核心能力,也就是問詢,模版渲染,文件生成這幾大核心功能。具體的示意圖可以看如下:


以上是cli2的核心模塊,需要引用hbs,inquirer.js,metalsmit等基本模塊,cli3的插件機制基本幫我們封裝好了,我們只需要根據插件的規范,就可以獲取這種能力。

由于有的讀者可能對cli2的流程比較陌生,所以我想簡單描述一下cli2的工作流程,如下圖所示:


首先,cli2提供init指令,執行這個指令,會去遠程拿模版文件,并拉到本地用戶目錄的.vue-template的文件夾,然后通過meta里問題,去問你,然后生成最終模版到你執行命令的目錄。

說完vue-cli2,我們來看看vue-cli3的插件是怎么樣的?

首先根據插件的位置,我們分成了cli插件,和service插件。cli的插件有完整的開發目錄,所能做的事情也比較多一點,service插件是一份js文件,導出一個函數。

cli插件的目錄如下所示:


具體的用發可以在官網了解到:

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

那么他們是怎么工作的呢?

cli的代碼主要在@vue/cli 下面,他的大概的流程如下圖所示:


@vue/cli/bin/vue.js:

program.command('add <plugin> [pluginOptions]').description('install a plugin and invoke its generator in an already created project').option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)').allowUnknownOption().action((plugin) => {require('../lib/add')(plugin, minimist(process.argv.slice(3)))})program.command('invoke <plugin> [pluginOptions]').description('invoke the generator of a plugin in an already created project').option('--registry <url>', 'Use specified npm registry when installing dependencies (only for npm)').allowUnknownOption().action((plugin) => {require('../lib/invoke')(plugin, minimist(process.argv.slice(3)))})復制代碼

首先,執行vue指令,會執行@vue/cli/bin/vue.js,這里定義了vue add , vue invoke,vue build,vue serve,等指令,可以看出,add指令其實是包含invoke指令的,add指令主要是安裝一個包,并且觸發generator.js,invoke主要是觸發generator.js。

然后再來看@vue/cli/lib/add.js,

  const packageManager = loadOptions().packageManager || (hasProjectYarn(context) ? 'yarn' : 'npm')await installPackage(context, packageManager, options.registry, packageName)復制代碼

  const generatorPath = resolveModule(`${packageName}/generator`, context)if (generatorPath) {invoke(pluginName, options, context)} else {log(`Plugin ${packageName} does not have a generator to invoke`)}復制代碼

add.js主要安裝包,然后執行invoke模塊,我們再看看invoke模塊做了什么。

@vue/cli/lib/invoke.js

  const generator = new Generator(context, {pkg,plugins: [plugin],files: await readFiles(context),completeCbs: createCompleteCbs,invoking: true})復制代碼

invoke里主要實例化generator類,然后把你的插件當成參數傳給類,generator類算是vue-cli的核心類了。

@vue/cli/lib/generator.js

  plugins.forEach(({ id, apply, options }) => {const api = new GeneratorAPI(id, this, options, rootOptions)apply(api, options, rootOptions, invoking)})復制代碼

這個類主要負責執行你的插件,然后把generatorapi作為參數傳入插件的generator.js導出的函數。

具體的vue-cli插件的開發是怎么樣的呢,我寫了一個demo,用在模擬多項目的ci模版管理,通常每個項目都有一份.gitlab-ci.yml模版,所以我們一般可以抽出一個公共的ci模版來管理,這里我用cli插件來管理,真正的項目可能不具備可行性,這里我只是用來寫一個例子。



目錄結構大概如上所示,執行vue add foo后,就會出現propmts對話框,然后選擇答案后,就會根據配置生成模版到你的根目錄下。


_gitlab-ci.yml ,根據問題選擇是否用私有npm倉庫:

 script:<%_ if (options.config === 'npm') { _%>- nrm add companynpm http://xxx.y.cn:XXXXX/- nrm use companynpm<%_ } _%>復制代碼

prompts.js,主要一些問題的設計:

module.exports = [{name: 'config',type: 'list',message: `是否需要切換內部源:`,choices: [{name: '需要',value: 'npm',short: ''},{name: '不需要',value: 'npm',short: ''}]}
]復制代碼

generator.js 這個模塊很簡單,直接渲染模版

module.exports = (api, options, rootOptions) => {// 復制并用 ejs 渲染 `./template` 內所有的文件api.render('./template')
}復制代碼

service插件主要放在項目本地,是一份js代碼,然后導出一個函數,通過package.json配置指向這個js文件的路徑,


service主要依賴的代碼在@vue/cli-service里,首先先執行@vue/cli-service/bin/vue-cli-service.js文件,


const Service = require('../lib/Service')
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd()).....service.run(command, args, rawArgv).catch(err => {error(err)process.exit(1)
})復制代碼

該文件實例化Service類,這個類是service插件的核心類,然后再執行run方法。

再來看看@vue/cli-service/lib/Service.js的代碼:

首先構造函數執行resolvePlugin,把官方提供的插件和項目里的插件都加載進來,

constructor (context, { plugins, pkg, inlineOptions, useBuiltIn } = {}) {this.plugins = this.resolvePlugins(plugins, useBuiltIn)
}復制代碼

resolvePlugin這個函數主要在這里引入本地的插件:

resolvePlugins (inlinePlugins, useBuiltIn) {// Local pluginsif (this.pkg.vuePlugins && this.pkg.vuePlugins.service) {const files = this.pkg.vuePlugins.serviceif (!Array.isArray(files)) {throw new Error(`Invalid type for option 'vuePlugins.service', expected 'array' but got ${typeof files}.`)}plugins = plugins.concat(files.map(file => ({id: `local:${file}`,apply: loadModule(file, this.pkgContext)})))}return plugins
}復制代碼

run方法又會執行init方法,在該方法內部執行插件:

init (mode = process.env.VUE_CLI_MODE) {// apply plugins.this.plugins.forEach(({ id, apply }) => {apply(new PluginAPI(id, this), this.projectOptions)}
}復制代碼


那么service插件要如何來實踐,我們來看如下的例子:

首先在package.json配置一下,指向本地的插件my-service.js

  "vuePlugins": {"service": ["my-service.js"]}復制代碼

my-service.js的代碼如下所示:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const webpack = require('webpack');module.exports = (api, projectOptions) => {api.registerCommand('analyze',{description: 'start analyze server',},(args) => {// 注冊 `vue-cli-service analyze`let options = projectOptions.pluginOptions.demoOptionsconsole.log(options);// resolve webpack configconst webpackConfig = api.resolveWebpackConfig();webpackConfig.plugins.push(new BundleAnalyzerPlugin());webpack(webpackConfig,(err,stats)=>{if(!err) console.log('打包成功')})},);
};復制代碼

該插件主要擴展vue-cli-service的指令,加了analyze指令,這個指令主要會向webpack的配置增加一個BundleAnalyzerPlugin的插件,用來分析包的大小,當然,這里也是沒有太大的現實可行性的,vue-cli 提供了vue ui的Gui界面讓你看到打包后各個模塊的大小,或者cli的命令,vue-cli-service build --report,也能生一個報告,效果也是一樣。


至此,vue-cli和service插件的使用和實現都介紹完了,如果有哪里寫的不到位,希望各位大神能提出指正。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276043.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276043.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276043.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ios設計登錄功能_親愛的產品設計師,這是iOS 14的新功能

ios設計登錄功能On June 22, 2020 Apple previewed iOS 14 for the first time. As always there are quite some changes you should know about as a product designer like widgets, pickers, app clips, permissions and more.2020年6月22日&#xff0c;Apple首次預覽iOS 1…

c++ int 轉 short_C/C++結構體內存對齊

在面試或工作中&#xff0c;經常會遇到內存對齊的問題。這里結合我的理解談一談對內存對齊的理解。1. 為什么要內存對齊&#xff0c;不對齊會怎么樣&#xff1f;內存中存放數據是為了給CPU使用&#xff0c;CPU訪問內存數據時會受到地址總線寬度的限制&#xff0c;也就是一次能從…

對于日訪問量達到1W IP的處理方法

轉自&#xff1a;http://www.java123.net/56026-2.html 對于日訪問量達到1W IP的處理方法 一、1萬ip真是不高&#xff1a; 1.常用數據用緩存&#xff0c;減輕數據庫壓力。 2.詳細頁數據生成靜態頁面。 二、10000算是相當小的了,不需要什么特殊的處理機制,只要符合最一般的…

數據契約(DataContract)

WCF第一要素就是契約: 服務契約用于聲明可用于遠程訪問的類型。在Interface或class開始處使用服務契約標簽. [ServiceContract] Public interface Iservice { } 接口調用契約的好處: 1. 同一服務類型可以實現多個不相干的服務契約. 2. 有利于版本升級 3. 按照…

jakob slam_Jakob Nielsen針對用戶界面設計的第二種可用性啟發法

jakob slamIn the pursuit of providing great user experiences, it’s imperative that digital products are evaluated. A 為了提供出色的用戶體驗&#xff0c;必須對數字產品進行評估。 一個 heuristic evaluation is essential to delivering great user experiences. I…

微軟Office 365正式上架Mac App Store

今天&#xff0c;Office 365正式在Mac App Store上架&#xff0c;Mac用戶可以輕松下載Word&#xff0c;Outlook&#xff0c;Excel&#xff0c;PowerPoint&#xff0c;OneNote以及整套微軟的熱門應用程序。用戶還可以從應用程序內訂購Office 365。蘋果全球開發者關系高級主管Sha…

一文搞懂瀏覽器原理

大家好&#xff0c;我是若川。最近這幾年&#xff0c;云計算的普及和 HTML5 技術的快速發展&#xff0c;越來越多的應用轉向了瀏覽器 / 服務器&#xff08;B/S&#xff09;架構&#xff0c;這種改變讓瀏覽器的重要性與日俱增&#xff0c;視頻、音頻、游戲幾大核心場景也都在逐漸…

python處理excel可視化_python如何將excel數據處理可視化

python將excel數據處理可視化的方法&#xff1a;首先安裝xlrd與xlwt庫&#xff0c;進行表格讀取&#xff1b;然后使用pyecharts生成Echarts圖表的類庫&#xff1b;最后安裝Echarts讀取Excel數據及顯示即可。python將excel數據處理可視化的方法&#xff1a;Excel表操作python操作…

dataframe中將一列數據切分成多列

為什么80%的碼農都做不了架構師&#xff1f;>>> 原sheet中數據 目的 將【備注】列切分成【key】列和【value】列 Python sheet[key] sheet[備注].str.extract(r(_.*(?\u503c))) sheet[value] sheet[備注].str.extract(r((?<).*))結果 參考 pandas.Series.st…

matplotlib可視化_EDA:Geopandas,Matplotlib和Bokeh中的可視化

matplotlib可視化Nowadays, everyone is immersed with plenty of data from news sources, cellphones, laptops, workplaces, and so on. Data conveys with tons of information from different data variables like date, string, numeric, and geographical format. How t…

(轉)結婚那天,媽問我:坐在角落里象兩個要飯模樣的人是誰?

人人看到的文章 很感人~~~~結婚那天&#xff0c;媽問我&#xff1a;坐在角落里象兩個要飯模樣的人是誰&#xff1f; 我看過去的時候&#xff0c;有個老頭正盯著我&#xff0c;旁邊還有個老太太&#xff0c;發現我看著他們時趕忙低下頭。我不認識他們但也不象要飯的&#xff0c;…

nginx-1.13.x源碼安裝

Nginx 安裝配置【依賴庫】[ zlib ]&#xff08;下載&#xff09;http://download.chinaunix.net/download.php?id24013&ResourceID12241 [ pcre ]apt-get install libpcre-dev[ openssl ]&#xff08;下載&#xff09;http://download.chinaunix.net/download.php?id3937…

小技巧!CSS 整塊文本溢出省略特性探究

大家好&#xff0c;我是若川。歡迎加我微信 ruochuan12&#xff0c;長期交流學習。今天的文章很有意思&#xff0c;講一講整塊文本溢出省略打點的一些有意思的細節。點擊下方卡片關注我&#xff0c;或者查看源碼系列文章。文本超長打點我們都知道&#xff0c;到今天&#xff08…

linux配置ip地址 suse_SUSE Linux下設置IP的兩種方法

第一種SUSE Linux IP設置方法ifconfig eth0 192.168.1.22 netmask 255.255.255.0 uproute add default gw 192.168.1.2釋義&#xff1a;#IP配置&#xff0c;包括子網掩碼,看情況修改eth0和192.168.1.22#網關修改 ,看情況修改192.168.1.2第二種SUSE Linux IP設置方法在suse操作系…

寒假作業3:抓老鼠啊

7-1 抓老鼠啊~虧了還是賺了&#xff1f; &#xff08;20 分&#xff09; 某地老鼠成災&#xff0c;現懸賞抓老鼠&#xff0c;每抓到一只獎勵10元&#xff0c;于是開始跟老鼠斗智斗勇&#xff1a;每天在墻角可選擇以下三個操作&#xff1a;放置一個帶有一塊奶酪的捕鼠夾(T)&…

筆記本移交_創建完美的設計移交

筆記本移交重點 (Top highlight)Design specifications (specs) are guidelines that developers will use to implement a design. Think of an architect providing building blueprints to the construction team. Many designers think of specs as mindless zombie work. …

大手筆,送¥1599的Apple AirPods Pro和獨家禮物等

大家好&#xff0c;我是若川。為感謝公眾號讀者們長久以來的支持&#xff0c;本次我聯合幾位前端界大佬給大家送超級福利了。除了聯合福利之外&#xff0c;每位前端大佬還帶了專屬禮品送給大家&#xff0c;所有抽獎均可重復參與、可重復中獎&#xff0c;詳情見下文每個公眾號的…

jQuery1.4新特性

1. 傳參給 jQuery(…) 之前&#xff0c;jQuery可以通過 attr 方法設置元素的屬性&#xff0c;既可傳屬性的名和值&#xff0c;也可以是包含幾組特定 屬性名值對 的 對象。在 jQuery 1.4 中&#xff0c;你可以把一個參數對象作為第二個參數傳給 jQuery 函數本身&#xff0c;同時…

python pack unpack_golang 仿python pack/unpack

package includesimport ("bytes""encoding/binary""fmt"_"os""strconv""strings")type Protocolstruct{Format []string}//封包func (p *Protocol) Pack(args ...interface{}) []byte{la :len(args)ls :len(p.Fo…

JavaScript遞歸應用與實踐

遞歸簡單來說就是函數內調用自生的一種方法&#xff0c;形如&#xff1a; function foo(){foo() } 復制代碼下面我列舉一些常用的遞歸應用。 1. 求和&#xff0c;例如求1234...100之和 分析如下&#xff1a; sum(100)sum(99)100 sum(99)sum(98)99 ... sum(1)sum(0)1 復制代碼代…