1

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?

KFE
  • 637
  • 5
  • 10

2 Answers2

2

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.

TLadd
  • 6,488
  • 2
  • 32
  • 40
  • How do you handle importing the component/3rd party library inside of your components though? Don't I still need to do `import { Button} from antd` which would then duplicate the code across multiple chunks/bundles? – KFE Mar 08 '18 at 14:12
  • When you have an explicit vendor bundle (or anything created from commonChunksPlugin), webpack is smart enough to read the import and know to look for it in the common vendor chunk. – TLadd Mar 08 '18 at 14:23
  • You're right @TLadd, I think my real issue is that CommonChunksPlugin doesn't seem to be pulling those component imports out of their respective chunk. It's creating a vendor chunk but those components are still be duplicated across multiple chunks. Do you think this could be because i'm using webpack's `import` to lazy-load/code-split my container components? https://i.imgur.com/kas9ab4.png – KFE Mar 08 '18 at 17:40
  • This other question seems very similar to the issue that i'm having however his chunks are named whereas mine have an ID and hash so i'm not sure I could explicitly list them in the chunks array. https://stackoverflow.com/questions/44922415/webpack-react-router-v4-code-splitting-duplicate-modules-in-async-chunks – KFE Mar 08 '18 at 17:45
  • Fixed the chunk names and tried the 'chunks' property of CommonChunksPlugin but those components were still duplicated across the board. :( – KFE Mar 08 '18 at 17:59
0

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" 
Azametzin
  • 5,223
  • 12
  • 28
  • 46
Scott Wager
  • 758
  • 11
  • 9