How does lazy loading improve performance?

Performance

The short answer

Lazy loading delays loading resources until they are actually needed. Instead of loading everything upfront, you load images when they scroll into view and load code when the user navigates to a page. This makes the initial page load faster and uses less bandwidth.

Lazy loading images

The simplest form is the loading="lazy" attribute on images:

<img src="photo.jpg" loading="lazy" alt="A photo" />

The browser only loads the image when it is close to the viewport. Images below the fold (not visible on screen) are not loaded until the user scrolls down.

For above-the-fold images (like a hero banner), do not use lazy loading — you want those to load immediately.

Code splitting in React

Instead of putting all your code in one big bundle, you split it into smaller chunks that load on demand:

import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));
const Settings = lazy(() => import('./Settings'));
function App() {
return (
<Suspense fallback={<p>Loading...</p>}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
);
}

The Dashboard and Settings components are only loaded when the user navigates to those routes. The initial bundle is smaller, so the first page load is faster.

Dynamic imports

You can also lazy load any module, not just React components:

button.addEventListener('click', async () => {
const { Chart } = await import('./chart-library');
const chart = new Chart(data);
chart.render();
});

The chart library is only loaded when the user clicks the button. If they never click it, it never loads.

Intersection Observer for custom lazy loading

For more control, use the Intersection Observer API to detect when elements enter the viewport:

const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document
.querySelectorAll('img[data-src]')
.forEach((img) => {
observer.observe(img);
});

What to lazy load

  • Images — especially below-the-fold images
  • Routes/pages — pages the user has not visited yet
  • Heavy components — charts, editors, maps
  • Third-party scripts — analytics, chat widgets, social embeds

What NOT to lazy load

  • Above-the-fold content (hero images, main content)
  • Critical CSS and JavaScript needed for first paint
  • Small resources where the lazy loading overhead is not worth it

Interview Tip

Cover both images (loading="lazy") and code (React.lazy / dynamic imports). The key insight is that lazy loading trades a small delay when the resource is first needed for a faster initial page load. Mention that you should not lazy load above-the-fold content — that would make the page feel slower, not faster.

Why interviewers ask this

Lazy loading is one of the most practical performance optimizations. Interviewers want to see if you know how to implement it at both the resource level (images) and the code level (code splitting), and if you understand the tradeoffs — what to lazy load and what to keep eager.