40

I'm using ant design library for my react application.

And I've faced with huge imports, that hurts my bundle (currently 1.1 mb in minified version because of ant-design lib).

How can I differently import antd components through all my app?

enter image description here

UPDATE:

Seems antd has some huge or non optimized modules. Here the thing - only difference is import Datepicker module, and.. boom! + almost 2MB (in dev bundle ofc.)

enter image description here

Philipp Kyeck
  • 16,652
  • 15
  • 72
  • 105
WebArtisan
  • 3,248
  • 9
  • 31
  • 54
  • I am using antd for a small project with only two route. The project size is 1.6MB after uglify. Kindly provide an answer here if you able to solve this problem. – Sisir Oct 01 '18 at 08:11

7 Answers7

22

UPD: the underlying issue seems to be resolved for the new (4.0) version of antd.
Therefore, if you try to resolve this issue for the earlier versions, the recommended way is to migrate onto antd 4

Previous answer:

At the moment, a huge part of antd dist is SVG icons.
There is no official way to deal with it yet (check the issue on github).

But a workaround exists.

  1. Adapt webpack to resolve icons differently. In your webpack config:
module.exports = {
  //...
  resolve: {
    alias: {
      "@ant-design/icons/lib/dist$": path.resolve(__dirname, "./src/icons.js")
    }
  }
};
  1. Create icons.js in the folder src/ or wherever you want it. Be sure it matches the alias path!
    In this file you define which icons antd should include.
export {
  default as DownOutline
} from "@ant-design/icons/lib/outline/DownOutline";

It's also possible to do this with react-app-rewire (create-react-app modifications) within config-overwrites.js

Community
  • 1
  • 1
Daydreaming Duck
  • 1,551
  • 2
  • 13
  • 23
11

1) Prevent antd to load the all moment localization. Add webpack plugin and configure it in webpack.config.js like the follow:

plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /ru/),
],
resolve: {
    alias: {moment: `moment/moment.js`}
},
target: `web`
}

2) Use the same moment version as in antd library.

3) Use modularized antd Use babel-plugin-import

// .babelrc or babel-loader option
{
  "plugins": [
    ["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
    // `style: true` for less
  ]
}

I use BundleAnalyzerPlugin to analyze the bundle.

plugins: [new BundleAnalyzerPlugin()]

sultan
  • 2,523
  • 1
  • 16
  • 25
9

Looking at the docs https://ant.design/docs/react/getting-started#Import-on-Demand there is a recommedation to import individual components on demand. So, you can try and replace

import { Button} from 'antd' 

with

import Button from 'antd/lib/button'
partyelite
  • 722
  • 13
  • 22
  • 8
    This is automatically taken care of when using [babel-plugin-import](https://github.com/ant-design/babel-plugin-import) – Dave Howson Apr 24 '19 at 10:31
  • I found https://github.com/vazco/uniforms/issues/219 helpful. – B--rian Oct 07 '19 at 12:33
  • @DaveHowson Yes but babel-plugin-import can be used with popular tools like create-react-app only by ejecting. Read [this issue](https://github.com/facebook/create-react-app/issues/2463) on GitHub for more info. – Paul Razvan Berg Nov 26 '19 at 18:07
  • I tried this approach in `import { Collapse } from "antd/lib/collapse";` and destructuring `const { Panel } = Collapse;` but getting error `TypeError: Cannot destructure property 'Panel' of 'antd_lib_collapse__WEBPACK_IMPORTED_MODULE_3__.Collapse' as it is undefined.` – era s'q Mar 15 '21 at 08:07
6

I reduced my bundle size by 500KB by editing config-override.js like so:

config-override.js

const { override, fixBabelImports } = require('customize-cra');
const path = require('path');

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css'
  }),
  // used to minimise bundle size by 500KB
  function(config, env) {
    const alias = config.resolve.alias || {};
    alias['@ant-design/icons/lib/dist$'] = path.resolve(__dirname, './src/icons.js');
    config.resolve.alias = alias;
    return config;
  }
);

