使用antd之类的框架经常需要以下配置用于减少打包后的体积:

1
2
3
4
5
{
"plugins": [
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }] // `style: true` 会加载 less 文件
]
}

这个插件的功能是利用babel解析后得到抽象语法树,收集导入库的语句,在编译时替换为导入指定文件。

antd为例,以下代码做的就是根据libraryName,也就是antd,来判断,如果导入语句符合import {Button} from 'antd'的形式,即从antd导入了组件,那么就将这条语句加入到待替换列表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ImportDeclaration(path) {
const { node } = path;

// path maybe removed by prev instances.
if (!node) return;

const { value } = node.source;
const libraryName = this.libraryName;
const types = this.types;
if (value === libraryName) {
node.specifiers.forEach(spec => {
if (types.isImportSpecifier(spec)) {
this.specified[spec.local.name] = spec.imported.name;
} else {
this.libraryObjs[spec.local.name] = true;
}
});
this.pathsToRemove.push(path);
}
}

得到了要替换的语句,就可以根据插件中配置的选项进行替换。例如:

1
import {Button} from 'antd'

根据插件配置解析后得到的文件路径为antd/es/button,其中es是插件中的libraryDirectory选项,指定组件所在的源文件目录。因此,上面的语句就变成了下面的形式:

1
import Button from 'antd/es/button'

这样就不必导入整个库了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
importMethod(methodName, file) {
if (!this.selectedMethods[methodName]) {
const libraryDirectory = this.libraryDirectory;
const style = this.style;
const transformedMethodName = this.camel2UnderlineComponentName // eslint-disable-line
? camel2Underline(methodName)
: this.camel2DashComponentName
? camel2Dash(methodName)
: methodName;
const path = winPath(
this.customName ? this.customName(transformedMethodName) : join(this.libraryName, libraryDirectory, transformedMethodName, this.fileName) // eslint-disable-line
);
this.selectedMethods[methodName] = addDefault(file.path, path, { nameHint: methodName });
if (style === true) {
addSideEffect(file.path, `${path}/style`);
} else if (style === 'css') {
addSideEffect(file.path, `${path}/style/css`);
} else if (typeof style === 'function') {
const stylePath = style(path, file);
if (stylePath) {
addSideEffect(file.path, stylePath);
}
}
}
return Object.assign({}, this.selectedMethods[methodName]);
}

总结下来就一句话:按需加载不过是将import {Button} from 'antd'的形式转换为import Button from 'antd/es/button'的形式的过程。

Loading comments...