Saltar para o conteúdo
Blume is now publicly available.
Blume
Português
Esc
navegarabrir⌘Jpré-visualizar
Nesta página

Ilhas

Coloque um componente interativo em islands/ e use-o em qualquer página MDX — hidratado automaticamente, sem importação por página.

O Blume renderiza sua documentação como HTML estático com zero JavaScript por padrão. Quando você precisa de algo interativo — uma demonstração ao vivo, um gráfico, um playground — você adiciona uma ilha: um componente de framework que envia JS apenas para si mesmo, apenas nas páginas que o utilizam.

A convenção islands/

Coloque um componente em uma pasta islands/ na raiz do seu projeto. O nome do arquivo se torna um componente que você pode usar em qualquer página .mdx, sem importação:

import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>Clicked {count}</button>;
}
Here's a live counter: <Counter />

O nome do arquivo é o nome do componente, então ele deve ser um identificador em PascalCase — apenas letras, dígitos e sublinhados (Counter.tsx<Counter />). Nomes de arquivo em minúsculas, nomes com traços/pontos/espaços (como Time-Picker.tsx) e duas ilhas que resolvem para o mesmo nome são ignorados com um aviso de compilação.

Registrando ilhas em components.ts

Se você preferir manter as ilhas junto ao restante dos seus componentes — ou dar a elas um nome diferente do arquivo — registre-as com defineComponents. O grupo islands é exatamente como a pasta islands/: cada entrada está disponível em todas as páginas MDX e é hidratada (com padrão client: "visible").

import { defineComponents } from "blume";
import Counter from "./widgets/Counter.tsx";

export default defineComponents({
  islands: {
    Counter, // <Counter /> in any MDX page, hydrated
  },
});

Referencie o componente por importação ou por uma string de caminho, e defina um modo de hidratação por ilha com a forma de descritor:

export default defineComponents({
  islands: {
    Chart: { component: "./widgets/Chart.tsx", client: "only" },
  },
});

Hidratação

Por padrão, uma ilha usa client:visible: ela é hidratada quando o leitor a rola até o campo de visão, então uma página cheia de ilhas ainda carrega instantaneamente. Opte por uma estratégia diferente com um export const client no arquivo da ilha:

// Skip server rendering entirely — for components that touch the DOM/window.
export const client = "only";

export default function Chart() {
  /* ... */
}
Valor de client Hidrata Use para
"visible" (padrão) Quando rolado até o campo de visão A maioria das ilhas
"load" Imediatamente ao carregar a página UI acima da dobra, que deve ser instantânea
"idle" Quando a thread principal está ociosa Interatividade não urgente
"only" Apenas no cliente, nunca renderizado no servidor Bibliotecas que precisam de window/document (gráficos, editores)

Frameworks

O React funciona de imediato — o Blume o ativa automaticamente assim que seu projeto contém uma ilha .tsx/.jsx.

O React Compiler está ativado por padrão sempre que o React está habilitado, então suas ilhas são memoizadas automaticamente — sem necessidade de useMemo/useCallback escritos à mão. Ele vem com o Blume; não há nada para instalar. Desative em blume.config.ts:

export default defineConfig({
  react: { compiler: false },
});

Vue e Svelte também são suportados; instale a integração Astro correspondente e o Blume configura o renderizador quando encontra uma ilha .vue ou .svelte:

# Vue
npm install @astrojs/vue vue

# Svelte
npm install @astrojs/svelte svelte
<script setup>
import { ref } from "vue";
const on = ref(false);
</script>

<template>
  <button @click="on = !on">{{ on ? "On" : "Off" }}</button>
</template>

As props que você passa no MDX (<Counter start={5} />) são encaminhadas ao componente, e os filhos (<Counter>label</Counter>) chegam como o slot padrão.

Hooks

As ilhas são hidratadas por conta própria, então não há contexto do React para conduzir os dados do projeto. Em vez disso, blume/hooks lê um pequeno snapshot que o layout serializa na página — sem props para repassar:

import { useBlume, usePage } from "blume/hooks";

export default function PageInfo() {
  const blume = useBlume();
  const page = usePage();
  if (!(blume && page)) {
    return null;
  }
  return (
    <p>
      You're reading <strong>{page.title}</strong> on {blume.config.title}.
    </p>
  );
}
Hook Retorna
useBlume() { config, navigation } do site, ou null antes da montagem
usePage() { route, title } da página atual, ou null antes da montagem
useSearch() { search, results, loading } — consulta o provedor de busca configurado
useAskAI() { ask, messages, loading, reset } — transmite a partir do endpoint Ask AI

useBlume() e usePage() retornam null até que a ilha seja montada (para que servidor e cliente renderizem o mesmo primeiro quadro) — proteja-se contra isso. O snapshot é emitido apenas em páginas que enviam React, então um site totalmente estático não paga nada.

Em páginas personalizadas construídas com PageLayout, passe clientData para que as ilhas ali possam lê-lo:

<PageLayout
  clientData={{ config: data.config, navigation: data.navigation, page: { route: "/", title: "Home" } }}
  {/* …other props… */}
/>

Esta página foi útil?