乐趣区

关于前端:彻底学会elementui按需引入和纯净主题定制

前言

手上有些我的项目用的element-ui,刚好有空推敲一下怎么减小打包文件大小和打包速度方面,为了演示试验,用 vue-cli 生成初始我的项目,在这仅对 element-ui 主题和组件方面来优化。

vue init webpack vuecli

残缺引入

残缺地将 ui 和款式引入。

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

在页面简略应用 2 个组件,看看成果。

<el-tabs v-model="activeName" @tab-click="handleClick">
  <el-tab-pane label="用户治理" name="first"> 用户治理 </el-tab-pane>
  <el-tab-pane label="配置管理" name="second"> 配置管理 </el-tab-pane>
  <el-tab-pane label="角色治理" name="third"> 角色治理 </el-tab-pane>
  <el-tab-pane label="定时工作弥补" name="fourth"> 定时工作弥补 </el-tab-pane>
</el-tabs>

<el-steps :active="2" align-center>
  <el-step title="步骤 1" description="这是一段很长很长很长的描述性文字"></el-step>
  <el-step title="步骤 2" description="这是一段很长很长很长的描述性文字"></el-step>
  <el-step title="步骤 3" description="这是一段很长很长很长的描述性文字"></el-step>
  <el-step title="步骤 4" description="这是一段很长很长很长的描述性文字"></el-step
></el-steps>

再看一下打包后的资源大小状况npm run build --report

Hash: 40db03677fe41f7369f6
Version: webpack 3.12.0
Time: 20874ms
                                                  Asset       Size  Chunks                    Chunk Names
    static/css/app.cb8131545d15085cee647fe45f1d5561.css     234 kB       1  [emitted]         app
                 static/fonts/element-icons.732389d.ttf      56 kB          [emitted]
               static/js/vendor.a753ce0919c8d42e4488.js     824 kB       0  [emitted]  [big]  vendor
                  static/js/app.8c4c97edfce9c9069ea3.js    3.56 kB       1  [emitted]         app
             static/js/manifest.2ae2e69a05c33dfc65f8.js  857 bytes       2  [emitted]         manifest
                static/fonts/element-icons.535877f.woff    28.2 kB          [emitted]
static/css/app.cb8131545d15085cee647fe45f1d5561.css.map     332 kB          [emitted]
           static/js/vendor.a753ce0919c8d42e4488.js.map    3.26 MB       0  [emitted]         vendor
              static/js/app.8c4c97edfce9c9069ea3.js.map    16.6 kB       1  [emitted]         app
         static/js/manifest.2ae2e69a05c33dfc65f8.js.map    4.97 kB       2  [emitted]         manifest
                                             index.html  506 bytes          [emitted]

发现打包后提取公共模块 static/js/vendor.js824kb

再看一下各个模块占用状况:

发现 elment-ui.common.js 占用最大。所有模块资源总共有 642kb。怎么能力减小打包后的大小呢?很容易就会想到 ui 的引入和款式的引入中,理论咱们只应用了三个组件,却整体都被打包了,在这里引入这三个组件即可。

按需引入组件款式

新建一个 element-variables.scss 文件(为什么是 SCSS 文件,前面自定义主题会用到)。

/*icon 字体门路变量 */
$--font-path: "~element-ui/lib/theme-chalk/fonts";

/* 按需引入用到的组件的 scss 文件和根底 scss 文件 */
@import "~element-ui/packages/theme-chalk/src/base.scss";
@import "~element-ui/packages/theme-chalk/src/rate.scss";
@import "~element-ui/packages/theme-chalk/src/button.scss";
@import "~element-ui/packages/theme-chalk/src/row.scss";

按需引入组件

新建一个 element-config.js 文件,将我的项目用到的 element 组件引入。

import {
  Tabs,
  TabPane,
  Steps,
  Step
} from 'element-ui'

export default {install (V) {V.use(Tabs)
    V.use(TabPane)
    V.use(Steps)
    V.use(Step)
  }
}

第一次优化后打包剖析

将以上 element-variables.scsselement-config.js 引入到 main.js 中。

import ElementUI from '@/assets/js/element-config'
import '@/assets/css/element-variables.scss'

Vue.use(ElementUI)

貌似下面所有都很牵强附会,打包后大小会减小。

Hash: 2ef987c23a5d612e00e1
Version: webpack 3.12.0
Time: 17430ms
                                                  Asset       Size  Chunks                    Chunk Names
    static/css/app.3c70d8d75c176393318b232a345e3f0f.css    38.8 kB       1  [emitted]         app
                 static/fonts/element-icons.732389d.ttf      56 kB          [emitted]
               static/js/vendor.caa5978bb1eb0a15b097.js     824 kB       0  [emitted]  [big]  vendor
                  static/js/app.5ebb19489355acc3167b.js    3.64 kB       1  [emitted]         app
             static/js/manifest.2ae2e69a05c33dfc65f8.js  857 bytes       2  [emitted]         manifest
                static/fonts/element-icons.535877f.woff    28.2 kB          [emitted]
