Chapter 3: Beyond Routes: Lazy Loading Components
Of course. Now that we've split our code by page (route), the next logical step is to optimize what happens inside each page. Welcome to the world of Lazy Loading Components.
The Scenario 📝
- System: A complex user dashboard page.
- Problem: Even though route-based code splitting is working, the JavaScript file for the dashboard page itself is still quite large. This is because the page contains several heavy components that aren't needed immediately, such as:
- A complex charting component (
AnalyticsChart.vue) located at the bottom of the page. - A profile editing modal (
EditProfileModal.vue) that only appears when a user clicks a button. - A video chat component.
- A complex charting component (
Analyzing the Bottleneck 🧐
Wasted Initial Resources: When a user loads the dashboard, their browser is forced to download and parse the JavaScript for the analytics chart and the edit modal, even if they never scroll down to see the chart or click the "Edit Profile" button.
The Impact: This increases the initial JavaScript bundle size for the page, which in turn slows down the Time to Interactive (TTI)—the moment the page becomes responsive to user input.
The Solution: Lazy Load Your Components ✅
The Logic: Instead of bundling all of a page's components into a single file, we'll only load the code for a component when it's actually needed. This can be triggered by two main events:
- When the component is about to be scrolled into the user's view.
- When the user performs an action (like clicking a button to open a modal).
How It Works: The framework (like Nuxt/Vue) creates separate, smaller JavaScript files (chunks) for these lazy-loaded components. The browser only requests these files when they are required.
How to Do It in Nuxt: It's Incredibly Simple ✨
Nuxt 3 provides a very convenient way to lazy load a component: just add the Lazy prefix to the component's name in your template.
The Standard Way (Loads Everything Upfront):
<template>
<div>
<h1>My Dashboard</h1>
<UserProfile />
<AnalyticsChart />
</div>
</template>
<script setup>
import UserProfile from '~/components/UserProfile.vue';
import AnalyticsChart from '~/components/AnalyticsChart.vue';
</script>The Optimized Way (Lazy Loading):
<template>
<div>
<h1>My Dashboard</h1>
<UserProfile />
<LazyAnalyticsChart />
</div>
</template>
<script setup>
import UserProfile from '~/components/UserProfile.vue';
// No need to import the lazy-loaded component here!
</script>Analyzing the Results
- Smaller Initial Bundle: The main JavaScript file for the dashboard page is now significantly lighter because the code for
AnalyticsCharthas been moved to its own file. - Faster TTI: The browser has less JavaScript to process initially, making the page interactive much faster.
- On-Demand Loading: The JavaScript for
AnalyticsChartwill only be downloaded over the network when the user scrolls down and the component is about to enter the viewport.
Conclusion:
- The Golden Rule: "Don't load what the user can't see."
- After optimizing with route-based code splitting, lazy loading components is the next step to boost the performance of individual pages.
- Identify components that are large, non-critical for the initial view (e.g., below the fold), or conditionally rendered (like modals and popups). These are the perfect candidates for lazy loading.