


Quick Optimization for your ReactJS Application for Performance and Size
React being massively used for frontend-intensive applications comes with its unique ways of performance and size optimizations. Improving both will have a considerable measurable impact on the React package bundle size. The lower the bundle size, the faster the loading time, considering that we are focusing on client-rendered applications.
Server-side rendering would further improve load time. In server-side rendering when a user requests a web page, the React components are rendered as HTML code in the server itself. Then this pre-rendered page is sent to the browser, allowing the user to see the page immediately without the overhead of the JS loading time.
But that’s a different story altogether. Let’s mainly focus on trying to improve our client-side rendered site by working on improving the Package bundle size by making tweaks in the code. Let’s dive deep.
1. Code Splitting and Dynamic Imports
“Bundling” of React code is the process of following through all imports and codes and combining it into a single file called a ‘Bundle’. Webpack, Browserify, etc., already do this for us.
Webpack has a feature called ‘Code Splitting’ that is responsible for splitting a single bundle into smaller chunks, deduplicating the chunks, and importing them ‘on demand’. This significantly impacts the load time of the application.
module.exports = { // Other webpack configuration options... optimization: { splitChunks: { chunks: 'all', // Options: 'initial', 'async', 'all' minSize: 10000, // Minimum size, in bytes, for a chunk to be generated maxSize: 0, // Maximum size, in bytes, for a chunk to be generated minChunks: 1, // Minimum number of chunks that must share a module before splitting maxAsyncRequests: 30, // Maximum number of parallel requests when on-demand loading maxInitialRequests: 30, // Maximum number of parallel requests at an entry point automaticNameDelimiter: '~', // Delimiter for generated names cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
Lazy Loading Components with React Suspense (React 18): This combined with dynamic imports will show a visible improvement in Component Loading time.
Generally, when we import child components within a parent component, we import it statically. To prevent importing this component till we actually have to render it, we can use a combination of dynamic imports with React Suspense. React Suspense enables loading a component on demand. It shows a Fallback UI while the corresponding components are dynamically imported and then rendered.
import { lazy } from 'react'; // The lazy loaded Component has to be exported as default const BlogSection = lazy(() => import('./BlogSection.tsx')); export default function HomePage() { return ( <> <Suspense fallback={<Loading />}> <BlogSection /> </Suspense> </> ); } function Loading() { return <h2>Component is Loading...</h2>; }
2. Tree Shaking
This is a technique used by JavaScript bundlers to remove all unused code before creating bundles. ES6 code can be tree-shaken; however, code that is based out of CommonJS (i.e., uses ‘require’) cannot be tree-shaken.
Webpack Bundle Analyzer is a plugin that will help you visualize the size of a webpack with an interactive map.
npm install --save-dev webpack-bundle-analyzer npm install -g source-map-explorer
Then configure your webpack to add the above as a plugin:
plugins: [ new BundleAnalyzerPlugin(), new HtmlWebpackPlugin({ template: './public/index.html', // Path to your HTML template filename: 'index.html', // Output HTML file name inject: true, // Inject all assets into the body }), ];
Make sure your script is configured to run Webpack:
"build": "webpack --config webpack.config.js --mode production"
Run yarn build to generate a report.html that will help you visualize your bundle size effectively.
It will look something like this:
3. Concurrent Rendering
Let’s start by understanding what Blocking Rendering is. Blocking rendering is when the main thread (UX updates) is blocked because React was doing some less important tasks in the background. This used to be the case till React 16.
React 18 has introduced concurrent features, which means it will:
- Give you more control around how background updates get scheduled and will create a smooth end-user experience by not blocking the main thread.
- Initiate automatic batching of state updates: Batching refers to grouping multiple re-renders due to multiple state updates in a way that the state updates just once.
Use the startTransition() hook to manage React updates as non-urgent, helping React prioritize urgent updates like user-input and user-interaction with components over the prior.
module.exports = { // Other webpack configuration options... optimization: { splitChunks: { chunks: 'all', // Options: 'initial', 'async', 'all' minSize: 10000, // Minimum size, in bytes, for a chunk to be generated maxSize: 0, // Maximum size, in bytes, for a chunk to be generated minChunks: 1, // Minimum number of chunks that must share a module before splitting maxAsyncRequests: 30, // Maximum number of parallel requests when on-demand loading maxInitialRequests: 30, // Maximum number of parallel requests at an entry point automaticNameDelimiter: '~', // Delimiter for generated names cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
In this example, when the input value changes, the handleChange function is called. The startTransition function is used to mark the update to the list state as non-urgent. This allows React to prioritize the update to the value state, ensuring that the input remains responsive even when the list is large.
Use the useDeferredValue hook to defer a value (usually an expensive calculation) until the UI is less busy.
import { lazy } from 'react'; // The lazy loaded Component has to be exported as default const BlogSection = lazy(() => import('./BlogSection.tsx')); export default function HomePage() { return ( <> <Suspense fallback={<Loading />}> <BlogSection /> </Suspense> </> ); } function Loading() { return <h2>Component is Loading...</h2>; }
In this example, the useDeferredValue hook is used to defer the value state until the UI is less busy. This helps keep the input responsive by deferring the rendering of the large list until after the input update is processed.
Key Benefits of Concurrent Rendering:
- Improved Responsiveness: By allowing React to interrupt rendering work, the UI remains responsive to user interactions.
- Prioritization: React can prioritize urgent updates over non-urgent ones, ensuring a smoother user experience.
- Better Performance: Expensive updates can be deferred, reducing the impact on the main thread and improving the app’s overall performance.
4. Support Pre-loading of Resources (React 19)
If you are aware of any heavy resources that your application would be fetching during loading, then a good idea would be to preload the resource. These resources could be fonts, images, stylesheets, etc.
Scenarios where preloading would be beneficial:
- A child component would use a resource. In that case, you can preload it during the rendering stage of the parent component.
- Preload it within an event handler, which redirects to a page/component that would be using this resource. This is, in fact, a better option than preloading it during rendering.
module.exports = { // Other webpack configuration options... optimization: { splitChunks: { chunks: 'all', // Options: 'initial', 'async', 'all' minSize: 10000, // Minimum size, in bytes, for a chunk to be generated maxSize: 0, // Maximum size, in bytes, for a chunk to be generated minChunks: 1, // Minimum number of chunks that must share a module before splitting maxAsyncRequests: 30, // Maximum number of parallel requests when on-demand loading maxInitialRequests: 30, // Maximum number of parallel requests at an entry point automaticNameDelimiter: '~', // Delimiter for generated names cacheGroups: { defaultVendors: { test: /[\/]node_modules[\/]/, priority: -10, reuseExistingChunk: true, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
Interesting fact: After implementing preloading, many sites, including Shopify, Financial Times, and Treebo, saw 1-second improvements in user-centric metrics such as Time to Interactive and User Perceived Latency.
Please leave a feedback <3
I hope you found this blog helpful! Your feedback is invaluable to me , so please leave your thoughts and suggestions in the comments below.
Feel free to connect with me on LinkedIn for more insights and updates. Let's stay connected and continue to learn and grow together!
The above is the detailed content of Quick Optimization for your ReactJS Application for Performance and Size. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

JavaScript is the cornerstone of modern web development, and its main functions include event-driven programming, dynamic content generation and asynchronous programming. 1) Event-driven programming allows web pages to change dynamically according to user operations. 2) Dynamic content generation allows page content to be adjusted according to conditions. 3) Asynchronous programming ensures that the user interface is not blocked. JavaScript is widely used in web interaction, single-page application and server-side development, greatly improving the flexibility of user experience and cross-platform development.

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

How to merge array elements with the same ID into one object in JavaScript? When processing data, we often encounter the need to have the same ID...

Learning JavaScript is not difficult, but it is challenging. 1) Understand basic concepts such as variables, data types, functions, etc. 2) Master asynchronous programming and implement it through event loops. 3) Use DOM operations and Promise to handle asynchronous requests. 4) Avoid common mistakes and use debugging techniques. 5) Optimize performance and follow best practices.

Discussion on the realization of parallax scrolling and element animation effects in this article will explore how to achieve similar to Shiseido official website (https://www.shiseido.co.jp/sb/wonderland/)...

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

In-depth discussion of the root causes of the difference in console.log output. This article will analyze the differences in the output results of console.log function in a piece of code and explain the reasons behind it. �...
