使用babel-plugin-component實現按需引入、打包。
將webpack配置成多入口,保證最終打包的目錄結構符合babel-plugin-component插件的要求,實現按需加載
一、build目錄中是cooking配置文件,cooking是餓了麼前端研發的基於webpack的前端構建工具,咱們使用原始的webpack實現。此處源碼忽略。javascript
二、example中是element項目的例子存放,打開element網頁,可看見的項目入口。css
三、packages目錄中,是全部的功能模塊,以alert模塊爲例,分析目錄結構html
alert模塊目錄,有一個index.js做爲模塊入口,在入口處,引入src目錄中的主要組件,再對該組件進行拓展,增長install方法,咱們知道,在對vue進行擴展,使用vue.use(...)時,vue內部會調用插件的install方法,此處給alert組件增長install方法,則最終打包完成後,按需引入alert功能組件時,可使用vue.use(alert)進行註冊組件到全局。
其餘功能模塊的目錄結構也大同小異,在入口處對組件進行install擴展。前端
四、src目錄中存放一些公共的mixin等工具和一個index.js入口文件,這個入口文件是打包後兼具全部功能組件的入口,上源碼,一個一個分析:vue
首先將packages中的各個功能模塊引入java
定義一個install方法,在此方法中,將全部的功能模塊進行註冊。node
components.map(component => { Vue.component(component.name, component); });
遍歷註冊webpack
Vue.prototype.$loading = Loading.service; Vue.prototype.$msgbox = MessageBox; Vue.prototype.$alert = MessageBox.alert; Vue.prototype.$confirm = MessageBox.confirm; Vue.prototype.$prompt = MessageBox.prompt; Vue.prototype.$notify = Notification; Vue.prototype.$message = Message; Vue.prototype.$ELEMENT = ELEMENT;
對vue原型進行擴展,使vue實例中可直接使用this.$alert等便捷方法。git
最後,將全部功能模塊和install方法一塊兒導出。這樣當引入element-ui時,即可以使用vue.use(element-ui)進行註冊,即將全部的功能組件進行全局註冊。github
五、lib目錄是按babel-plugin-component插件要求打包後存放最終代碼的目錄。
詳細看看這個目錄中的結構
目錄中,將各個功能模塊打包成了一個.js文件,在theme-chalk中,存放這名稱和功能模塊相同的.css文件。爲什麼要這樣打包??這就進入了咱們的重點,看看babel-plugin-component插件的文檔:
import { Button } from 'antd'
會被解析成同時引入antd/lib/button/index.js
和引入lib/button/style.css
這就是這個插件爲咱們帶來的按需引入的功能。插件會去解析你的代碼,當你引入的是配置的modules中的某一部分時,自動爲你解析,只爲你的項目引入你指定的部分。
這個插件有幾種目錄結構的配置方案,剛剛解釋的只是其中一種,咱們來看element-ui採用的也是咱們要使用的一種:
在lib下,存在幾個模塊componentA、componentB,當引入import {componentA} from '...'時,會被解析成從lib/componentA,此時,這個componentA如果目錄,則進入目錄找目錄入口,也就是index.js,若componentA是個.js文件,則直接引入這個文件。
樣式文件會經過你的bablerc配置,從lib中指定的目錄中去引入同名文件
看看bablerc中的相關配置:
在plugins中,增長component配置,component相關option配置:
看看element官網說明的配置:
配置了libraryName和styleLibraryName。
好,到此element的分析及babel-plugin-componentbable插件的說明暫時告一段落。
我們繼續看咱們如何去實現。
項目是用vue-cli搭建的項目:
一、build中是webpack相關配置
二、example目錄是開發時調試用
三、src目錄中components中是各個功能模塊,各功能模塊的入口中同element同樣,對組件進行擴展,增長install方法,將組件進行全局註冊,index.js是入口,其中引入全部功能模塊,同時導出模塊和install方法,將全部模塊進行註冊。
四、lib中是最終打包的目標目錄
五、增長components.json文件
記錄將要打包的功能模塊名稱和路徑
規劃中,須要將各個模塊打包至lib,一個功能模塊爲一個.js文件,而且在theme目錄中存在一個同名的.css文件,這樣使用時藉助babel-plugin-component插件就可實現按需引入。還須要一個總的index.js包含全部的功能模塊,和一個index.css包含全部的樣式。
這裏採用多入口(entry)配置,實現各個功能模塊分別打包成一個.js文件,並使用extract-text-webpack-plugin將樣式進行抽離後,按入口chunk進行打包爲對應的.css文件。
當將須要打包至一塊兒是,使用單個入口,抽離全部css到一個css文件。
因此完成打包目標須要執行兩個打包命令,看package.json相關配置:
"scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "build": "node build/build.js", "build_all": "node build/build.js all" }
npm run build
進行將各個模塊打包爲各自的.js文件,樣式文件也同時抽離處理爲同名的.css,npm run build_all
將全部的功能打包爲index.js和index.css
上webpack詳細配置更改代碼:
首先在config中將assetsRoot,output的路徑設置爲lib
在build.js中,獲取命令行參數,根據參數判斷須要進行的打包任務,下面詳細介紹webpack.prod.conf和webpack.prodAll.conf文件
一、刪除HtmlWebpackPlugin相關配置,這裏只需打包爲js文件和css文件,不涉及html
二、引入components.json,根據配置的模塊及路徑配置入口entrys,配置完後,將入口寫入entry配置
三、ExtractTextPlugin插件是進行css抽離的,這裏不用處理
四、ouput中,出口.js文件的名稱不能寫死
五、在plugins插件配置處,ExtractTextPlugin相關配置,filename不能寫死,須要根據chunk名稱自動生成對應名稱。這裏設置爲'/theme/[name].css'
指定目錄lib/theme存放
一、一樣刪除html相關配置
注意入口配置,設置爲src/index.js這個文件中引入了全部的功能模塊。
output和抽離css的配置中的filename寫死成index也可,寫成[name]按chunk名也可,由於入口只有一個。只要在entry指定入口名爲index。
到此,webpack配置就差很少完成了。最後上一個打包完成後的目錄結構:
這樣,在使用時,只須要引入babel-plugin-component插件,並進行配置,配置中,指定libraryName爲庫名,指定styleLibraryName爲theme便可。
這個相關配置已經發布了npm包。其中只有兩個功能組件,一個upload,一個input。
有讀者想要試按需引入功能的能夠按以下配置:
一、bable配置:
二、引入時:
本文完成啦,但願能對你有所幫助~~學無止境,你們共勉
一、相關代碼已經發布至github,地址: https://github.com/yuanalina/installAsRequired 二、打包時須要注意名稱命名須要使用kebab-case (短橫線分隔命名)格式,例如:button-model,在components.json配置中,須要使用短橫線分隔命名; 三、在後續的配置中我進行了優化,把總體打包和各組件分離打包整合到了一塊兒,更改的地方爲:在components.json中增長"index": "./src/index.js"便可。詳見github