仿ElementUI構建本身的Vue組件庫用babel-plugin-component按需加載組件及自定義SASS主題

最近使用ElementUI作項目的時候用Babel的插件babel-plugin-component作按需加載,使得組件打包的JS和CSS包體積大大縮小,加載速度也大大提高,全部想模仿作一個組件庫也來作下按需加載。css

首先用Vue CLI 3.0新建一個項目

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

相關文章
相關標籤/搜索