为了降低首屏代码大小,对于一些大的第三方库或者团队的基础工具库,需要按需导入模块。如:
import Button from 'antd/lib/button';
但这在需要导入非常多的组件场景时,开发繁琐,体验不友好。在这些组件库的官方文档或者社区会推荐一些babel插件,帮助达到良好的开发体验和性能优化。
本文将详细探究这些工具的原理。
antd等UI组件库按需加载
在使用antd的老版本时,会推荐使用babel-plugin-import工具按需导入组件。工具可以做到如下的转换:
import { Button } from 'antd';
ReactDOM.render(<Button>xxxx</Button>);
↓ ↓ ↓ ↓ ↓ ↓
var _button = require('antd/lib/button');
require('antd/lib/button/style');
ReactDOM.render(<_button>xxxx</_button>);
antd和element-ui都叫做按需加载,但我觉得叫做按需导入更加贴合意境。
eleemnt-ui配套按需导入工具为babel-plugin-component。
babel-plugin-import工具,会在编译时会分析模块导入语句。当为需要导入的目标库组件时,会将原导入删除,生成多个新的导入(如果你配置了style,会额外导入样式)。由于重新生成的导入语句会导致模块变量发生变化(如上文案例演示中Button
会被转换为_button
),这导致插件程序还会分析当前模块的所有变量,对使用原变量的语句中,将变量名修复。
最新的antd已经推荐使用webpack的tree shaking机制来按需加载。babel-plugin-import也基本没什么更新。对于vue生态来说,很多组件库为了支持全局注册的方式,无法使用tree shaking。
虽然babel-plugin-import等工具支持一些配置定制,但还是存在下面缺点:
- 每个插件都是针对特定的组件库,需要符合特定的目录和文件维护规范。如babel-plugin-import导入的模块需要支持目录为:
|--component
|----index.js
|----*.js
|----style
|------index.js
|------*.css
- babel-plugin-import由于底层实现改变了导入的模块变量,然后再全模块枚举语句类型中找到使用变量将其修复,再某一些非常不常见的语句中,会出现没有转变模块变量导致语法错误问题。
在vue代码中根据标签按需导入
在vue应用注册组件时,有两种方式:全局注册和局部注册。全局注册开发体验式最好的,但会导入UI组件库的所有代码,增加很多无用代码从而首屏激增。如何做到像全局注册组件那样开发友好,又支持按需导入组件提高性能呢?
这里提供一个方案:在vue文件的模板在解析的时候,记录模板文件使用的标签,然后在文件对应的js代码编译的时候,根据标签自动导入UI组件,然后在组件配置对象的components
属性中注册上去。
假如代码:
<template>
<div>
<el-button>按钮</el-button>
</div>
</template>
<script>
export default {
created() {
},
};
</script>
在编译时,将会转换类似于:
<template>
<div>
<el-button>按钮</el-button>
</div>
</template>
<script>
import ElButton from 'element-ui/lib/form-item';
export default {
components: {
ElButton,
},
created() {
},
};
</script>