As your Next.js app grows in complexity, it's good to keep track of what dependencies are having an outsized impact on your bundle size. The Next team has a few tricks up their sleeve to reduce client side bundle size. However, in real life you will run into some packages that are MBs in size and you'll need to find a way to reduce their impact on your bundle size.
The best way to track the impact of each dependency is to use a Next.js specific Bundle Analyzer to see what is contributing to your bundle size.
You are able to break this down by page, and beyond that you can quickly knock down some large dependencies with dynamic imports
At $WORK we were battling a large First Load JS Shared By All
, which was clearly being weighed down by our react-icons
package.
To save you some googling, the problem is react-icons is a legacy monorepo that bundles all of the icons into one package. This means that if you only use one icon, you are still bundling all of the icons. You can try to use every next trick in the book, and you might read that it doesn't happen in NODE_ENV=production
, but it does...
Once you learn about all the problems, with react-icons
you'll find that there is a new package called @react-icons/all-files
that is a drop in replacement for react-icons
that allows you to import only the icons you need. It doesn't have the same bundling issues as react-icons
and it's supposed to be a drop in replacement. The problem is the newest version of @react-icons/all-files
isn't up to date with the latest version of react-icons
and it's missing some icons. Oi vey.
The reason is because the @react-icons/all-files
package is reportedly too large to upload to npm. An obvious solution would be to try to off ramp from react-icons all together but I found that easier said than done, it's convienent!
The only solution I have found is installing @react-icons/all-files
by linking your package.json
to the .tgz
file hosted on github:
"@react-icons/all-files": "https://github.com/react-icons/react-icons/releases/download/v4.11.0/react-icons-all-files-4.11.0.tgz",
This seems to dramatically increase install times, but if reducing bundle size is your ultimate goal, than it is worth it.
When I was converting my teams app, we had over 90 imports of react-icons
and I didn't want to manually convert each one. I found that using regex was the best way to quickly convert all of the imports.
I manually wrote (no chat-gpt fr) a regex that would convert all of the imports from react-icons
to @react-icons/all-files
:
import \{ ([a-zA-Z]+) \}[ ]+from[ ']+react-icons/([a-z]+)
import { $1 } from '@react-icons/all-files/$2/$1
This will only work for files with single react-icon imports, which was about 80% of our imports. For the other 20% I had to manually convert them.
Making these changes dramatically redruced our bundle size and I hope it does the same for you!