Written by Njong Emy✏️
In the world of software development, performance is a crucial metric. How can an application serve and execute multiple requests, without sacrificing performance? It is important to note that performance depends on how data is accessed. If an application needs to access heavy amounts of data, this may affect load times, hence performance. This doesn't stop certain applications from handling large amounts of data without sacrificing the speed at which they relay the data between the client and server.
In this article, we’ll explore two easy techniques for accessing data: lazy loading and error loading. With each method, we’ll see use cases and advantages and also how these techniques can be implemented in a single-page application (SPA) framework such as React.
What is lazy loading?
Lazy loading is a data-accessing technique whereby resources are loaded only when needed. Resources in this case include videos, images, scripts, or components. If you were scrolling on a webpage, for example, an image on that page would only load once you scroll to it.
Lazy loading is a good way of improving user experience and performance because queries made to the server are kept minimal, and the application only focuses on running operations that are needed at that moment.
Benefits of lazy loading
- Faster load times: Because the fetching and loading of resources are being prioritized, when a page loads for the first time, the initial load time is much faster
- Improved user experience: Imagine opening up a webpage and waiting for up to a minute for the page to completely load. With resources being loaded only when they are required, this problem can easily be avoided. Lazy loading reduces wait time, thereby increasing customer satisfaction
- Reduction in bandwidth usage: Bandwidth is the amount of data that is being transferred between the client and the server per second. With lazy loading, there is a significant reduction in bandwidth usage because not all resources are being loaded at once
- Increase in performance: When a page has too much to load, the browser takes its time to make sure that the content is delivered the way it should be. This can sometimes cause poor rendering of layouts and slow performance. With the lazy loading approach, browsers do not need to do too much work to ensure that the page is loaded correctly
Disadvantages of lazy loading
- The lazy loading approach is not ideal for cases where the data in one part of an application depends on another
- With lazy loading, more database calls are made, as compared to other techniques. This is because data is not fetched all at once, but has to continuously be fetched at different points in time within the application
What is eager loading?
With eager loading, all resources required for the running of the application are loaded upfront. Once the page initially loads, all images, scripts, and components are fetched from the server.
Eager loading is particularly beneficial in applications where data in one part of the app is required for other parts within the app. This is common in dashboard applications.
Benefits of eager loading
- Lesser database queries: Unlike the lazy loading strategy, eager loading involves fewer database queries. Because all resources are loaded at once, the client does not repeatedly have to query the backend to load other parts of the page
- Simplified code: Unlike lazy loading, eager loading avoids the need to explicitly find ways to defer the loading of resources. This approach therefore involves simpler and less complex code
- Data consistency: Eager loading ensures data consistency as all related data is fetched at once. This is useful in scenarios where processes modify data in the background between queries.
Disadvantages of eager loading
- Increase in bandwidth usage, as the amount of data sent between the client and server per second at the initial load time is high
- With the eager loading approach, there are slower initial load times and wait times
- When not properly implemented, eager loading can impair application performance. The browser suddenly has to manage a lot of data at the same time and ensure that layouts are displayed properly
- With eager loading, there is usually unnecessary fetching of data. Imagine a social media application whereby there is a users table and a posts table, and we want to fetch them both in one query. In the case where we need to fetch a user’s name and their latest post, eager loading would fetch unnecessary data (all posts from that user), leading to over-fetching and performance issues
Differences between lazy and eager loading
Lazy loading | Eager loading |
---|---|
Loads data only when it is accessed for the first time | Loads all related data at the initial load time |
Results in more database queries, as each related data access triggers a fetch from the database | Results in fewer database queries, as all related data access is fetched upfront |
Uses less memory, as data is accessed only when it is needed | May increase memory usage as all data is loaded upfront |
Code is more complex, as you need to handle cases where additional resources are to be loaded from the database | Code is simplified here, as there is no need to explicitly define any edge cases |
Provides more control, allowing you to decide when to load data, which can be beneficial in scenarios with conditional data access | Offers less control over when data is being fetched, because all data resources are being fetched at once |
Better used in scenarios where data is rarely accessed and is needed only at the time when it should be loaded | Used in scenarios where data is continuously accessed and is always needed |
Lazy loading in React
Single-page application (SPA) frameworks like React have default methods of implementing lazy and eager loading. By using [Suspense](https://blog.logrocket.com/data-fetching-react-suspense/)
and the React.lazy
function in React, we can see how to load a component at will, by clicking a button.
Say we have a component that we only need to use later in our application. We'll implement this as a component that is loaded at the click of a button. Let’s call the component MyLazyComponent
:
const MyLazyComponent = () => {
return (
<div>
<p>Look, I am the lazy component that is loaded after a button click</p>
</div>
)
}
export default MyLazyComponent
Now that we have the component to be lazily loaded, let’s see how React implements lazy loading through its inbuilt React.lazy
function:
import React, { Suspense, useState } from "react"
const LazyComponent = React.lazy(() => import('./MyLazyComponent'))
function App() {
const [showComponent, setShowComponent] = useState(false)
return (
<>
<h1>Lazy component example</h1>
<button onClick={() => setShowComponent(true)}>Load Component</button>
<Suspense fallback={<div>Loading component...</div>}>
{showComponent && <LazyComponent/>}
</Suspense>
</>
);
}
export default App
In our App.jsx
file, we instantiate a LazyComponent
variable, which uses the React.lazy()
function to dynamically call the MyLazyComponent
we created before. We have a showComponent
state that is initialized to false and is set to true when the button is clicked. Once the state of showComponent
is set to true, the MyLazyComponent
is then loaded onto the page. The built-in Suspense
component provides a fallback UI for when the MyLazyComponent
is in the process of loading.
With the code as is, we can’t see the effect of the fallback UI because the lazy-loaded component is loaded too fast. Let’s simulate a delay in loading the lazy component. By using a promise, we can use the setTimeout
function to induce a two-second delay. We use a promise here because we are working with a dynamic import:
const LazyComponent = React.lazy(
() =>
new Promise((resolve) => {
setTimeout(() => resolve(import("./MyLazyComponent")), 2000);
})
);
Running the code with the changes above, you can now see that the fallback UI takes effect just as the lazy component is loaded and displayed on the page:
Something interesting to note, however, is that even without the React.lazy
function, we are able to run and see the same results. This defeats the purpose of lazy loading, however, because the component is still being loaded in the background. React.lazy
is essential because it allows us to dynamically import a component and use it only when needed, without including it in the initial application bundle. This is the whole point of lazy loading. Without React.lazy
, MyLazyComponent
is still included in the initial application bundle.
Eager loading in React
Eager loading is the default behavior for loading components in React and can be implemented through [useEffect](https://blog.logrocket.com/useeffect-react-hook-complete-guide/)
Hooks, or normal component imports. If we had to refactor our code above to demonstrate eager loading, we’d do so as follows.
We have the MyLazyComponent
being refactored to MyEagerComponent
:
const MyEagerComponent = () => {
return (
<div>
<p>I am an eager-loaded component, hello.</p>
</div>
)
}
export default MyEagerComponent
And as for our App.jsx
:
import MyEagerComponent from "./MyEagerComponent";
function App() {
return (
<>
<h1>Eager component example</h1>
<MyEagerComponent/>
</>
);
}
export default App
You can see that no additional code is required to load the above component eagerly. Running this app would immediately load the eager component onto the page.
Conclusion
In this article, we explored eager and lazy loading in detail, covering their benefits and differences. We also implemented both lazy and eager loading in a single-page application like React using only components.
These techniques are essential in optimizing the performance of web applications. Lazy loading helps enhance user experience by reducing initial load times and conserving bandwidth, making it ideal for infrequently accessed data. Eager loading, on the other hand, ensures data consistency and simplifies code, particularly in cases where data is required across different parts of the application. By choosing the right loading strategy, you can significantly improve the responsiveness and performance of your application, ultimately creating a more seamless experience for users.
Get set up with LogRocket's modern error tracking in minutes:
- Visit https://logrocket.com/signup/ to get an app ID.
- Install LogRocket via NPM or script tag.
LogRocket.init()
must be called client-side, not server-side.
NPM:
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
Script Tag:
Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
3.(Optional) Install plugins for deeper integrations with your stack:
- Redux middleware
- ngrx middleware
- Vuex plugin
Top comments (0)