仿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
仿ElementUI构建自己的Vue组件库用babel-plugin-component按需加载组件及自定义SASS主题的更多相关文章
- vue按需加载组件,异步组件
说实话,我一开始也不知道什么叫按需加载组件,组件还可以按需加载???后来知道了 学不完啊...没关系,看我的 按需加载组件,或者异步组件,主要是应用了component的 is 属性 template ...
- iview简单使用+按需加载组件的方法(全局和局部)
1,简单使用 vue项目中使用iview非常简单: 首先安装依赖: $ npm install iview --save 会安装最新版本的依赖,安装完成后package.json会出现如下图配置 表示 ...
- vue项目优化之按需加载组件-使用webpack require.ensure
require-ensure和require-amd的区别: require-amd 说明: 同AMD规范的require函数,使用时传递一个模块数组和回调函数,模块都被下载下来且都被执行后才执行回调 ...
- vue按需加载组件-webpack require.ensure
使用 vue-cli构建的项目,在 默认情况下 ,执行 npm run build 会将所有的js代码打包为一个整体, 打包位置是 dist/static/js/app.[contenthash].j ...
- vue路由管理-保留滚动位置功能、按需加载模块名自定义
路由管理:保留滚动位置 其实现与组件的keep-alive相关,仅设置了keep-aive的页面,实施保留回退位置能力. keep-alive介绍 作用 把切换出去的组件保留在内存中,可以保留它的状态 ...
- ant-design如果按需加载组件
Ant Design React按需加载 Ant Design是阿里巴巴为React做出的组件库,有统一的样式及一致的用户体验 官网地址:https://ant.design 1.安装: npm in ...
- 【react学习二】create-react-app 接入antd 并按需加载组件
1.安装 cnpm i babel-plugin-import --save-dev 2.使用 在根目录下的package.json下的bable中添加相应代码 "babel": ...
- vue如何实现代码打包分离(按需加载)
在vue中使用import()来代替require.ensure()实现代码打包分离 一.require.ensure() 方法来实现代码打包分离 require.ensure() 是 webpack ...
- 前端开发web组件之旅(一)-- 定义与加载组件
/* 前言 */ 自上而下的 职责和API应用层框架层框架浏览器 一 组件定义与调用 1.增加一个组件 tabview.css ------------------------------------ ...
随机推荐
- Mac OSX sublime text2 各种快捷键
Mac 快捷键 https://support.apple.com/zh-cn/HT201236 Preferences -> Key Bindings - User [ { "key ...
- Python(网络基础)
day33 参考:http://www.cnblogs.com/linhaifeng/articles/5937962.html IP协议: 规定网络地址的协议叫ip协议,它定义的地址称之为ip地址, ...
- [Angular 6] 初学angular,环境全部最新,[ ng serve ] 不能启动,卡在 95% 不动 => 解决方案
2018.9.7 问题描述: 通过ng serve命令启动angular应用时,卡在95%, ctrl+c 停掉后看到错误内容为找不到ng_modules下的angular模块下的package.js ...
- 网络请求 爬虫学习笔记 一 requsets 模块的使用 get请求和post请求初识别,代理,session 和ssl证书
前情提要: 为了养家糊口,为了爱与正义,为了世界和平, 从新学习一个爬虫技术,做一个爬虫学习博客记录 学习内容来自各大网站,网课,博客. 如果觉得食用不良,你来打我啊 requsets 个人觉得系统自 ...
- 数据库中"DDL","DML","DCL"
sql组成:DDL:数据库模式定义语言,关键字:createDML:数据操纵语言,关键字:Insert.delete.updateDCL:数据库控制语言 ,关键字:grant.removeDQL:数据 ...
- 汉诺塔问题(C++版)
题目描述 Description 约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下.由小到大顺序串着由64个圆盘构成的塔.目的是将最左边杆上的盘全部移到中间的杆 ...
- POJ 1111
#include<iostream> #define MAXN 30 using namespace std; char _m[MAXN][MAXN]; bool mark[MAXN][M ...
- .Net Core Nuget还原失败
项目获取后发现所有项目的依赖项全部报黄.. 展开发现所有的Nuget包都没有引用.. 按错误窗口的提示使用解决方案上"Nuget包还原"来解决却没有任何进展.. 错误窗口报文 找不 ...
- 剑指offer三十五之数组中的逆序对
一.题目 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数P.并将P对1000000007取模的结果输出. 即输出P%1000 ...
- js前端日期格式化处理
js前端日期格式化处理 1.项目中时间返回值,很过时候为毫秒值,我们需要转换成 能够看懂的时间的格式: 例如: yyyy-MM-dd HH:mm:ss 2.处理方法(处理方法有多种,可以传值到前端 ...