Code Splitting in React
When building a large website with a lot of third-party libraries and multiple react components, the code of the project gets larger. During the loading of the website in the browser, all the code in the project will be combined to form a bundle using tools like Rollup, Webpack, or Browserify and loaded into browsers.
We may not need all the components of a page that has been bundled together at a time and the website takes a lot of time to load if the bundle is very large, therefore to prevent such large bundles of code, we can split the code into multiple bundles and load them dynamically whenever the component is needed.
What is Code Splitting in React?
React code splitting is a feature that allows us to split the code into different bundles and load them to the browser dynamically on whenever needed basis.
Bundling is the process of merging multiple files into a single file or bundle before loading the file to the browser. Bundling is a little complex and is usually done by tools like Webpack, Rollup, or Browserify.
Bundling collects all the code imported from different files and creates a bundle that has all the code in one place for the browser. If you are using webpack as your bundling option, you can configure bundling properties in the webpack.config.js file.
- Bundling tools like Webpack usually have an entry point from which Webpack will treat every import statement as a dependency and build a dependency graph that records all the code or modules that are required for the application to run.
- The bundler is specified using the module option and rules are used to specify the files and loaders.
- The output is used to specify the path and filename to which the generated bundle must be stored.
- The test parameter is used to specify the type of files that should be processed and the use parameter is used to specify the type of bundler to be used.
Let us consider the following file with code for a button that is to be displayed on the center of the website,
Let us consider the main file in which the above component has to be rendered,
The above file imports the Button from the button.jsx file and renders it inside a div component. A bundle that has the App.jsx as an entry point will see the import and add the file to its dependency tree. A sample bundle will be like the following file,
The above file is a standard example of a bundle of files that will be used in the code splitting react app. So when we use multiple imports and third-party libraries, the bundle will grow larger.
When to Use Code Splitting in React?
Code Splitting React applications can be used during the need for the following:
- To improve the performance of the application. Smaller bundles load faster in the browser.
- When there is a memory constraint in the server and to reduce the usage of memory in servers.
- When there are multiple views of the application and code can be loaded dynamically when a user goes to another view.
- When the next action of the user is known before, we can load code after a certain action.
- To load components during the transition of pages while changing routes dynamically.
React Code Splitting Using Import
Dynamic import statements can be used to create code-splitting react applications. Normally we can import components from other components using two syntaxes based on the type of export. If the component has a normal export, we can use the following syntax,
For components use default export using the default keyword. We can use the following syntax,
It is important to note that, the above syntax must be used when using dynamic imports.
Note: Refer to the Splitting Named Exports on ways to optimize the way of using default exports.
These kinds of imports are immediately added to the dependency graph of the bundle and will be made into a bundle as soon as the file is loaded. To prevent bundling at an initial stage, we can use the dynamic import syntax in a code-splitting react application,
The webpack will understand this syntax and performs react code splitting. This dynamic import returns a promise that can be handled using the then function. This dynamic import can be used on both client-side and server-side rendering.
We can also manually perform react code splitting by providing multiple entry points in the webpack.config.js file that configures the webpack. Every entry module in Webpack has a bundle and also stores all the components or modules used by the entry file.
The dependsOn option can be used to allow sharing of modules bundled in one entry point to other entry points.
The following file illustrates the above configuration,
- The import specifies the file that will act as an entry point for the building of the dependency graph.
- The dependOn option specifies a name that will declare the modules or libraries that will be shared with other entry points.
- In our above example, the shared includes the libraries React, React-dom, and Material UI. When Webpack sees these libraries imported, it will not add them to the bundle.
We can also use the SplitChunksPlugin of Webpack to implement code splitting. A bundle is made of multiple chunks and CommonsChunkPlugin prevents multiple dependencies in these chunks.
React.lazy and Suspense
We can use the React.lazy() method to create components that can be dynamically loaded into our code-splitting React application. The component imported using the React.lazy() should be rendered inside a React.Suspense component that has features to show fallback content like a loading image and prevent the rendering of other elements during the importing of the component. The lazy() function will return a promise which will only be loaded when the page is rendered.
The above syntax shows a normal import statement.
We can import multiple components using the React.lazy() function and render them all together inside a Suspense component.
- The component that should be shown during the loading of the dynamic component should be specified in the fallback prop in the Suspense.
- The Button component is loaded dynamically and is not available immediately to the App component, but during that time the Suspense prevent the rendering of the Button component and shows the component provided in the feedback prop.
React Code Splitting: Error Boundaries
Error boundary is a components that should be placed at a higher hierarchical level in a code splitting react app and catches errors in rendering and lifecycle methods that occur in its child components, and print those errors in the console. In normal cases, an error will in the application will be displayed on the screen, but when using error boundaries, a fallback UI can be displayed as an error page in case of an error.
An error boundary can be created using the static getDerivedStateFromError() function or the componentDidCatch() function of the react lifecycle.
The static getDerivedStateFromError() is called in the rendering phase when there is an error in the rendering stage of any children components. When creating error boundaries, a fallback UI is displayed using the function. The function takes the error as its parameter.
The componentDidCatch() function is called in the commit phase when there is an error in the rendering stage in the lifecycle of children components. When creating error boundaries, the error is logged into the console using this function. The function takes the cached error and the information or the componentStack trace of the component that has thrown the error.
The following code shows a simple Error Boundary,
The error state is used to check if there is an error in the application. If there is no error, the child components are rendered.
The getDerivedStateFromError modifies the state of the component when there is an error in any of the children's components.
Now, let us use the error boundary with the dynamic loading component in a code splitting react app. We can render the error boundary at a top level to catch errors in the dynamic component,
Route Based Code Splitting in React
Code splitting react apps that uses dynamic imports takes time to load, which can affect user experience. Therefore, we can introduce code splitting in routes and load custom transitions in Suspense components to give a better user experience.
- We use react-router-dom to make routes in any code splitting react app. The router is a high-level component.
- We render the Routes component inside React's Suspense component to provide dynamic routes.
- The elements specified in the Route will load dynamically and the Loading component will be displayed till the element is loaded.
React Code Splitting Named Exports
React lazy function can only be used to import components that use default export in a code splitting react app. If we want to import components that use named exports, then the best way is to create another file that imports these named exports and reexport them as default components.
Consider a file, component.jsx with a named export,
The following example shows the re-exporting of components with default exports in a code-splitting react application,
Then we can import the Sample component from the defaults.jsx and perform a dynamic import.
Q. How to resolve errors in the screen when using React.lazy() to load dynamic components?
A. There are multiple reasons and corresponding fixes for this error in a code-splitting react app, check if the dynamic component is within a Suspense component.
Dynamic components are not loaded immediately, so there is a need to render them inside the Suspense component. Implement your code inside a high-level error boundary.
Q. How to fix the 'Error: ChunkLoadError: Loading chunk 0 failed.' error?
A. Check the network connection in your code-splitting react application. If the above method doesn't work, we can make automated retries to load the dynamic component in webpack using the webpack-retry-chunk-load-plugin library. Install the above library using npm or yarn.
Implement the webpack.config.js just like the below configuration.
- Code Splitting in React can be used to split the code into different bundles and load them to the browser.
- Code Splitting React apps have greater performance due to the reduction of the size of the bundle to be loaded.
- Bundling tools like webpack are used to combine all the code in different files before loading to the browser in a code-splitting react application. In Webpack, can configure bundling properties in the webpack.config.js file.
- Dynamic imports can be used to import components dynamically in react code splitting.
- React code splitting provides with lazy() function and a Suspense component to handle the dynamic loading of components.
- Error Boundaries can be implemented in react code splitting applications to catch errors in dynamic loading components and display an error page.
- Only default exports can be used along with dynamic loading in react code splitting. Therefore, we can re-export named exports as default exports in a separate file.