React root.js weights about 9MB - reactjs

Ok, so... I have this project where we are using a lot of components (as usual in every React project) but when we compile the project to see it in the browser (ie. foreman start) it takes a lot of time to load and also when it loads it creates a file that is very very large.
We don't know why this is happening, probably something that we messed up and we don't know yet.
I don't know which part of code you need to see to help me understand why this is happening. Let me know and I will give it to you.
Also, I wanna know if there is a way to prevent that file to be that large, as long as I know it should weight no more than 2Mb or something...
Thanks in advance!

The typical reason for such issues is not the amount of components you have made but rather the libraries you use. You can check what is the cause for a large bundle by first running
webpack --json > stats.json
and then installing and running webpack bundle analyzer
webpack-bundle-analyzer stats.json
After this you need to start working on fixing the cause of the large size.
Normally that would depend on what the reason for large bundle size is..but the following methods will definitely help.
code splitting for react
code splitting for webpack
Using webpack's optimizations
And, since sometimes tree-shaking doesn't work as well as it is expected to..you could change your imports from the style of
import {x, y} from 'library';
to
import x from 'library/x';
import y from 'library/y';
Which would ensure that if there are 10 exports from the library, then all of them dont get loaded... Only those that are needed do. For example, if you are using lodash,
import {debounce} from 'lodash';
will import the entire lodash library while
import debounce from 'lodash/debounce';
will only import that particular file.
There are other ways to optimize your output (like webpack externals) but that is dependent on what is actually causing the issue.
NOTE A lot of this answer assumes you are using webpack to bundle code. However if that is not the case you will need to search out optimization and bundle analyzed for the specific bundling tool you are using

Related

I could save about 20kb if my webpack configuration didnt use long WEBPACK_IMPORTED_MODULE names for modules. But how to shorten it?

I'm working on a React project using babel '#babel/preset-env' & '#babel/preset-react' and trying to optimise my output file with Terser plugin too.
After reading docs here there and everywhere I cannot for the love of me figure out how to shorten these names __WEBPACK_IMPORTED_MODULE__ __webpack_require__ etc. Why cant they be shorter?!
I believe I've followed tree shaking protocols making sure I'm using import { function } instead of import Everything and even looked at webpacks' optimization.moduleIds to see if that would help but no avail.
Any suggestions on how I can minimise the footprint of webpack in this production build please?

How to load .web extenstion files in React Native Web with Typescript

In the case of react native web we have a possibility to use files with .web and .android extensions.
Eg.
myFile.web.js
myFile.android.js
then we can include them via
import myFile from './myFile';
and React native web automatically provides proper file content depends on the platform.
It works so far but after I added Typescript the ts compiler started to complain about the missing module 'myFile' and it's logically okay because we don't have this file and TS compiler doesn't know that the RNWeb will automatically pick a proper file later.
When I disabling Typescript, everything works fine so the system is working.
The question is how to solve it in the case of Typescript?
Thanks for any help.
The only way I found how to avoid this issue is using CommonJS module system - require instead of ES6 - import standard
Example: const MyFile = require('./myFile')
In this case, the TS compiler will ignore it. Unfortunately, it isn't a perfect/right solution as I'd like to see but it works so I just use it as is.
P.S. If someone finds another way, please, provide your solution, I'll be appreciated.

How to remove dead code in Create React App

I have a create-react-app project, and I am working on reducing my bundled JS file size. About half of my bundle size is coming from a dependency called MDBReact (a react component library), and majority of it is not being used. I am trying to find out how/if I can remove dead code with tree shaking from the bundled build. I have been looking into this for a while and the closest article I found was this. This article leaves me confused and it does not give any explanation into how or if it can be done. I also found this guide on webpack tree shaking explaining how it can be done, but this does not seem to solve the problem.
CRA is using webpack to bundle code. Webpack can only treeshake es modules by default and commonjs modules when using plugins.
To help you on the way, how are you currently importing from MDBReact?
It looks like MDBReact is not written in es modules and webpack is therefore going to have a hard time tree shaking if you use the following import statement:
import { module } from 'MDBReact';
Instead you could try to import using the following
import modules from 'MDBReact/module';
You might have to change the path to the module depending on how MDBReact is structured. Take a look in the node_modules folder to find out.

