在业务中,只要使用组件库,就不可避免的要涉及到按需引入的问题,尤其是element这种重量级的组件库,如果一次性全部引入,对整个项目的大小影响很大。但是,element官方只提供了基于babel的按需引入方案(babel-plugin-component),并没有给出ts应该如何做到按需引入。
经过试验,如果不做处理,哪怕是import { Button, Select } from 'element-ui';
,在ts中还是会全部引入。
本来是之前是没什么好办法的,只能额外引入babel,先将ts编译成ES6的JS,再通过babel进行一次处理,但是上次用vant-ui的时候,看到他们官方推荐的一个插件很有意思, ts-import-plugin。按照作者的说法,这个插件是babel-plugin-component的ts实现,看了看文档似乎也是支持element-ui的:
// webpack.config.js
const tsImportPluginFactory = require('ts-import-plugin')
module.exports = {
// ...
module: {
rules: [
{
test: /\.(jsx|tsx|js|ts)$/,
loader: 'ts-loader',
options: {
transpileOnly: true,
getCustomTransformers: () => ({
before: [ tsImportPluginFactory( /** options */) ]
}),
compilerOptions: {
module: 'es2015'
}
},
exclude: /node_modules/
}
]
},
// ...
}
transformerFactory({
libraryName: 'element-ui',
libraryDirectory: 'lib',
camel2DashComponentName: true,
style: (path: string) =>
join('element-ui', 'lib', 'theme-chalk', `${
camel2Dash(basename(path, '.js'))}.css`),
})
看起来是没啥问题的。但是真正用起来,里面有两个小问题:
-
文档前面的
tsImportPluginFactory
和后面的transformerFactory
是不是一个东西?经过试验,确实是一个东西。 -
如果直接复制上面的代码,会报错join、camel2Dash、basename未定义。并且作者也没有在文档上写明白这一点。事实上,这是额外引入了两个库:
const path = require("path"); const join = path.join; const basename = path.basename; const camel2Dash = require("camel-2-dash");
解决了上面两个问题,就可以按照import { Button, Select } from 'element-ui';
的方式进行按需引入了。
因为我这个场景是Vue,vue-cli的配置有一点区别,因为vue-cli基于webpack-chain,所以语法和标准的webpack还不太一样,需要一些额外的处理。在根目录下创建一个vue.config.js,然后把上面的内容改造一下:
// vue.config.js
const path = require("path");
const tsImportPluginFactory = require("ts-import-plugin");
const join = path.join;
const basename = path.basename;
const camel2Dash = require("camel-2-dash");
module.exports = {
chainWebpack: config => {
config.module
.rule("ts")
.use("ts-loader")
.tap(options => {
options = merge(options, {
transpileOnly: true,
getCustomTransformers: () => ({
before: [
tsImportPluginFactory({
libraryName: "element-ui",
libraryDirectory: "lib",
camel2DashComponentName: true,
style: path =>
join(
"element-ui",
"lib",
"theme-chalk",
`${camel2Dash(basename(path, ".js"))}.css`
)
})
]
}),
compilerOptions: {
module: "es2015"
}
});
return options;
});
}
};
这样就可以和Vue联动了。
参考资料
- https://element.eleme.cn/#/zh-CN/component/quickstart#an-xu-yin-ru
- https://youzan.github.io/vant/?source=vuejsorg#/zh-CN/quickstart#yin-ru-zu-jian
- https://github.com/Brooooooklyn/ts-import-plugin#element-ui
- https://github.com/Brooooooklyn/ts-import-plugin/issues/29#issuecomment-583895937