Partial hydration
On this page
OverviewSlinkity lets you control if and when your components use client-side JavaScript. Let's understand the options available.
Add a client:
directive
Section titled "Add a client: directive" Slinkity does not render your component client-side by default. In other words, your component will be rendered server-side, but your React useState
, Vue ref
s, and Svelte stores will not work until you opt-in to JS. This keeps your client-side bundle as lean as possible.
You'll need to pass a client:
directive to opt-in to hydration.
Hydrate component shortcodes
Section titled "Hydrate component shortcodes"<!--server-render with hydration-->
{% island 'Component.vue', 'client:load' %}{% endisland %}
<!--client-side rendering only-->
{% clientOnlyIsland 'Component.vue', 'client:load' %}{% endclientOnlyIsland %}
More on component shortcodes →
Hydrate component pages
Section titled "Hydrate component pages"// about.jsx
import { useState } from 'react'
export const island = {
when: 'client:load',
}
export default function About() {
const [count, setCount] = useState(0)
return (
<>
<p>You've had {count} glasses of water 💧</p>
<button onClick={() => setCount(count + 1)}>Add one</button>
</>
)
}
<!--about.vue-->
<template>
<p>You've had {{ count }} glasses of water 💧</p>
<button @click="add()">Add one</button>
</template>
<script>
import { ref } from "vue";
export default {
island: {
when: 'client:load',
},
setup() {
const count = ref(0);
const add = () => (count.value = count.value + 1);
return { count, add };
},
};
</script>
<!--about.svelte-->
<script context="module">
export const island = {
when: 'client:load',
}
</script>
<script>
let count = 0;
function add() {
count += 1;
}
</script>
<p>You've had {count} glasses of water 💧</p>
<button on:click={add}>Add one</button>
Choose the right client:
directive
Section titled "Choose the right client: directive" Hydration isn't just an on-off switch. Using Astro's hydration modes as a guide, we've added more granular options to choose when your component's JS is loaded. All of these options are available for shortcodes and component pages.
client:load
Section titled "client:load" This mirrors how "traditional" component-based frameworks operate. Components using any of these values will be rendered client-side as soon as possible.
<!--server-render with hydration-->
{% island 'Component.vue', 'client:load' %}{% endisland %}
<!--client-side rendering only-->
{% clientOnlyIsland 'Component.vue', 'client:load' %}{% endclientOnlyIsland %}
Whenever you visit /page-with-shortcode
, we'll import the component library (Vue in this case) and hydrate Component.vue
as soon as the page is done parsing (see MDN's docs on scripts with type="module"
). This ensures you component is interactive as soon as possible.
client:visible
Section titled "client:visible" Similar to lazy-loading images, client:visible
will only hydrate your component when it is scrolled into view. This uses the Intersection Observer API to figure out whether your component is on the page. Once it is, Slinkity will import the necessary dependencies to hydrate your component.
Note: We still import Slinkity-specific scripts ahead of time using module preloading. This is the bare minimum JS to hydrate your component using the Intersection Observer API.
<!--server-render with hydration-->
{% island 'Component.vue', 'client:visible' %}{% endisland %}
<!--client-side rendering only-->
{% clientOnlyIsland 'Component.vue', 'client:visible' %}{% endclientOnlyIsland %}
client:idle
Section titled "client:idle" client:idle
will load your component client-side as soon as the browser's main thread is free. This de-prioritizes your component and allows other JS resources on your page to take precedence.
This relies on the window.requestIdleCallback()
method in supported browsers, and sets an arbitrary 200ms
timeout for unsupported browsers.
<!--server-render with hydration-->
{% island 'Component.vue', 'client:idle' %}{% endisland %}
<!--client-side rendering only-->
{% clientOnlyIsland 'Component.vue', 'client:idle' %}{% endclientOnlyIsland %}
client:media
Section titled "client:media" client:media
loads your component client-side when a media query is met. This is helpful for components that only need interactivity at certain screen sizes (ex. a slide-out navigation for mobile devices). This relies on the window.matchMedia()
method.
<!--server-render with hydration-->
{% island 'Component.vue', 'client:media="screen (max-width: 400px)"' %}{% endisland %}
<!--client-side rendering only-->
{% clientOnlyIsland 'Component.vue', 'client:media="screen (max-width: 400px)"' %}{% endclientOnlyIsland %}
Don't forget wrapper quotes "..." around your media query!
Pass multiple client
directives
Section titled "Pass multiple client directives" You may want to hydrate your component once multiple client:
directives are met. To do so, pass multiple client:
directives to the island
shortcode.
This example will only hydrate at screen sizes below 400px
and when the component is visible on-screen:
<!--server-render with hydration-->
{% island 'Component.vue', 'client:visible', 'client:media="screen (max-width: 400px)"' %}{% endisland %}
<!--client-side rendering only-->
{% clientOnlyIsland 'Component.vue', 'client:visible', 'client:media="screen (max-width: 400px)"' %}{% endclientOnlyIsland %}