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


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

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

vue create bes-ui

注意的是cli3的腳手架用的Babel7的配置,只有babel.config.js文件,所以要自己添加.babelrc文件。

項目結構

新建項目之后,可以按照自己的想法建文件結構,也可以按照babel-plugin-component官方文檔的目錄構建:
在這里插入圖片描述
上面有兩種方式,前一種是組件單一主題方式,后一種是主題庫的方式,大家可以自己選擇,下圖是bes-ui的目錄結構:
在這里插入圖片描述
這里大概介紹下文件用途:
-dist:組件庫測試項目打包文件
-examples:組件庫的測試項目
-lib:組件庫的源碼
-local:組件庫的國際化文件
-package:組件庫打包后的壓縮的js,css文件
-static:組件庫的靜態資源(css主題)
其他文件就不介紹了,都是腳手架生成的文件

組件介紹

這里組件庫寫了兩個樣例: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】里面有涉及到獲取對應文件:

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文件):
在這里插入圖片描述

組件使用

組件放上去后,就可以在項目里面使用了,這里用vue create添加了一個example項目:
在這里插入圖片描述
項目加載bes-ui:
在這里插入圖片描述
項目使用bes-ui(這里只加載了component2):
在這里插入圖片描述
啟動項目后,觀察加載的項目日志:
在這里插入圖片描述
這里日志打印的只加載了component2,如果還不放心的話可以看下style標簽是不是只有component2的css:
在這里插入圖片描述
這里確實只有component2的樣式,這里有個問題就是樣式加載了兩遍 這里主要是組件內部加載了一次樣式,babel-plugin-component的按需又加載了一次,這里主要是為了測試兩種不同方式,(組件內的加載樣式是給壓縮js和css用的)如果做按需的話就可以去掉了:
在這里插入圖片描述
這里貼下Babel的配置:
在這里插入圖片描述

總結

最后可以打個測試項目包,看下里面確實沒有其他組件的代碼和樣式,這里就不貼圖了,大家可以自己嘗試,總結下這里的bes-ui其實就是模仿ElementUI的一個簡易的組件庫(雖然目前只加了按需加載,后續可以把國際化和主題加上),項目里面的一些配置和文件都大同小異,如果有興趣構建自己的vue組件庫的時候,bes-ui是個不錯的模版。

GitHub項目地址:https://github.com/BothEyes1993/bes-ui


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM