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:
| Condition | JS on initial load | Best for |
|---|---|---|
on:client | Yes — blocks critical path | Hero animations, auth-gated UI |
on:visible | Deferred until scroll | Below-the-fold content |
on:interaction | Deferred until click/hover | Forms, menus, dropdowns |
on:idle | Background, lowest priority | Analytics, chat widgets |
media: | Only if query matches | Responsive-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.