Vue 2.x TypeScript 按需引入element-ui

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

看起來是沒啥問題的。但是真正用起來,裏面有兩個小問題:

  1. 文檔前面的tsImportPluginFactory和後面的transformerFactory是不是一個東西?經過試驗,確實是一個東西。

  2. 如果直接複製上面的代碼,會報錯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聯動了。

參考資料

  1. https://element.eleme.cn/#/zh-CN/component/quickstart#an-xu-yin-ru
  2. https://youzan.github.io/vant/?source=vuejsorg#/zh-CN/quickstart#yin-ru-zu-jian
  3. https://github.com/Brooooooklyn/ts-import-plugin#element-ui
  4. https://github.com/Brooooooklyn/ts-import-plugin/issues/29#issuecomment-583895937
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章