umijs / babel-plugin-import

Modularly import plugin for babel.
3.16k stars 404 forks source link

Fix vendor / commonchunks / code splitting problems with antd #190

Open andriijas opened 6 years ago

andriijas commented 6 years ago

When using babel-plugin-import with antd it currently cant be used with vendor splitting or commonchunks. Can we investigate if we can get this working?

using webpack analyzer shows that most antd apps with chunks and code splitting rebundle a lot of antd with every chunk which creates overhead. We can use ant-design/ant-design-pro#278 as example.

cameronb23 commented 6 years ago

Any solution?

andriijas commented 6 years ago

Its possible, just need to use the full path in your vendor config

vendors: { "antd/es/modal", "rc-dialog" }

FoxxMD commented 4 years ago

For folks finding this in the future I got this 'mostly' fixed by trial and error. This is what has worked best for me so far.

It is tree-shaking both antd and @ant-design/icons with babel-plugin-imports and then chunking the tree-shaked modules into a named chunk. The vendors chunk excludes antd/ant-design (and optionally react is chunked separately too).

image

In webpack.prod.js

optimization: {
  splitChunks: {
    chunks: 'all',
    name: true, // using named keeps the modules together for some reason
    minSize: 0,
    cacheGroups: {
      // not necessary but helps
      react: {
        test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
        name: 'react',
        chunks: 'all',
        reuseExistingChunk: true,
      },
      // chunk all antd/ant-design modules into a named module
      antd: {
        test(module) {
          return module.resource && (module.resource.includes('antd') || module.resource.includes('ant-design'));
        },
        name: 'antd',
        chunks: 'all',
        reuseExistingChunk: true,
      },
      // chunk all non antd/ant-design modules into vendors
      vendors: {
        reuseExistingChunk: true,
        test(module, chunks) {
          // https://github.com/ant-design/babel-plugin-import#note
          return module.resource
            && module.resource.includes('node_modules')
            && !module.resource.includes('antd')
            && !module.resource.includes('ant-design');
        },
      },
    },
  },
  ...
}

In webpack.base.js (babel-plugin-import config)

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            plugins: [
              ['import', {
                libraryName: 'antd',
                libraryDirectory: 'lib', // lib works better than es
                style: true, // used when importing less or modifying theme variables
              }, 'antd'],
              [
                // only need if also using ant-design icons
                "import",
                {
                  // this was the best combination
                  libraryName: '@ant-design/icons',
                  libraryDirectory: '', 
                  camel2DashComponentName: false
                },
                '@ant-design/icons'
              ],
            ],
          },
        },
      },
      // https://medium.com/@GeoffMiller/how-to-customize-ant-design-with-react-webpack-the-missing-guide-c6430f2db10f
      // only needed if using less and modifying variables
      {
        test: /\.less$/,
        use: [
          { loader: 'style-loader' },
          { loader: 'css-loader' },
          {
            loader: 'less-loader',
            options: {
              javascriptEnabled: true,
              modifyVars: {
                'hack': `true; @import "${themeOverrideLocation}";`
              }
            },
          },
        ],
      },