Redux + React understanding size of webpack bundle

I read various answers like this regarding reducing the bundle size. First I wanted to understand what is going on with my 13MB bundle, so I've installed the Webpack Bundle Size Analyzer. It generated this output:
There are a few things I don't understand:
Why is react appearing twice with two different sizes?
How come it doesn't add up to 13MB? (it's around 4.75MB)
Does this means my own code is only 4KB? (last line)
Is it possible to understand from this tree how to save KBs? I mean, for instance, is there a way to use only parts of lodash or is it required as a whole by React?
Update:
Found the answer for #1. React-color requires ReactCSS which requires a different version of react and lodash. Without React-color my bundle dropped from 13MB to 8MB. I will try to find a way to re-use react and lodash.
It seems that you have eval-source-map devtool option in your webpack config file, that's why you are getting such huge bundle size. This way, sourcemaps are putting inside of bundle js file.
Try to change this option to source-map to build source maps separately.
// webpack.config.js
{
devtool: 'source-map',
// ... other options
}
1) Sometimes other dependencies require again lodash and / or react, so these dependencies are pulled in multiple times by webpack (usually happens when the version differs), here the DedupePlugin should help. The final bundle size also depends on your devtool entry in webpack, so in development it is usually much bigger as you probably have sourcemaps enabled and a your build is not optimized. Hard to tell without your actual webpack config.
2) Maybe webpack is already deduping?
3) last line says 400KB
4) You can definitely save a few kbs. A good way to start is using lodash-webpack-plugin with babel-plugin-lodash, this will import only the lodash methods you are actually using instead of the complete library. You can also just require the bits you need from material-ui as outlined in this answer.
I recently added the webpack-dashboard to my webpack config, so I instantly see the output and percentages that make up my bundle size, so maybe you think twice about adding huge dependencies if you don't really need them.

React components large size

Is it normal to have over 700kB in file size for a react component?
This is the file size after compilation.
GridComponent.js 732 kB 0 [emitted] GridComponent
main.js 7.97 kB 1 [emitted] main
GridComponent is the react component. main is normal js for comparison.
Is that normal?
I plan to only include react components in pages that requires them.
I can see that you're using webpack in your app, and your GridComponent.js should have something like require('react'); (or import React from 'react';, if using ES6 modules with babel).
When you require things, webpack will "join" all your dependencies in the specified "output" settings (provided in webpack.config.js). So, if you check the contents of GridComponent.js you'll see that React is inside. In your case, this GridComponent.js is your "bundled file" (it will contain all the dependencies that you've imported). That's why it seems to be "large", because this file contains your component and React itself (and other dependencies as well).
When you say "I plan to only include react components in pages that requires them.", I think you may want to split your code, so your page will only load the things you need. You can check more info about code splitting here:
https://webpack.github.io/docs/code-splitting.html
A basic "splitting" strategy would be to split your "vendor" code from your "app" code (https://webpack.github.io/docs/code-splitting.html#split-app-and-vendor-code). In your case, React, React DOM and other "common" dependencies would go to "vendor", and your app is the code you've written.
But just as tip, code splitting is only really needed when you have lots of code. Because sometimes an extra network request may introduce more "latency" than downloading a few more bytes. Or if you have some "special" caching strategy, since your app may change more times than your vendor code (your vendor code will only be downloaded again when some dependency version is changed), and you avoid downloading lots of bytes when a simple thing is changed in your app.
I think this solves your question, but to add more information here, if you want to distribute your code to more people (i.e. an open source project), you may distribute your code and say "ok, to run that, you must install that other dependency", and you can achieve that with peer dependencies.
If peer dependencies is not your case, you can save some bytes by minifying your file (you can do that by modifying your webpack configuration). A good blog post talking about that can be found here:
http://moduscreate.com/optimizing-react-es6-webpack-production-build/

Resources