static/css/app.3c70d8d75c176393318b232a345e3f0f.css.map    53.9 kB          [emitted]
           static/js/vendor.caa5978bb1eb0a15b097.js.map    3.26 MB       0  [emitted]         vendor
              static/js/app.5ebb19489355acc3167b.js.map      17 kB       1  [emitted]         app
         static/js/manifest.2ae2e69a05c33dfc65f8.js.map    4.97 kB       2  [emitted]         manifest
                                             index.html  506 bytes          [emitted]

后果可知,static/js/vendor.js 还是 824kb

再看各个模块占用状况:

WHAT? 居然模块都没什么变动,岂不是竹篮打水,大失所望。

再次打包优化尝试

起初查到有人同样遇到这个问题,提出一个 issues#6362,原来只引入须要的 element-ui 组件,webpack还是把整体的 UI 库和款式都打包了,须要一个 webpackbabel 插件 babel-plugin-component,这样能力真正按需引入打包。这块其实被写到官网文档更换 自定义主题 的配置了。

于是 npm i babel-pugin-componet -D 装置后,在减少 .babelrc 文件插件配置

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": [
    "transform-vue-jsx",
    "transform-runtime",
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

页面运行失常,再次打包。

Hash: f182f70cb4ceee63b5d5
Version: webpack 3.12.0
Time: 10912ms
                                                  Asset       Size  Chunks             Chunk Names
    static/css/app.95c94c90ab11fdd4dfb413718f444d0c.css    39.9 kB       1  [emitted]  app
                 static/fonts/element-icons.732389d.ttf      56 kB          [emitted]
               static/js/vendor.befb0a8962f74af4b7e2.js     157 kB       0  [emitted]  vendor
                  static/js/app.5343843cc20a78e80469.js    3.86 kB       1  [emitted]  app
             static/js/manifest.2ae2e69a05c33dfc65f8.js  857 bytes       2  [emitted]  manifest
                static/fonts/element-icons.535877f.woff    28.2 kB          [emitted]
static/css/app.95c94c90ab11fdd4dfb413718f444d0c.css.map    93.5 kB          [emitted]
           static/js/vendor.befb0a8962f74af4b7e2.js.map     776 kB       0  [emitted]  vendor
              static/js/app.5343843cc20a78e80469.js.map    17.1 kB       1  [emitted]  app
         static/js/manifest.2ae2e69a05c33dfc65f8.js.map    4.97 kB       2  [emitted]  manifest
                                             index.html  506 bytes          [emitted]

static/js/vendor.js 的确变小了,157kB。再来看各个模块剖析图。

模块总共 157.93KB,少了 5 倍!

更换主题 - 笼罩款式

element-uitheme-chalk 应用 SCSS 编写,如果在本人的我的项目中也是用 SCSS,那么能够间接在我的项目中扭转款式变量,因而能够在后面新建的 element-variables.scss 文件用新的主题色彩变量笼罩即可。

/**
* 笼罩主题色
*/
/* 主题色彩变量 */
$--color-primary: #f0f;

/*icon 字体门路变量 */
$--font-path: '~element-ui/lib/theme-chalk/fonts';

/* 引入全副默认款式 会引入没用到的组件款式 */
// @import '~element-ui/packages/theme-chalk/src/index';

/* 按需引入用到的组件的 scss 文件和根底 scss 文件 */
@import '~element-ui/packages/theme-chalk/src/base.scss';
@import '~element-ui/packages/theme-chalk/src/rate.scss';
@import '~element-ui/packages/theme-chalk/src/button.scss';
@import '~element-ui/packages/theme-chalk/src/row.scss';

当初咱们的主题就变成了预期成果

可能你曾经留神到了,这里举荐的是别离引入用到的组件款式,而不是引入全副默认款式,因为这样会导致引入没有应用到的组件款式。比方以后案例中咱们没有应用到 ColorPicker 组件,在打包输入的 css 文件中确有该组件款式。

更换主题 - 污浊款式

通过以上优化能够按需的将所用到组件打包,排除没用到的组件,缩小包的大小。然而,还是存在一个小瑕疵:一个用到的组件款式会被两次打包,一次是默认的款式,一次是笼罩的款式。

呈现这个问题是因为咱们在两个中央对款式进行引入了,一个是在 .babelrc 文件中通过 babel-plugin-component 插件按需引入 element-ui 组件及其默认款式,一个是在 element-variables.scss 文件中笼罩默认款式生成的自定义款式。

所以怎么将二者联合,即babel-plugin-component 插件按需引入的组件款式改成用户自定义款式,达成污浊款式指标呢?这里就要用到 element-ui 的主题工具进行深层次的主题定制。

主题和主题工具装置

首先装置主题工具 element-theme,能够全局装置也可装置在我的项目目录。这里举荐装置在我的项目录,不便他人 clone 我的项目时能间接装置依赖并启动。

npm i element-theme -D

而后装置白垩主题,能够从 npm 装置或者从 GitHub 拉取最新代码。

