Documentation
...Concept
Section titled “Concept”Bring Astro’s client directives to vanilla JavaScript! 🎉
Script Islands fakes a framework renderer so you can use client:load, client:visible, client:idle and friends with plain JavaScript. Each <ScriptIsland> extracts its <script> into a separate file that only loads when triggered.
Why?
- Use Astro’s powerful client directives without any framework overhead
- Defer scripts until they’re actually needed
- Reduce initial page load size and improve performance
Installation
Section titled “Installation”Install Script Islands in your Astro project:
npm install astro-script-islandspnpm install astro-script-islandsAdd the integration to your astro.config.* file:
import { defineConfig } from 'astro/config';import ScriptIslands from 'astro-script-islands/integration';
export default defineConfig({ integrations: [ ScriptIslands() ],});Examples
Section titled “Examples”Basic Usage
Section titled “Basic Usage”- Import the
ScriptIslandcomponent fromastro-script-islands/component - Wrap your JavaScript code inside
<ScriptIsland> - Use any of Astro’s
client:*directives to control when the script loads
---import ScriptIsland from "astro-script-islands/component"import { Badge } from "@astrojs/starlight/components"---
<p id="client-idle"> <span>Script loaded:</span> <Badge id="idle-false" text="false" variant="danger" /> <Badge id="idle-true" text="true" variant="success" class="hidden" /></p>
<ScriptIsland client:idle> <script> document.querySelector("#client-idle #idle-false").classList.add("hidden") document.querySelector("#client-idle #idle-true").classList.remove("hidden") document.querySelector("#client-idle span.success").textContent = new Date().toLocaleTimeString() // demo:start window.dispatchEvent(new CustomEvent("island-hydrated")) // demo:end </script></ScriptIsland>Script loaded: false
The script inside <ScriptIsland> is extracted into a separate file and only loaded when the client:idle condition is met (after the page finishes its initial load and the browser is idle).
Slotting Elements
Section titled “Slotting Elements”You can slot HTML elements or Astro components inside <ScriptIsland>. This is useful when using client:visible, which needs a visible element to observe.
---import ScriptIsland from "astro-script-islands/component"---
<ScriptIsland client:visible> <p>You finally waited for <strong id="countup">0</strong> seconds.</p> <script> import { CountUp } from "countup.js" let demo = new CountUp("countup", 3000) demo.start() // demo:start window.dispatchEvent(new CustomEvent("island-hydrated")) // demo:end </script></ScriptIsland>You finally waited for 0 seconds.
Custom Client Directives
Section titled “Custom Client Directives”Script Islands work seamlessly with Astro’s custom client directives. This example demonstrates a custom client:tracking directive that activates tracking code across multiple components when a global event is dispatched.
---import ScriptIsland from "astro-script-islands/component"---
<button id="hover-button" disabled>Hover me</button>
<ScriptIsland client:tracking> <script> import { track } from "./track.ts"
const hoverButton = document.getElementById("hover-button") hoverButton.disabled = false hoverButton?.addEventListener("mouseover", () => { track() }) // demo:start window.dispatchEvent(new CustomEvent("island-hydrated")) // demo:end </script></ScriptIsland>---import ScriptIsland from "astro-script-islands/component"---
<button id="click-button" disabled>Click me</button>
<ScriptIsland client:tracking> <script> import { track } from "./track.ts"
const clickButton = document.getElementById("click-button") clickButton.disabled = false clickButton?.addEventListener("click", () => { track() }) // demo:start window.dispatchEvent(new CustomEvent("island-hydrated")) // demo:end </script></ScriptIsland>