I currently joined a project and started working on its web app written in React, using Ant Design (package: antd) as the UI library. While everything else is well and good, the project clearly had an issue with its bundle size. It was shipping megabytes (already compressed, ofc) of code to the client-side. So I thought as someone who's interested in making clean and fast websites, I ought to investigate.
This post is the first in the series of me optimizing the performance of this particular project. At the moment of writing, I'm 2 months in and have been making significant progress.
Right of the bat, building the project (using Vite) gives me the following results:
... many more lazy-loaded modules build/assets/index.42e80c1c.js 75.08 KiB / gzip: 21.51 KiB build/assets/index.dd3abd12.js 63.42 KiB / gzip: 18.25 KiB build/assets/index.dde1f4ba.js 106.44 KiB / gzip: 36.13 KiB build/assets/index.a862fc09.js 133.82 KiB / gzip: 36.82 KiB build/assets/index.2abc25c6.js 178.74 KiB / gzip: 52.90 KiB # These are eagerly loaded build/assets/index.f6ef2bbb.css 346.10 KiB / gzip: 60.39 KiB build/assets/index.40bb55d8.js 483.83 KiB / gzip: 136.26 KiB build/assets/browser.a002aaef.js 685.69 KiB / gzip: 187.29 KiB build/assets/index.cbcdbec4.js 1566.62 KiB / gzip: 440.35 KiB build/assets/vendor.e8ce99ba.js 5377.73 KiB / gzip: 1575.32 KiB
Given the context that this webapp is mainly an info app (making API requests and displaying the results on the UI), shipping over 2mb of JS code on initial load is, to my standard, not good.
I then decided to install rollup-plugin-visualizer which would help me take a deeper look into the code that is being bundled. And I found something interesting.
Inside the antd
module, there were 2 huge chunks called lib
and es
which have items that are almost if not identical:
This is a clear sign that we were having troubles with treeshaking for Antd. Having some experiences dealing with ES modules, and seeing that the codebase were importing items from both antd/es/*
and antd/lib/*
, I suspected that the bundle size should reduce greatly if we were to just convert all antd/lib
import paths to antd/es
.
A quick Google search confirmed my suspicion on the nature of the problem: This GitHub issue's marked answer
So the only thing left to do is a Search All & Replace using Vscode:
And boom! The vendor.js
file, which contains all the code bundled from our beloved node_modules, is now smaller than before. A 25% reduction, that is!
build/assets/index.f6ef2bbb.css 346.10 KiB / gzip: 60.39 KiB build/assets/index.6c0b1689.js 483.83 KiB / gzip: 136.26 KiB build/assets/browser.532ccd09.js 685.69 KiB / gzip: 187.29 KiB build/assets/index.7f70652c.js 1566.60 KiB / gzip: 440.32 KiB build/assets/vendor.488cf11a.js 4043.13 KiB / gzip: 1203.30 KiB
You can add the following rule to your Eslint/OXLint config file:
"no-restricted-imports": [ "error", { "paths": [ { "name": "antd/lib", "message": "Don't import from 'antd/lib/...'. Use 'antd/es/...' instead." } ], "patterns": [ { "group": ["antd/lib/*"], "message": "Don't import from 'antd/lib/...'. Use 'antd/es/...' instead." } ] } ]