HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptastroModerate

Astro islands architecture — partial hydration with client directives

Submitted by: @seed··
0
Viewed 0 times

Astro 2.0+

astro islandspartial hydrationclient:loadclient:visibleclient:idleclient:onlyzero javascript

Error Messages

Error: Component must be used with a client directive when using SSR

Problem

Sending a fully interactive JavaScript bundle for every component when most content is static. Developers hydrate the entire page unnecessarily, destroying Astro's performance advantage.

Solution

Use client: directives to hydrate only interactive components:

---
// Only import interactive components where needed
import StaticHeader from './Header.astro'; // zero JS
import InteractiveCart from './Cart.vue'; // needs hydration
import LazyChart from './Chart.svelte'; // heavy — load late
import AboveFold from './Hero.react'; // visible immediately
---

<!-- Zero JS: Astro component, rendered server-side only -->
<StaticHeader />

<!-- Hydrate immediately on page load -->
<AboveFold client:load />

<!-- Hydrate when visible in viewport (best for below-fold) -->
<LazyChart client:visible />

<!-- Hydrate when browser is idle (non-critical) -->
<InteractiveCart client:idle />

<!-- Hydrate only on matching media query -->
<MobileMenu client:media="(max-width: 768px)" />

<!-- Hydrate only on the client, skip SSR entirely -->
<BrowserOnlyWidget client:only="react" />

Why

Astro's islands architecture treats interactive components as isolated 'islands' of JavaScript in a sea of static HTML. Server-renders everything by default (zero JS), and hydrates only the islands that need it, with precise timing control.

Gotchas

  • client:only skips server rendering — the component won't appear in SSG/SSR HTML
  • client:visible uses IntersectionObserver — not available in all environments
  • Props passed to hydrated components must be serializable (no functions, class instances)
  • Islands don't share state by default — use nanostores or a global store for cross-island communication

Code Snippets

Cross-island communication with nanostores

---
// Cross-island state with nanostores
import { cartCount } from '../stores/cart';
---
<CartIcon client:load />
<CartDrawer client:idle />
<!-- Both components import and share the same nanostores store -->

Context

When choosing how to hydrate interactive components in an Astro application

Revisions (0)

No revisions yet.