最近使用ElementUI作項目的時候用Babel的插件babel-plugin-component作按需加載,使得組件打包的JS和CSS包體積大大縮小,加載速度也大大提高,全部想模仿作一個組件庫也來作下按需加載。css
vue create bes-ui
注意的是cli3的腳手架用的Babel7的配置,只有babel.config.js文件,因此要本身添加.babelrc文件。vue
新建項目以後,能夠按照本身的想法建文件結構,也能夠按照babel-plugin-component官方文檔的目錄構建:
上面有兩種方式,前一種是組件單一主題方式,後一種是主題庫的方式,你們能夠本身選擇,下圖是bes-ui的目錄結構:
這裏大概介紹下文件用途:
-dist:組件庫測試項目打包文件
-examples:組件庫的測試項目
-lib:組件庫的源碼
-local:組件庫的國際化文件
-package:組件庫打包後的壓縮的js,css文件
-static:組件庫的靜態資源(css主題)
其餘文件就不介紹了,都是腳手架生成的文件node
這裏組件庫寫了兩個樣例:component1,component2 。 每一個組件都添加了本身的初始化install方法(用於按需加載時候獨立使用),install方面裏面加個日誌,方便後面看看組件加載記錄。
最外面添加總體加載用的index.js,用於一次性加載全部項目
最後就是組件的樣式文件了(這裏的base.css和index.css都是必須的,官方的api有有標註):
你們注意的一點是組件包名必定要叫 「 lib 」 ,樣式文件的路徑和名字你們能夠隨意,到時候在配置文件裏面引用對應的路徑就行,我這裏叫static,裏面必定要加 base.css和index.css,這都是babel-plugin-component的API裏面標註了,固然你們也能夠看babel-plugin-component的源碼core.js【位置在node_modules/babel-plugin-component/lib/core.js】裏面有涉及到獲取對應文件:git
if (styleLibrary && _typeof(styleLibrary) === 'object') {//這個是樣式的一些配置 styleLibraryName = styleLibrary.name; isBaseStyle = styleLibrary.base; modulePathTpl = styleLibrary.path; mixin = styleLibrary.mixin; styleRoot = styleLibrary.root; } if (styleLibraryName) {//是否在.babelrc配置了styleLibraryName if (!cachePath[libraryName]) {//是否存在配置好的樣式獲取路徑 var themeName = styleLibraryName.replace(/^~/, ''); cachePath[libraryName] = styleLibraryName.indexOf('~') === 0 ?//路徑是否相對於element-ui/lib resolve(process.cwd(), themeName) : "".concat(libraryName, "/").concat(libDir, "/").concat(themeName); }//若是是相對於lib 組合路徑---element-ui/lib/theme-chalk/ 這個目錄下是75個css文件 //這裏將這一段路徑保存在了cachePath[libraryName] 後續會用到 if (libraryObjs[methodName]) {//做者也沒搞清楚這裏是什麼 不過不要緊,事實證實這裏走了false /* istanbul ingore next */ if (cache[libraryName] === 2) { throw Error('[babel-plugin-component] If you are using both' + 'on-demand and importing all, make sure to invoke the' + ' importing all first.'); } if (styleRoot) {//這裏默認是沒有配置的 全部走false path = "".concat(cachePath[libraryName]).concat(styleRoot).concat(ext); } else { path = "".concat(cachePath[libraryName]).concat(_root || '/index').concat(ext); }//這裏會默認先加載index.css 由於ext沒設置就會默認css cache[libraryName] = 1; } else {//走了else if (cache[libraryName] !== 1) {//這裏確定是不等於1,由於上面一行纔會賦值1 /* if set styleLibrary.path(format: [module]/module.css) */ var parsedMethodName = parseName(methodName, camel2Dash); if (modulePathTpl) { var modulePath = modulePathTpl.replace(/\[module]/ig, parsedMethodName); path = "".concat(cachePath[libraryName], "/").concat(modulePath); } else {//這裏走了else 也就是樣式路徑後續爲模塊名.[ext] path = "".concat(cachePath[libraryName], "/").concat(parsedMethodName).concat(ext); }//全部這裏的路徑就是element-ui/lib/ if (mixin && !isExist(path)) { path = style === true ? "".concat(_path, "/style").concat(ext) : "".concat(_path, "/").concat(style); } if (isBaseStyle) { addSideEffect(file.path, "".concat(cachePath[libraryName], "/base").concat(ext)); } cache[libraryName] = 2; } } addDefault(file.path, path, { nameHint: methodName }); } else { if (style === true) { addSideEffect(file.path, "".concat(path, "/style").concat(ext)); } else if (style) { addSideEffect(file.path, "".concat(path, "/").concat(style)); } } }
轉回正題,文件建立好了以後,就能夠發包到npm了,這裏提供了兩種方式:1是將組件庫打包壓縮成css和js,暴露出去(這種方式沒法作按需,由於因此代碼壓縮在一塊兒了);2是將lib下的index暴露出去(這種方式能夠作按需加載);以下(package文件):
github
組件放上去後,就能夠在項目裏面使用了,這裏用vue create添加了一個example項目:
項目加載bes-ui:
項目使用bes-ui(這裏只加載了component2):
啓動項目後,觀察加載的項目日誌:
這裏日誌打印的只加載了component2,若是還不放心的話能夠看下style標籤是否是隻有component2的css:
這裏確實只有component2的樣式,這裏有個問題就是樣式加載了兩遍 這裏主要是組件內部加載了一次樣式,babel-plugin-component的按需又加載了一次,這裏主要是爲了測試兩種不一樣方式,(組件內的加載樣式是給壓縮js和css用的)若是作按需的話就能夠去掉了:
這裏貼下Babel的配置:
vue-cli
最後能夠打個測試項目包,看下里面確實沒有其餘組件的代碼和樣式,這裏就不貼圖了,你們能夠本身嘗試,總結下這裏的bes-ui其實就是模仿ElementUI的一個簡易的組件庫(雖然目前只加了按需加載,後續能夠把國際化和主題加上),項目裏面的一些配置和文件都大同小異,若是有興趣構建本身的vue組件庫的時候,bes-ui是個不錯的模版。npm
GitHub項目地址:https://github.com/BothEyes1993/bes-uielement-ui