Vue cookbook · Advanced

Lazy-load and lazily hydrate heavy components

A chart library and comments widget make the initial page slow, even though they're below the fold.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Wrap heavy components with defineAsyncComponent (with loading and error components and a timeout). In SSR apps, add a hydration strategy (Vue 3.5) such as hydrateOnVisible() so their JavaScript only hydrates when needed.

Solution

// components/lazy.ts
import { defineAsyncComponent, hydrateOnIdle, hydrateOnVisible } from "vue";
import LoadingBlock from "./LoadingBlock.vue";
import ErrorBlock from "./ErrorBlock.vue";

export const SalesChart = defineAsyncComponent({
  loader: () => import("./SalesChart.vue"),
  loadingComponent: LoadingBlock,
  errorComponent: ErrorBlock,
  delay: 200,                                            // avoid flashing the loader for fast loads
  timeout: 10000,
  hydrate: hydrateOnVisible({ rootMargin: "200px" }),
});

export const CommentsWidget = defineAsyncComponent({
  loader: () => import("./CommentsWidget.vue"),
  hydrate: hydrateOnIdle(),
});

Pitfalls

  • Lazy-loading components that are visible on first paint, delaying the main content.
  • No error component, leaving a blank area when a chunk fails to load.
  • Expecting hydration strategies to help in client-only apps; they apply to server-rendered HTML.

Variations

  • In Nuxt, prefix components with Lazy (<LazySalesChart hydrate-on-visible />).
  • hydrateOnInteraction("click") defers hydration until the user interacts.

Further reading: Async components and lazy hydration

Reference: https://vuejs.org/guide/components/async.html#lazy-hydration

More Vue recipes

Was this page helpful?