Closed sandeepreddy19 closed 3 years ago
I have the same issue
@JaccoGoris Did you find any fix for this issue?
@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 😄
@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
Should be better in 3.x with #141
I have the same problem with react-icons 3.0.1
import { <icon> } from 'react-icons/md'
is now 350kbimport 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'
@kamijin-fanta any insight?
@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.
@kamijin-fanta 4.16.3
Config: https://github.com/wopian/kitsu-season-trends/blob/master/webpack.production.config.js
@kamijin-fanta I am using the default webpack config provided by Create-React-App
@wopian I saw the configuration easily.
['.mjs', '.js', '.jsx']
.js
file is outputting commonjs. this is not optimized. should use .mjs files."modules ": false
to preset env https://babeljs.io/docs/en/babel-preset-env/#modulesreact-hot-loader/babel
)for additional debugging please submit the minimum project configuration.
@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.
Back down to 2kb (5 icons) after those changes 👍
@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?
@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
@kamijin-fanta I think the new build structure in 3.0 is pretty bad.
['.mjs', '.js', '.jsx']
works, but ['.js', '.mjs', '.jsx']
does not.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.
@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.
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.
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' ];
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?
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
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.
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 ?
@Stalinko I ended up switching over to React FontAwesome, because React Icons only carries a subset of FontAwesome's icons. Had a tree-shaking issue there too actually, but was able to resolve and it works great now.
.mjs
is now being abandoned anyway: https://github.com/facebook/create-react-app/issues/5103
won't this create issues then with the current setup?
Are there any plans to get compatibility with create-react-app (2.x) back on track?
What should I do to obtain compatibility?
I am considering changing the extension. Tools such as Jest do not support to ES Modules, so need to deal with both ...
.mjs
-> .js
.js
-> .cjs
Looks like they added .mjs support back !! https://github.com/facebook/create-react-app/releases/tag/v2.0.4
I'm currently using TypeScript with a target version of es5 and because of this tree shaking is not working with Webpack since it relies on the es6 module syntax. With 3.x of React Icons this leads to the entire icon library to be included in my output bundle.
The only workaround I've found for this problem is to declare all the icons I'm using in my own module that I then use instead of importing the icons directly from the library. Something like this:
import { GenIcon, IconBaseProps } from 'react-icons/lib/iconBase';
export function MdPriorityHigh(props: IconBaseProps): JSX.Element {
return GenIcon({'tag':'svg','attr':{'viewBox':'0 0 24 24'},'child':[{'tag':'circle','attr':{'cx':'12','cy':'19','r':'2'}},{'tag':'path','attr':{'d':'M10 3h4v12h-4z'}}]} as any)(props);
}
Does anyone know if there's a better way of doing this? Is there any way to just import a single icon with require like there was in 2.x?
When building with parcel (v1.10.3) instead of webpack, react-icons is included completely, resulting in a huge bundle size.
There is no option is parcel to change the extension resolve order. I think js
has precedence over mjs
.
Is anyone experiencing the same problem? Or could someone give any hints on how to solve this problem?
@marlonbaeten It might be solved with the this code...
import { FaBeer } from 'react-icons/fa/index.mjs';
but, It is not good-looking.
@marlonbaeten there is an open issue tracking that problem 👌 https://github.com/parcel-bundler/parcel/issues/2238
@jgidlow
I'm a bit late to the tree shaking party here but I thought I'd leave a potential solution for others to see.
I'm also using TypeScript with a target of es5, with react-icons 3.2.2, and I have tree shaking working properly with webpack.
What worked for me was setting "module" to "es6" in my tsconfig.json. I had it set to "commonjs" before. If that's an option for you, tree shaking should work.
tsconfig.json
{
...
"compilerOptions": {
...
"module": "es6"
....
}
}
so, shall we keep .mjs or shall we make a more universally compatible v4 of this lib?
universally compatible sounds good 👍
import { FaTimes } from 'react-icons/fa/index.mjs';
Results in the error:
Can't import the named export 'GenIcon' from non EcmaScript module (only default export is available)
Edit: This comment helped me avoid the error: https://github.com/react-icons/react-icons/issues/193#issuecomment-428871071
import { FaTimes } from 'react-icons/fa/index.mjs';
doesn't seem to work :\
// webpack.config.js...
extensions: ['.mjs', '.web.js', '.js', '.json', '.web.jsx', '.jsx'],
alias: {
shared: resolve(__dirname, 'src/shared'),
}....
Error:
Unexpected use of file extension "mjs" for "react-icons/fa/index.mjs" import/extensions
"react-icons": "^3.3.0", "webpack": "^4.23.1",
can we please go back to being able to cherry-pick? relying on treeshaking is haphazard and inconsistent. It's an optimization not something that we should be relying on as the main strategy for including what we use. Not to mention that mjs
support is very inconsistent and it's implementation and behavior is still actively changing in tools
@mustafawm can you copy your entire Webpack config into a Gist?
Also, it looks like I used this code in the end along with the Webpack changes: import { FaTimes } from 'react-icons/fa';
- There's a pretty good chance that should work.
Hi @Slapbox, here it is https://gist.github.com/mustafawm/45e37b8d137fb09d10d3ccb51a609f70
Could it be the same webpack issue that fontawesome-react has? https://fontawesome.com/how-to-use/with-the-api/other/tree-shaking#issues
I switched to fontawesome which ironically had the same issue, but the workaround suggested in the link above worked.
@mustafawm did you get it working? I'm not entirely clear since that last bit is in a blockquote. If so which workaround on that page helped you? Point 1, Using deep imports?
My Webpack config looks very similar, but I've got this line which may make a difference:
resolve: {
extensions: ['.mjs', '.js', '.jsx', '.json'],
modules: [cwd, 'node_modules'], // This line might be necessary, but I think this is probably unrelated
},
I got fontawesome to work (by deep importing each icon)
Will try your suggestion and get back to you
@Slapbox no success, still importing the whole thing! (even with importing from index.mjs
)
PS: in your webpack config you have
cwd
as a variable!? Webpack complains as it only expects strings in its resolve.modules array so I changed it to 'cwd'
@mustafawm sorry! Instead of cwd
use process.cwd()
- doubt it helps, but that's what I should have said in the first place.
Tried that as well, still didn't work!
✖ 「wds」: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.resolve.modules[0] should be a string.
-> A non-empty string
You should get the same error if you're running the same webpack v
"webpack": "^4.23.1",
@mustafawm I'm on 4.28.3
in case that makes any difference. Still though, process.cwd()
should be a non-empty string, so I'm not sure why you'd be seeing that error. If you console.log(process.cwd())
at the top of your configuration what's that spit out?
This thread has many different things going on.
What is the best way to import and cherry pick specific icons on the current version without growing your bundle size by basically importing the entire libraries?
@Crizzooo the entire thread is just trying to accomplish that. Wish it was as easy as telling you the best way. Have you tried the recommendations found above? There's at least 3 different methods to try if I recall. The one I posted works for me.
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'