You can define which components should remain interactive in the production
build by using client:
directives in your components (borrowed from Astro).
Any JS required for these components will be automatically inferred and optimized to perform partial hydration in the final build.
No JS is shipped unless you use a hydration strategy! 🏝
Here's an example with MDX, an interactive audio player in a mostly static page:
---
title: Song for You
audio: /song-for-you.mp3
---
I've recently recorded a song, listen:
<AudioPlayer {...frontmatter} client:visible/>
You can also use these directives inside your Vue components. In the following
example, the Download link is rendered statically, while the <Audio>
component is interactive and will be hydrated when visible.
<template>
<div class="audio-player">
<Audio client:visible :src="audio" :initialDuration="initialDuration"/>
<div>
<a :href="audio" :download="`${title}.mp3`">
Download the Song
</a>
</div>
</div>
</template>
The following hydration strategies are available.
Hydrates the component immediately as the page loads.
<DarkModeSwitch client:load/>
Hydrate the component as soon as the main thread is free.
<TimeAgo :date="date" client:idle/>
Hydrates the component as soon as the element enters the viewport.
<AudioPlayer :src="/example.mp3" client:visible/>
Hydrates the component as soon as the browser matches the given media query.
Useful to avoid unnecessary work depending on the available viewport, such as in mobile devices.
<Sidebar client:media="screen and (min-width: 600px)"/>
Does not hydrate the component in the client, it will be prerendered as static HTML.
Allows to detect Preact, SolidJS, or Svelte components embedded in Vue or MDX files.
No JS will be shipped in the buildYou should use any of the other directives if you want the component to be interactive.
Does not prerender the component during build.
Because it's not pre-rendered it could cause layout shift and affect the user experience.
Prefer one of the previous strategies whenever possible.