./src/icons.js

/**
 * List all antd icons you want to use in your source code
 */
export {
  default as SearchOutline
} from '@ant-design/icons/lib/outline/SearchOutline';

export {
  default as CloseOutline
} from '@ant-design/icons/lib/outline/CloseOutline';

export {
  default as QuestionCircleOutline
} from '@ant-design/icons/lib/outline/QuestionCircleOutline';

export {
  default as PlayCircleOutline
} from '@ant-design/icons/lib/outline/PlayCircleOutline';

export {
  default as PauseCircleOutline
} from '@ant-design/icons/lib/outline/PauseCircleOutline';

export {
  default as LoadingOutline
} from '@ant-design/icons/lib/outline/LoadingOutline';

Before

Screen Shot 2019-11-05 at 2 56 54 pm

After

Screen Shot 2019-11-05 at 2 56 48 pm

Jan
  • 697
  • 8
  • 10
  • Hi @Jan, How can we know which icons should we import in icons.js file. I have an InputNumber and also Select dropdown. but the arrows are not visible :-| Any help/suggestion would be appreciated. – stafan Jan 31 '20 at 18:59
3

Those few components are certainly not 1.2M together. Looks like you are importing the whole library when you only need a few components.

To get antd to load only the needed modules you should use babel-plugin-import. Check your console log for the "You are using a whole package of antd" warning described at that link.

Check out the docs for Create-React-App for how to implement it if you're using CRA.

Jesper We
  • 4,858
  • 2
  • 19
  • 33
  • My console is clean as baby tear. And I'm already using babel-plugin-import. Anyway bundle still huge. Will try to reformat my imports with import Thing from 'antd/lib/thing'. It will reduce size, probably, but definitely will cause many import strings. – WebArtisan Feb 12 '18 at 14:08
  • Well something is wrong with your setup. My bundles usually has all of the components you list except Layout, plus many more. antd is 348kB uncompressed. The **entire** app including antd, React and stupidly large lodash plus lots of other stuff is 350kB gzipped. – Jesper We Feb 12 '18 at 14:29
  • A tip: https://github.com/chrisbateman/webpack-visualizer is a simple plugin that will give you a very good visual report of your bundle where you can drill down inside of modules. You can use it to see which parts of Antd are actually included. – Jesper We Feb 12 '18 at 14:33
  • Had the same problem as WebArtisan. Followed the instructions for CRA step by step. It didn't help the bundle still contains components that I don't use. Here are screenshots of my package.json. config-overrides.js, and the visualisation of bundle.js: https://imgur.com/a/Pnpm4I3 – Zapnuk Jul 19 '18 at 11:44
0

Try using code splitting using webpack and react router. It will help you to load the modules asynchronously. This is the only solution helped me to improve the page load time when using ant framework.

Sivadass N
  • 803
  • 3
  • 12
  • 22
  • I am also thinking of using react-loadable for async loading with antd but the Ant documentation talks about using react-app-rewire for modular imports. I am wondering if I should do both or just react-loadble for dynamic component import. I feel like code splitting alone should help but this thread worries me - https://github.com/ant-design/ant-design/issues/12011 – AnBisw Apr 06 '19 at 23:44
0

Issue which caused large bundle size has been fixed in Ant Design 4.0.

Quoting from the release announcement.

Smaller size

In antd @ 3.9.0, we introduced the svg icon ([Why use the svg icon?] ()). The icon API using the string name cannot be loaded on demand, so the svg icon file is fully introduced, which greatly increases the size of the packaged product. In 4.0, we adjusted the icon usage API to support tree shaking, reducing the default package size of Antant by about 150 KB (Gzipped).

In order to install Ant Design 4 you have to do following

npm install antd@4.0.0-rc.1
// or  in yarn
yarn add antd@4.0.0-rc.1
user158
  • 9,766
  • 7
  • 39
  • 71