在業務中,只要使用組件庫,就不可避免的要涉及到按需引入的問題,尤其是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