Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Icons Imports everything even when included 2 or 3 icons #154

Closed
sandeepreddy19 opened this issue Jul 19, 2018 · 156 comments
Closed

React Icons Imports everything even when included 2 or 3 icons #154

sandeepreddy19 opened this issue Jul 19, 2018 · 156 comments

Comments

@sandeepreddy19
Copy link

I had imported below icons in Create React App and I see that it included the whole library in the bundle. Attached is a screenshot. How do we get around this?

import {
FaBarChart,
FaDatabase,
FaMinus,
FaPlus,
FaStickyNote
} from 'react-icons/lib/fa'
import { IoChatboxWorking } from 'react-icons/lib/io'

screen shot 2018-07-19 at 9 58 14 am

@sandeepreddy19 sandeepreddy19 changed the title Imports everything even when included 2 or 3 icons React Icons Imports everything even when included 2 or 3 icons Jul 19, 2018
@JaccoGoris
Copy link

I have the same issue
image

@sandeepreddy19
Copy link
Author

@JaccoGoris Did you find any fix for this issue?

@JaccoGoris
Copy link

JaccoGoris commented Jul 25, 2018

@sandeepreddy19
I found a fix by switching to 3.0.0-Beta1 and including icons like this:
import { MdPublic } from 'react-icons/md/index.mjs';
which resulted in correct threeshaking. the downside is that my build time went from 3 seconds to 225 seconds.. (3.75min) so.. 75x slower when using this method with md icons.
Then, when I also used some fa icons too, it went up to 279 seconds (93x).
But at least my bundle size went from 1MB to 270kb 😄

@JaccoGoris
Copy link

JaccoGoris commented Jul 25, 2018

@sandeepreddy19
I just figured out how to set it up correctly with 2.2.7
unfortunately you have to import them all separately from the lib files, like this:

import FaFacebookSquare from 'react-icons/lib/fa/facebook-square';
import FaLinkedin from 'react-icons/lib/fa/linkedin';
import FaTwitter from 'react-icons/lib/fa/twitter';
import FaPinterest from 'react-icons/lib/fa/pinterest-square';
import FaInstagram from 'react-icons/lib/fa/instagram';

instead of like this:

import {
    FaFacebookSquare,
    FaLinkedin,
    FaTwitter,
    FaPinterest,
    FaInstagram
} from 'react-icons/lib/fa';

which would have been a lot nicer.
But I got only the icons I need now and a build time of 5 seconds!
So probably we need to fix the code or fix the docs

@antoinerousseau
Copy link
Collaborator

antoinerousseau commented Jul 28, 2018

Should be better in 3.x with #141

@abramobagnara
Copy link

I have the same problem with react-icons 3.0.1

@wopian
Copy link

wopian commented Aug 1, 2018

#141 doesn't seem to have had any effect on size. 2.2.7 with the old format was 6kb for 5 icons. Upgrading to 3.0.1 and migrating to import { <icon> } from 'react-icons/md' is now 350kb

import MdGroup from 'react-icons/lib/md/group'
import MdFavorite from 'react-icons/lib/md/favorite'
import MdStar from 'react-icons/lib/md/star'
import MdThumbsUpDown from 'react-icons/lib/md/thumbs-up-down'
import MdLocalLibrary from 'react-icons/lib/md/local-library'

vs

import { MdGroup, MdFavorite, MdStar, MdThumbsUpDown, MdLocalLibrary } from 'react-icons/md'

@antoinerousseau
Copy link
Collaborator

@kamijin-fanta any insight?

@kamijin-fanta
Copy link
Member

@wopian Please tell me the version of webpack.
I verified with webpack@3.8.1 / webpack@4.5.0.

If upgrade has no effect, please provide webpack.config.js.

@wopian
Copy link

wopian commented Aug 1, 2018

@sandeepreddy19
Copy link
Author

sandeepreddy19 commented Aug 1, 2018

