1
votes

Problem: Common antd components (such as Button) are being duplicated across multiple chunks, instead of being extracted into a separate file, and thus being downloaded more than once by the end user.

I'm using create-react-app in conjunction with react-app-rewired and it's injectBabelPlugin function to modularly call Ant Design components.

My config-overrides.js

const { injectBabelPlugin } = require("react-app-rewired")

module.exports = function override(config, env) {
    return injectBabelPlugin(["import", { libraryName: "antd", style: 
    "css" }], config)
}

and I call the components like:

import { Row, Col, Button } from "antd"

This all works fine and dandy.

The issue i'm having is when running webpack-bundle-analyzer, i'm seeing that common antd components (such as Button) are being duplicated across multiple chunks.

(see example)

I've tried some CommonChunksPlugin configurations but to no avail.

My end goal is to load antd components, that are used in multiple chunks, in their own file. Is this possible using code splitting and lazy loaded components?

2

2 Answers

2
votes

Typically, I would put a common dependency like this in my vendor bundle, which basically just includes 3rd-party dependencies that don't change all that often, so they will load once and be pulled from cache until I update one of the vendor dependencies. It looks like the ability to create a vendor bundle with CRA is going to come with the upgrade to Webpack 4 in v2.0.0 of react-scripts, but isn't ready yet. I'm not sure if there's a great way to solve this problem right now without ejecting, but seems like there will be in the future.

0
votes

Solution without modifying webpack:

On the parent component (or a higher parent), do the exact same import here:

import { Row, Col, Button } from "antd"

You could use React.lazy to import here as well. I don't think it's necessary, but you could put this inside a useEffect so this code is only read by your app when that parent component mounts.

useEffect(() => {
  React.lazy(() => import("antd"))
}, []);

In the child component, import with the same code as normal to use the variables. Webpack recognises that this module has already been downloaded, because the parent component still exists so it doesn't include them in new bundles.

import { Row, Col, Button } from "antd"