前言
手上有些项目用的element-ui
,刚好有空琢磨一下怎么减小打包文件大小和打包速度方面,为了演示实验,用 vue-cli
生成初始项目,在这仅对 element-ui
主题和组件方面来优化。
1 | vue init webpack vuecli |
完整引入
完整地将 ui
和样式引入。
1 | import ElementUI from 'element-ui' |
在页面简单使用 2 个组件,看看效果。
1 | <el-tabs v-model="activeName" @tab-click="handleClick"> |
再看一下打包后的资源大小情况npm run build --report
。
1 | Hash: 40db03677fe41f7369f6 |
发现打包后提取公共模块 static/js/vendor.js
有 824kb
再看一下各个模块占用情况:
发现 elment-ui.common.js
占用最大。所有模块资源总共有 642kb
。怎么才能减小打包后的大小呢?很容易就会想到 ui
的引入和样式的引入中,实际我们只使用了三个组件,却整体都被打包了,在这里引入这三个组件即可。
按需引入组件样式
新建一个 element-variables.scss
文件(为什么是 SCSS
文件,后面自定义主题会用到)。
1 | /*icon字体路径变量*/ |
按需引入组件
新建一个 element-config.js
文件,将项目用到的 element
组件引入。
1 | import { Tabs, TabPane, Steps, Step } from 'element-ui' |
第一次优化后打包分析
将以上 element-variables.scss
和 element-config.js
引入到 main.js
中。
1 | import ElementUI from '@/assets/js/element-config' |
貌似上面一切都很顺理成章,打包后大小会减小。
1 | Hash: 2ef987c23a5d612e00e1 |
结果可知,static/js/vendor.js
还是 824kb
!
再看各个模块占用情况:
WHAT? 竟然模块都没什么变化,岂不是竹篮打水,事与愿违。
再次打包优化尝试
后来查到有人同样遇到这个问题,提出一个issues#6362,原来只引入需要的element-ui
组件,webpack
还是把整体的 UI
库和样式都打包了,需要一个 webpack
的 babel
插件 babel-plugin-component
,这样才能真正按需引入打包。这块其实被写到官方文档更换 自定义主题 的配置了。
于是 npm i babel-pugin-componet -D
安装后,在增加 .babelrc
文件插件配置
1 | { |
页面运行正常,再次打包。
1 | Hash: f182f70cb4ceee63b5d5 |
static/js/vendor.js
确实变小了,157kB
。再来看各个模块分析图。
模块总共 157.93KB
,少了 5 倍!
更换主题-覆盖样式
element-ui
的 theme-chalk
使用 SCSS
编写,如果在自己的项目中也是用 SCSS
,那么可以直接在项目中改变样式变量,因此可以在前面新建的 element-variables.scss
文件用新的主题颜色变量覆盖即可。
1 | /** |
现在我们的主题就变成了预期效果
可能你已经注意到了,这里推荐的是分别引入用到的组件样式,而不是引入全部默认样式,因为这样会导致引入没有使用到的组件样式。比如当前案例中我们没有使用到 ColorPicker
组件,在打包输出的 css
文件中确有该组件样式。
更换主题-纯净样式
通过以上优化可以按需的将所用到组件打包,排除没用到的组件,减少包的大小。但是,还是存在一个小瑕疵:一个用到的组件样式会被两次打包,一次是默认的样式,一次是覆盖的样式。
出现这个问题是由于我们在两个地方对样式进行引入了,一个是在 .babelrc
文件中通过 babel-plugin-component
插件按需引入 element-ui
组件及其默认样式,一个是在 element-variables.scss
文件中覆盖默认样式生成的自定义样式。
所以怎样将二者结合,即babel-plugin-component
插件按需引入的组件样式改成用户自定义样式,达成纯净样式目标呢?这里就要用到 element-ui
的主题工具进行深层次的主题定制。
主题和主题工具安装
首先安装主题工具 element-theme
,可以全局安装也可安装在项目目录。这里推荐安装在项目录,方便别人 clone
项目时能直接安装依赖并启动。
1 | npm i element-theme -D |
然后安装白垩主题,可以从 npm
安装或者从 GitHub
拉取最新代码。
1 | 从 npm |
主题构建
element-theme
支持的构建有 Node API
和 CLI
方式。
通过 CLI 构建方式
如果全局安装可以在命令行里通过 et
调用工具,如果安装在当前目录下,需要通过 node_modules/.bin/et
访问到命令。执行 -i
(--init
) 初始化变量文件。默认输出到 element-variables.scss
,当然你可以传参数指定文件输出目录。如果你想启用 watch 模式,实时编译主题,增加 -w
(--watch
) 参数;如果你在初始化时指定了自定义变量文件,则需要增加 -c
(--config
) 参数,并带上你的变量文件名。默认情况下编译的主题目录是放在 ./theme
下,你可以通过 -o
(--out
) 参数指定打包目录。
1 | 初始化变量文件 |
通过 Node API 构建方式
引入 element-theme
通过 Node API
形式构建
1 | var et = require('element-theme') |
应用 Node API 构建自定义主题
在这里,为了让主题的构建更加直观和被项目共享,采用 Node API
方式构建,在项目根目录下新建 theme.js
文件。
1 | const et = require('element-theme') |
在 package.json
中增加 scripts
指令
1 | { |
这样就可以通过 npm run theme
指令来编译主题了。编译过程:
- 运行该指令初始化主题变量文件
theme.scss
。 - 根据实际需要修改这个文件里主题样式。
- 再运行该指令编译输出自定义的主题样式文件放在
theme
目录下。
这样就完成了所有自定义主题样式的构建。要想将这些自定义样式随着组件按需引入,需要将 .babelrc
文件中按需引入插件 babel-plugin-component
参数 styleLibraryName
从原本的 element-ui
默认样式目录变成现在自定义目录 ~src/theme
。
1 | "plugins": [ |
一切准备就绪,项目打包,打包后的 css
文件中只有唯一自定义样式,没有了默认样式,也不存在没被引入组件的样式,实现了我们预期的纯净的自定义样式!
1 | Hash: c442bcf9d471bddfdccf |
由于样式是纯净的,css
文件大小从原来完全引入的 234KB
变成 38.8KB
,进一步减小了打包大小。
总结
通过以上实验分析我们可以得知,element-ui
要想实现按需引入和纯净的主题样式:
- 首先通过
babel-plugin-component
插件进行按需引入。 - 再用
element-theme
工具生成样变量文件。 - 然后根据项目需求修改自定义样式,依据该文件构建生成所有样式。
- 最后将按需引入样式
styleLibraryName
指向自定义样式目录。
如果对样式提取要求不高,可直接采取变量覆盖形式(同时存在默认样式)。
还有不清楚可以戳这里查看案例源码,赠人 star,手有余香。
完~ps:个人见解有限,欢迎指正。