@kamijin-fanta I am using the default webpack config provided by Create-React-App

@kamijin-fanta
Copy link
Member

kamijin-fanta commented Aug 2, 2018

@wopian I saw the configuration easily.

  • It is necessary to add '.mjs' to resolve.extensions
    • like: ['.mjs', '.js', '.jsx']
    • .js file is outputting commonjs. this is not optimized. should use .mjs files.
  • .babelrc

for additional debugging please submit the minimum project configuration.

@kamijin-fanta
Copy link
Member

@sandeepreddy19 I verified with react-script@1.1.4.
see: https://github.com/react-icons/react-icons/tree/master/packages/demo

please upload the smallest project including bug.

@wopian
Copy link

wopian commented Aug 2, 2018

Back down to 2kb (5 icons) after those changes 👍

@antoinerousseau
Copy link
Collaborator

antoinerousseau commented Aug 2, 2018

@kamijin-fanta many people use create-react-app without ejecting (see webpack default prod config). it would be nice if the new 3.x version would work out-of-the-box with that small footprint for those users. is that the case?

@kamijin-fanta
Copy link
Member

@antoinerousseau the size of the demo project is 37.84 KB in production build.
use three types of icon library: FaFolder, MdAccessibility, TiArrowDown.
not ejected.

demo project: https://github.com/react-icons/react-icons/tree/master/packages/demo

@markusenglund
Copy link

@kamijin-fanta I think the new build structure in 3.0 is pretty bad.

  1. In normal webpack setups (including creacte-react-app) it will cause a HUGE bundle size footprint, and some people won't have enough knowledge to realize what the problem is / how to fix it.
  2. The solution you propose is kind of hacky since it's based on the order of the extensions. So ['.mjs', '.js', '.jsx'] works, but ['.js', '.mjs', '.jsx'] does not.
  3. Since the solution is based on es modules, I believe it will not work at all in webpack 1.x (?)
  4. Even with the solution, the bundle size foot print is STILL bigger than before. Upgrading from 2.2 to 3.0 caused my bundle size to expand by 0.5 kb gzipped (+3.6 kb not gzipped). (The project used five different icons from fa)

All in all, a pretty big regression from 2.2. To fix it, I would start by renaming the .mjs file to index.esm.js or something like that and put a package.json file inside the fa-folder (and other such folders) and include "module": "index.esm.js" inside the file. This should cause webpack to find the right file by default.

@kamijin-fanta
Copy link
Member

@markusenglund thanks for the good feedback.

about 3, 4 you are right.
part 1 and 2 are also correct. project should prepare troubleshooting guide.

projects created with creacte-react-app should normally resolve .mjs first. In versions older than 1.0.15, the bundle size appears to be large.
ref: https://github.com/facebook/create-react-app/blob/v1.1.4/packages/react-scripts/config/webpack.config.dev.js#L93

the default setting of the latest webpack resolves .mjs first. https://webpack.js.org/configuration/resolve/#resolve-extensions

I think that problems are occurring when using old packages or wrong config overrides. The first problem is temporary.

@markusenglund
Copy link

Ah ok. Number 2. was kind of a nonsensical criticism then.

Still, I think we should strive to build npm packages that work great out of the box for everyone. The setup for this package is right now pretty atypical, so it's not surprising that some projects don't have their build tools properly set up for it.

@curran
Copy link
Contributor

curran commented Aug 14, 2018

I encountered this issue while using Next.js with default configuration.

