Learn Nuxt - Performance Optimization
Series/Learn Nuxt/Episode 15
Episode 15 of 24

Learn Nuxt - Performance Optimization

This episode covers deep performance optimization: profiling with Vue DevTools and browser DevTools, optimizing component rendering and bundle size, prefetching links with resource hints, and strategies to reduce the JavaScript payload and server payload.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Episode 14 gave you caching strategies; episode 15 goes deeper into technical performance optimization. You can't fix what you don't measure, so this episode starts with profiling, then moves to specific fixes: rendering, bundle, payload, and prefetching.

The goal isn't just a good Lighthouse score, but a real experience: pages that are immediately interactive, navigation that feels instant, and a bundle that doesn't burden users on slow connections.

Profiling with Vue DevTools and Browser Tools

Using Nuxt DevTools

Nuxt DevTools — which we enabled in episode 3 — provides a performance tab to see each component's render time:

Aktifkan dev server
npm run dev

Open http://localhost:3000/_nuxt/ then choose the Performa tab. From here you can see which components take the longest to render and how often they re-render.

Browser DevTools and Lighthouse

Chrome DevTools gives you two key tools: the Network tab to see request sizes and ordering, and the Performance tab to record runtime profiles. For quality scores, use Lighthouse:

Audit dengan Lighthouse
npx lighthouse http://localhost:3000 --view

The npx lighthouse http://localhost:3000 --view command runs a full audit and opens the results. Pay attention to metrics like Largest Contentful Paint and Total Blocking Time.

Optimizing Component Rendering and Bundle Size

Components That Re-Render Too Often

If an expensive component re-renders every time state changes, limit its responsiveness. A well-placed computed can cut repeated renders:

JSMemoisasi daftar
const daftarBayar = computed(() =>
  items.value.filter((item) => item.harga > 100000)
)

computed(() => items.value.filter(...)) only recomputes when items changes, not when the component re-renders. Avoid doing heavy calculations directly in the template.

Bundle Analysis with nuxi analyze

Bundle size is often the main source of slow pages. Analyze visually:

Analisis bundle
npx nuxi analyze

npx nuxi analyze generates an interactive report of the bundle contents: which libraries are biggest and where they can be split. Two main targets: large libraries that can be lazy-loaded, and code that's never actually used.

<NuxtLink> already does smart prefetching — when a link becomes visible in the viewport, Nuxt downloads the target page's payload in the background. This makes navigation feel instant:

HTMLLink dengan prefetch
<NuxtLink to="/produk" prefetch>Katalog</NuxtLink>

NuxtLink to="/produk" prefetch forces prefetch even before the link is visible. For very important pages, add prefetch; for rarely visited areas, leave the default.

Manual Resource Hints

For resources that aren't links, use resource hints:

JSPreload font di head
export default defineNuxtConfig({
  app: {
    head: {
      link: [
        { rel: "preload", href: "/font/utama.woff2", as: "font", type: "font/woff2", crossorigin: "" },
      ],
    },
  },
})

rel: "preload" tells the browser this font is needed immediately. Use it sparingly — preloading too much steals bandwidth from other resources.

Reducing the JavaScript Payload and Server Payload

Lazy-Loaded Components

Large components like text editors or charts should load only when needed. Use a lazy component:

HTMLLazy load komponen
<script setup lang="ts">
const { ChartHarga } = defineAsyncComponent({
  loader: () => import("~/components/ChartHarga.vue"),
})
</script>

defineAsyncComponent(() => import(...)) makes the component load separately from the main bundle. This code doesn't burden the initial page — it's only downloaded when the component first renders.

Efficient Server Payload

Nuxt sends data to the client so hydration stays consistent. A bloated payload slows the page. Request only the fields you need:

JSKurangi payload
const { data } = await useFetch("/api/produk", {
  query: { fields: "id,nama,harga" },
})

Request only the fields you need from the API. The smallest possible payload means less parse and network time.

Conclusion

Episode 15 trains your performance instincts: measuring with Nuxt DevTools, Lighthouse, and nuxi analyze before optimizing; improving rendering with computed values and lazy components; leveraging NuxtLink prefetching and resource hints; and shrinking both the JavaScript and server payloads.

Key takeaways:

  • Measure first with Nuxt DevTools and Lighthouse before optimizing.
  • computed and memoization prevent unnecessary re-renders.
  • nuxi analyze shows the bundle composition visually.
  • NuxtLink prefetches automatically as links approach the viewport.
  • Lazy components with defineAsyncComponent shrink the initial bundle.
  • Reduce the server payload by only fetching the fields you need.

In the next episode, episode 16, we will discuss testing and quality — unit testing with Vitest, component testing with Vue Test Utils, integration and end-to-end testing with Playwright, and static analysis and type checking to maintain quality. Your store's code will be tested automatically.

Learn Nuxt - Performance Optimization | Learn Nuxt