# 从 npm
npm i element-theme-chalk -D

# 从 GitHub
npm i https://github.com/ElementUI/theme-chalk -D

主题构建

element-theme 反对的构建有 Node APICLI 形式。

通过 CLI 构建形式

如果全局装置能够在命令行里通过 et 调用工具,如果装置在当前目录下,须要通过 node_modules/.bin/et 拜访到命令。执行 -i--init)初始化变量文件。默认输入到 element-variables.scss,当然你能够传参数指定文件输入目录。如果你想启用 watch 模式,实时编译主题,减少 -w--watch)参数;如果你在初始化时指定了自定义变量文件,则须要减少 -c--config)参数,并带上你的变量文件名。默认状况下编译的主题目录是放在 ./theme 下,你能够通过 -o--out)参数指定打包目录。

# 初始化变量文件
et --init [file path]

# 实时编译
et --watch [--config variable file path] [--out theme path]

# 编译
et [--config variable file path] [--out theme path] [--minimize]

通过 Node API 构建形式

引入 element-theme 通过 Node API 模式构建

var et = require('element-theme')

// 实时编译模式
et.watch({
  config: 'variables/path',
  out: 'output/path'
})

// 编译
et.run({
  config: 'variables/path', // 配置参数文件门路 默认 `./element-variables.css`
  out: 'output/path', // 输入目录 默认 `./theme`
  minimize: false, // 压缩文件
  browsers: ['ie > 9', 'last 2 versions'], // 浏览器反对
  components: ['button', 'input'] // 选定组件构建自定义主题
})

利用 Node API 构建自定义主题

在这里,为了让主题的构建更加直观和被我的项目共享,采纳 Node API 形式构建,在我的项目根目录下新建 theme.js文件。

const et = require('element-theme')
// 第一步生成款式变量文件
// et.init('./src/theme.scss')
// 第二步依据理论须要批改该文件
// ...
// 第三步依据该变量文件编译出自定义的主题款式文件
et.run({
  config: './src/theme.scss',
  out: './src/theme'
})

package.json 中减少 scripts 指令

{
  "scripts": {"theme": "node theme.js"}
}

这样就能够通过 npm run theme 指令来编译主题了。编译过程:

  • 运行该指令初始化主题变量文件 theme.scss
  • 依据理论须要批改这个文件里主题款式。
  • 再运行该指令编译输入自定义的主题款式文件放在 theme 目录下。

这样就实现了所有自定义主题款式的构建。要想将这些自定义款式随着组件按需引入,须要将 .babelrc 文件中按需引入插件 babel-plugin-component 参数 styleLibraryName 从本来的 element-ui 默认款式目录变成当初自定义目录 ~src/theme

"plugins": [
    "transform-vue-jsx",
    "transform-runtime",
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "~src/theme"
      }
    ]
  ]

所有准备就绪,我的项目打包,打包后的 css 文件中只有惟一自定义款式,没有了默认款式,也不存在没被引入组件的款式,实现了咱们预期的污浊的自定义款式!

Hash: c442bcf9d471bddfdccf
Version: webpack 3.12.0
Time: 10174ms
                                                  Asset       Size  Chunks             Chunk Names
    static/css/app.52d411d0c1b344066ec1f456355aa7b9.css    38.8 kB       1  [emitted]  app
                static/fonts/element-icons.535877f.woff    28.2 kB          [emitted]
               static/js/vendor.befb0a8962f74af4b7e2.js     157 kB       0  [emitted]  vendor
                  static/js/app.43c09c1f16b24d371e07.js    3.82 kB       1  [emitted]  app
             static/js/manifest.2ae2e69a05c33dfc65f8.js  857 bytes       2  [emitted]  manifest
                 static/fonts/element-icons.732389d.ttf      56 kB          [emitted]
static/css/app.52d411d0c1b344066ec1f456355aa7b9.css.map    81.3 kB          [emitted]
           static/js/vendor.befb0a8962f74af4b7e2.js.map     776 kB       0  [emitted]  vendor
              static/js/app.43c09c1f16b24d371e07.js.map    17.1 kB       1  [emitted]  app
         static/js/manifest.2ae2e69a05c33dfc65f8.js.map    4.97 kB       2  [emitted]  manifest
                                             index.html  506 bytes          [emitted]

因为款式是污浊的,css 文件大小从原来齐全引入的 234KB 变成 38.8KB,进一步减小了打包大小。

总结

通过以上试验剖析咱们能够得悉,element-ui 要想实现按需引入和污浊的主题款式:

  • 首先通过 babel-plugin-component 插件进行按需引入。
  • 再用 element-theme 工具生成样变量文件。
  • 而后依据我的项目需要批改自定义款式,根据该文件构建生成所有款式。
  • 最初将按需引入款式 styleLibraryName 指向自定义款式目录。

如果对款式提取要求不高,可间接采取变量笼罩模式(同时存在默认款式)。
还有不分明能够戳这里查看案例源码,赠人 star,手有余香。

完~ps:个人见解无限,欢送斧正。

退出移动版