Adding '.mjs' in the Webpack config (via next.config.js) solved the problem:

  webpack: config => {
    config.resolve.extensions = [ '.mjs', '.js', '.jsx', '.json' ];

@curran
Copy link
Contributor

curran commented Aug 14, 2018

Suggestion: Since this will be a common issue encountered for newcomers, it may be nice to link to this issue in the README where the ES6 imports are recommended. Something like this:

Ending up with a large JS bundle? Check out this issue.

Thoughts?

@SpicyPete
Copy link

SpicyPete commented Aug 22, 2018

Getting this issue with Gatsby v2.
There's a way to modify it's webpack. If I find a solution I'll update it here

@elramus
Copy link

elramus commented Aug 27, 2018

I'm having this issue using Laravel Mix's webpack config. I'm using just one icon and it's adding the entire font awesome library. I'd like to try your solution, @kamijin-fanta, but I'm not really sure how to go about it.

Mix lets you add webpack customizations like so:

mix.webpackConfig({
  plugins: [
    new BundleAnalyzerPlugin()
  ]
})

to which I added:

mix.webpackConfig({
  plugins: [
    new BundleAnalyzerPlugin()
  ],
  resolve: {
    extensions: [ '.mjs', '.js', '.jsx', '.json' ]
  }
})

but that didn't seem to fix it. I'm a bit of a webpack noob, so any pointers would be great. FWIW, I'm importing the icon like so: import { FaCamera } from 'react-icons/fa', and react-icon's index.js is coming out gzipped at 247k.

Thanks.

@Stalinko
Copy link

I have the same problem as @elramus
Standard installation of Laravel Mix with ReactJS 16.5
Installed latest React-Icons (3.1.0) and imported 3 icons + IconContext:

import { IconContext } from 'react-icons'
import { GoCalendar } from 'react-icons/go'
import { FaRegClock } from 'react-icons/fa'
import { FaMapMarkerAlt } from 'react-icons/fa'

And my compiled JS grew up by 900kb !

Solutions mentioned here don't help :(
was anybody able to make it work properly with Laravel Mix ?

@hoangvu12
Copy link

Why the bundle size is bigger when I changed to @react-icons/all-files.

@naingaungphyo
Copy link

naingaungphyo commented Jan 22, 2023

@IgnacioSuburuAssertia @hoangvu12
Import the icons like this!

For missing icons, wait for the maintainer to update the package for latest icons. No other workarounds :)

@hoangvu12
Copy link

@IgnacioSuburuAssertia @hoangvu12
Import the icons like this!

That's what I did, I got both 200kb of two type of imports.

@naingaungphyo
Copy link

naingaungphyo commented Jan 22, 2023

@hoangvu12
Did you clear the browser cache and try again? Or is that happening only in Dev Mode? How about in Prod Mode?

@hoangvu12
Copy link

@hoangvu12
Did you clear the browser cache and try again? Or is that happening only in Dev Mode? How about in Prod Mode?

I ran next/bundle-analyzer to see the result.

@naingaungphyo
Copy link

I think that there will be tree shaking with Production Build, depending on your bundler tho.

@naingaungphyo
Copy link

Also, lets wait for this happen :)
#634 (comment)

@Keshavdulal
Copy link

Faced the same issue with gatsby v5 with react-icons 4.4.0 i.e. ~97.9KiB unused bytes in bundle.

Tried adding extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx'] inside webpack config as suggested but didn't work.

  • installed @react-icons/all-files
  • replaced import { FiLogOut } from "react-icons/fi" with import { FiLogOut } from "@react-icons/all-files/fi/FiLogOut"
  • uninstalled react-icons
  • Bundle size reduced (still a long way to go)

Screen Shot 2023-02-07 at 9 22 18 PM

Ref - https://react-icons.github.io/react-icons/
Note - This method has the trade-off that it takes a long time to install the package. Suitable for MeteorJS, Gatsbyjs etc.

@DinsmoreDesign
Copy link

Just tried switching to @react-icons/all-files, but it doesn't include all the icons we're using on both our Webpack entry points, so that's out. Not sure what the solution is at this point for us. One of our entry points is only using 2 icons, but importing them adds an extra 1.9 MB onto our bundle size. My solution right now for that specific entry is to just not use the icons at all, but the bundle still seems super large on the other entry for what should be fairly small icons...

