解决element-ui按需引入时自定义修改scss变量导致的重复引入css的问题

现状

根据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";`
  }
}

你可能感兴趣的:(解决element-ui按需引入时自定义修改scss变量导致的重复引入css的问题)