现状
根据element-ui官方提供的方法,使用babel-pugin-componet
插件可以完成js和css的按需引入,官方提供的配置如下:
// babel.config.js
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
然后在项目的js或者vue文件中引入
import { Button, Select } from 'element-ui';
根据babel-pugin-componet
的官方说明,结合element-ui提供的配置,其作用相当于
// 会自动引入base.css
require('element-ui/lib/theme-chalk/base.css')
var Button = require('element-ui/lib/button')
require('element-ui/lib/theme-chalk/button.css')
var Select = require('element-ui/lib/select')
require('element-ui/lib/theme-chalk/select.css')
这样确实做到了按需引入组件js和css,但是大多数的情况下,我们会根据项目的情况调整element-ui的scss变量,因此就只能手动再单独去引element-ui提供的scss文件,使用scss预编译的结果去覆盖默认的css,最终导致打包出来的css文件中会包括两份base.css、button.css和select.css的内容。
思路
希望按需引入可以直接引入scss文件,然后配置全局的scss变量,直接对引入的scss文件进行作用,而不是通过样式覆盖的方式
babel-pugin-componet
的详细配置中提供了styleLibrary
属性,可以对引入的样式目录进行深度的配置,官方说明如下
// babel-pugin-componet options
["component", { "styleLibrary": {} }]: Import a independent theme package with more config
styleLibrary: {
"name": "xxx", // same with styleLibraryName
"base": true, // if theme package has a base.css
"path": "[module]/index.css", // the style path. e.g. module Alert => alert/index.css
"mixin": true // if theme-package not found css file, then use [libraryName]'s css file
}
可以看到这个配置可以修改加载样式文件的目录,我们按element-ui的scss文件目录进行配置
[
"component",
{
"libraryName": "element-ui",
"styleLibrary": {
"name": "~node_modules/element-ui/packages/theme-chalk/src", // element-ui的scss目录
"base": true, // if theme package has a base.css
"path": "[module].scss", // element-ui的组件scss文件
"mixin": true // if theme-package not found css file, then use [libraryName]'s css file
}
}
]
可以注意到我们配置了base: true
,也就是会加载一个基础样式,因为element-ui是必须有一个基础样式的。进行编译后会报错,提示无法找到node_modules/element-ui/packages/theme-chalk/src/base.css,其实就是默认的文件后缀是css,官方说明中并没有提供设置文件后缀的参数,所以我们进入源码碰碰运气,很幸运在源码中可以看到
const ext = options.ext || '.css';
修改配置
[
"component",
{
"libraryName": "element-ui",
"styleLibrary": {
"ext": ".scss",
"name": "~node_modules/element-ui/packages/theme-chalk/src", // element-ui的scss目录
"base": true, // if theme package has a base.css
"path": "[module].scss", // element-ui的组件scss文件
"mixin": true // if theme-package not found css file, then use [libraryName]'s css file
}
}
]
到这一步就已经成功一大半了,接下去只需要配置一下scss文件的全局预加载变量,使所有的scss文件都加上全局的scss变量。
将修改后的element-ui的全局变量保存在项目根目录中的variables.scss,然后在vue.config.js
中对sass-loader的options进行配置,根据sass-loader的版本不同配置项也不同
{
loader: "sass-loader",
options: {
data: `@import "variables.scss";`
}
}
// 新版sass-loader
{
loader: "sass-loader",
options: {
prependData: `@import "variables.scss";`
}
}