@jacobwgillespie
Copy link

It's probably a large lift for existing projects using React Icons, but if you're looking for an alternative you might be interested in unplugin-icons. It provides access to over 100 different icon packs by configuring your bundler to dynamically import only the icons you actually use, rather than relying on native tree-shaking. All the supported packs and icons can be seen at https://icones.js.org/.

This approach, or just copy-pasting the icons we actually use into an icons.tsx file in the repo, is what I've switched to after using / maintaining styled-icons. It can be surprisingly hard to get tree-shaking working, and Node SSR performance can break easily even if you do get client-side tree-shaking working.

@abhishekprajapati1
Copy link

So all of the stuff going on here, I decided to do some copycat. Let me explain:

  1. Find your desired icon on react-icons website copy its svg and make your own icon component files.
  2. before making a build try to minify each file [ though build gzipped every thing ] it is a great addition.

Actually it is not that bad because you will hardly use more than 20 - 25 icons per project.

@CRSylar
Copy link

CRSylar commented Mar 14, 2023

@abhi0661236 can't find the SVGs on react-icons website, maybe you're referring to heroIcons ?

@abhishekprajapati1
Copy link

abhishekprajapati1 commented Mar 14, 2023

@CRSylar No I am talking about the react-icons webpage itself. just inspect and copy from markup :)

@Jucabel
Copy link

Jucabel commented Mar 31, 2023

I am using react-icons@4.8.0

I saw that in dev mode (Chrome Dev Tools/Network Tab), all the library is loaded in loaded (almost 2.2mb) but when I pass to production (Analyzed with source-map-explorer) the react-icons size inside de vendor chunk is just 4.2kb, so it appears to be fixed.

I have to add that I am using Vite@4.2.1 & React 18.2.0, maybe The bundling process and dep optimization of vite has something to do with it.

@calvincchong
Copy link

I am having the same issue with Next.js, and Vercel deployment. However, this is only occuring with one specific icon import, whics the io5 folder.

import { IoBagAdd, IoAddCircleSharp } from 'react-icons/io5'; 

adds the entire io5 folder and 200 kb. Might possibly remove the icon at this point unless there's a quick fix.

Screenshot 2023-04-27 at 11 26 24 AM

oztek22 added a commit to oztek22/react-icons that referenced this issue May 4, 2023
When someone imports files from this library by using import statement, it will automatically use `index.esm.js` file without specifying `type: module` in index.js.

Currently typescript complains about the type If you directly import esm files which can be solved by specifying types.

should also resolve issue react-icons#154 without using all-files
oztek22 added a commit to oztek22/react-icons that referenced this issue May 4, 2023
This PR should resolve tree shaking issue mentioned in react-icons#154 without using all-files.

It also resolves typescript issue when you try to import esm file directly.
@andrei10k
Copy link

andrei10k commented Aug 1, 2023

Hey! I managed to fix the big bundle size. In my case the problem was that inside my babel.config.js i had "@babel/plugin-transform-modules-commonjs" plugin. that transformed my es2015 modules into commonjs modules, and webpack's tree shaking fails with commonjs modules as you can read in their docs:

https://webpack.js.org/guides/tree-shaking/: "Ensure no compilers transform your ES2015 module syntax into CommonJS modules (this is the default behavior of the popular Babel preset @babel/preset-env - see the documentation for more details)."

basically in your babel.config.js you have to add "modules": false in your preset-env and make sure you or another compiler don't transform the modules to commonjs. I'm attaching before and after screenshots. it also works with the latest version to date 4.10.1. hope this helps someone

image

Screenshot 2023-08-01 at 13 32 10

disclaimer: first screenshot had a different version. the second was for 4.10.1. that's why the different stat sizes

@laith00x
Copy link

Still having the same problem in 2024, this approach works for me, just add /index.esm.js at the end of your imports.

import { HiClock } from "react-icons/hi/index.esm.js";

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.