AvalonAvalon
GitHub

Performance

Tips and patterns for keeping your Avalon site fast.

Zero JS by default

The biggest performance win is already built in: pages ship no JavaScript unless you add an island. A page with no islands is pure HTML and CSS — no hydration, no runtime overhead.

Choose the right hydration condition

Each hydration condition has a different impact on page load:

ConditionJS on initial loadBest for
on:clientYes — blocks critical pathHero animations, auth-gated UI
on:visibleDeferred until scrollBelow-the-fold content
on:interactionDeferred until click/hoverForms, menus, dropdowns
on:idleBackground, lowest priorityAnalytics, chat widgets
media:Only if query matchesResponsive-only components

Prefer on:interaction or on:idle for anything that doesn't need to be interactive immediately.

Lazy integrations

Enable lazyIntegrations to avoid loading unused framework adapters:

const plugins = await avalon({
  integrations: ['react', 'vue', 'svelte'],
  lazyIntegrations: true,
});

With lazy integrations, the adapter for each framework is only loaded when a page actually uses an island from that framework.

Image optimization

Avalon includes a built-in <Image> component that handles format conversion, responsive srcset generation, and lazy loading automatically:

import { Image } from '@useavalon/avalon/client';

<Image src="/hero.jpg" alt="Hero" width={1200} height={600} />

The component converts images to modern formats (WebP, AVIF), generates multiple sizes for responsive layouts, and adds width/height attributes to prevent layout shift. See the full Image Optimization guide for configuration options.

Streaming SSR

Avalon streams the layout shell to the browser before page data resolves. This dramatically improves FCP on pages with async data fetching — the user sees the navigation and layout instantly while the server waits on API calls. Streaming is automatic for all pages using the modular layout system. See Streaming SSR for details.

Cache headers

Configure long-lived cache headers for immutable assets:

nitro: {
  routeRules: {
    '/assets/**': {
      headers: { 'Cache-Control': 'public, max-age=31536000, immutable' },
    },
    '/islands/**': {
      headers: { 'Cache-Control': 'public, max-age=31536000, immutable' },
    },
  },
}

Bundle analysis

Inspect your island bundles with Vite's built-in rollup visualizer:

bun add -d rollup-plugin-visualizer
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  plugins: [visualizer({ open: true })],
});

Preloading critical islands

For on:client islands that are above the fold, add a <link rel="modulepreload"> in your layout's <head> to start fetching the bundle earlier.

Measuring

Use PageSpeed Insights or Lighthouse to measure real-world performance. The key metrics to watch are LCP (Largest Contentful Paint) and TBT (Total Blocking Time) — both improve significantly when you defer or eliminate unnecessary JavaScript.