A brain dump of things you can do to load React apps faster
A brain dump of things you can do to load React apps faster
This post covers the breadth of tools, options, plugins, presets and settings I use when working on improving performance of React web apps. I had these noted down as rough notes on my local system and decided to convert them into a blog post to bring more clarity to the notes (and my understanding). I also hope these will be of some use to someone trying to improve front-end performance for their React web app:
Where to start
Avoid starting without having a good look at these three things:
Know the amount of JS that loads on opening your top entry routes through browser's devtools. And, know what constitutes these bundles through Webpack bundle analyzer. Keep tracking these as you optimize.
Peek into Webpack Bundle Analyzer for low hanging fruits
Start by looking into webpack bundle analyzer for some quick opportunities to reduce the bundle size:
// within webpack.config.js
module.exports = {
resolve: {
alias: {
'lodash-es': 'lodash',
},
},
};
// refer all lodash imports to the lodash instance at node_modules/lodash
module.exports = {
resolve: {
alias: {
lodash: path.resolve(__dirname, 'node_modules/lodash'),
},
},
};
//within .babelrc or package.json "babel" config
{
"presets": [
"next/babel"
],
"plugins": [
["transform-imports", {
"material-ui": {
"transform": "material-ui/${member}",
"preventFullImport": true
}
}]
]
}
Uncover code splitting opportunities
This refers to setting up your code in a way that webpack can split it into various bundles in an optimal manner. For code splitting opportunities, look for conditional rendering of stuff:
import ProfileComponent from 'Component/ProfileComponent';
...
...
export class InfoView extends React.Component {
...
...
render() {
...
return (
{showProfileComponent ? (<ProfileComponent />) : null }
);
}
In the code snippet above, the ProfileComponent shall only be visible in some circumstances, but will be loaded with InfoView JS bundle every time. This can be optimized to load conditionally through React lazy or loadable-components :
import React, { lazy, Suspense } from 'react';
....
const ProfileComponent = lazy(() => import('Component/ProfileComponent'));
...
...
export class InfoView extends React.Component {
...
...
render() {
...
return (
{showProfileComponent ? (<Suspense fallback={<div />}><ProfileComponent /></Suspense>) : null }
);
}
When code splitting a , be aware of the following caveats:
Setup vendor bundle for caching benefits
Having a separate vendor bundle can help get caching benefits because this bundle is expected to change less frequently. Webpack 4 provides SplitChunksPlugin (and CommonsChunkPlugin for earlier Webpack versions) to setup creation of vendor bundle during build process. That being stated, it is critical to ensure this is setup efficiently for maximum benefits:
Reduce core-js size with efficient babel transpilation
Babel's preset-env allows you to specify the target browser environments and includes transpiled version of your code only for those environments. You can use this to ignore very old browsers - this shall reduce the size of your bundle. This preset also provides useBuiltIns option. When set to 'usage' (experimental), babel adds specific imports for polyfills only when they are used. This helps reduce the size of your initial bundle.
Conclusion
Improving your React web app's performance can be complex. You can make this exercise effective by constantly tracking the JS sizes for your top entry routes through browser devtools and webpack bundle analyzer. Also, being aware of the wide number of options in improving the performance helps one uncover the top-most optimizations quickly.
Also Read