API de Integrações Astro

Integrações Astro adicionam novas funcionalidades e comportamentos ao seu projeto com apenas algumas linhas de código.

Esta página de referência é para qualquer um que esteja escrevendo sua própria integração. Para aprender como utilizar uma integração em seu projeto, veja o nosso guia, Usando Integrações no lugar.

As integrações Astro oficiais podem ser utilizadas como referência enquanto você constrói suas próprias integrações.

interface AstroIntegration {
    name: string;
    hooks: {
        'astro:config:setup'?: (options: {
            config: AstroConfig;
            command: 'dev' | 'build';
            updateConfig: (newConfig: Record<string, any>) => void;
            addRenderer: (renderer: AstroRenderer) => void;
            injectScript: (stage: InjectedScriptStage, content: string) => void;
            injectRoute: ({ pattern: string, entryPoint: string }) => void;
        }) => void;
        'astro:config:done'?: (options: { config: AstroConfig }) => void | Promise<void>;
        'astro:server:setup'?: (options: { server: vite.ViteDevServer }) => void | Promise<void>;
        'astro:server:start'?: (options: { address: AddressInfo }) => void | Promise<void>;
        'astro:server:done'?: () => void | Promise<void>;
        'astro:build:start'?: (options: { buildConfig: BuildConfig }) => void | Promise<void>;
        'astro:build:setup'?: (options: {
          vite: ViteConfigWithSSR;
          pages: Map<string, PageBuildData>;
          target: 'client' | 'server';
        }) => void | Promise<void>;
        'astro:build:ssr'?: (options: { manifest: SerializedSSRManifest }) => void | Promise<void>;
        'astro:build:done'?: (options: { pages: { pathname: string }[]; dir: URL; routes: RouteData[] }) => void | Promise<void>;
    };
}

Próximo hook: astro:config:done

Quando: Durante a inicialização, antes da configuração do Vite ou Astro ser resolvida.

Por que: Para estender a configuração do projeto. Isso inclui atualizar a configuração do Astro, aplicar plugins Vite, adicionar renderizadores de componentes, e injetar scripts na página.

'astro:config:setup'?: (options: {
    config: AstroConfig;
    command: 'dev' | 'build';
    updateConfig: (newConfig: Record<string, any>) => void;
    addRenderer: (renderer: AstroRenderer) => void;
    injectScript: (stage: InjectedScriptStage, content: string) => void;
    injectRoute: ({ pattern: string, entryPoint: string }) => void;
}) => void;

Tipo: AstroConfig

Uma cópia de somente leitura da configuração Astro suprida pelo usuário. Isto é resolvido antes de qualquer outra integração ser executada. Se você precisa de uma cópia da configuração depois de todas as integrações completarem seus processos de atualização da configuração, veja o hook astro:config:done.

Tipo: 'dev' / 'build'

  • dev - Projeto é executado a partir de astro dev ou astro preview
  • build - Projeto é executado a partir de astro build

Tipo: (newConfig: Record<string, any>) => void;

Uma função de callback para atualizar a configuração Astro suprida pelo usuário. Qualquer configuração que você providenciar será mesclada com a configuração do usuário + atualizações da configuração de outras integrações, então você está livre para omitir as chaves!

Por exemplo, digamos que você precisa fornecer um plugin Vite ao projeto do usuário:

import bananaCSS from '@vitejs/official-banana-css-plugin';

export default {
  name: 'banana-css-integration',
  hooks: {
    'astro:config:setup': ({ updateConfig }) => {
      updateConfig({
        vite: {
          plugins: [bananaCSS()],
        }
      })
    }
  }
}

Tipo: (renderer: AstroRenderer ) => void; Exemplos: lit, svelte, react, preact, vue, solid

Uma função de callback para adicionar um renderizador de um framework de componentes (ex. React, Vue, Svelte, etc). Você pode explorar os exemplos e definições de tipagem acima para opções mais avançadas, mas aqui estão as duas principais opções que você precisa estar ciente sobre:

  • clientEntrypoint - caminho para um arquivo que é executado no cliente sempre que seu componente é utilizado. Esta é principalmente utilizado para renderizar ou hidratar seu componente com JS.
  • serverEntrypoint - caminho para um arquivo que é executado durante requisições no lado do servidor ou builds estáticas sempre que seu componente é utilizado. Esta deve renderizar componentes para uma marcação estática, com hooks para hidratação aonde aplicável. o callback renderToString do React é um exemplo clássico.

Tipo: ({ pattern: string, entryPoint: string }) => void;

Uma função de callback para injetar rotas em um projeto Astro. Rotas injetadas podem ser páginas .astro ou handlers de rotas .js e .ts.

injectRoute recebe um objeto com um pattern e um entryPoint.

  • pattern - aonde a rota deve ser inserida no navegador, por exemplo /foo/bar. Um pattern pode utilizar a sintaxe de caminho de arquivos do Astro para indicar rotas dinâmicas, por exemplo /foo/[bar] ou /foo/[...bar]. Note que uma extensão de arquivo não é necessária no pattern.
  • entryPoint - apenas um especificador de módulo apontando para a página .astro ou handler de rota .js/.ts que manipula a rota indicada no pattern.

Exemplo de uso:

injectRoute({
  pattern: '/foo/[dinamico]',
  entryPoint: 'foo/pagina-dinamica.astro'
});

Tipo: (stage: InjectedScriptStage, content: string) => void;

Uma função de callback para injetar uma string de conteúdo JavaScript em todas as páginas.

O stage indica como este script (o content) deve ser inserido. Alguns stages permitem inserir scripts sem modificação, enquanto outros permitem otimizações durante a etapa de bundling do Vite:

  • "head-inline": Injetado em uma tag script no <head> de cada página. Não é otimizado ou resolvido pelo Vite.

  • "before-hydration": Importado no lado do cliente, antes do script de hidratação ser executado. Otimizado e resolvido pelo Vite.

  • "page": Similar a head-inline, exceto que o script injetado é transformado por Vite e passa por bundle junto com quaisquer outras tags <script> definidas dentro de componentes Astro na página. O script será carregado com um <script type="module"> no resultado final da página, otimizado e resolvido pelo Vite.

  • "page-ssr": Importado como um módulo separado no frontmatter de cada componente de página Astro. Por conta desse stage importar seu script, a global Astro não está disponível e seu script será executado apenas uma vez quando o import for analisado pela primeira vez.

    O principal uso para o stage page-ssr é para injetar um import de CSS em cada página para ser otimizado e resolvido pelo Vite:

    injectScript('page-ssr', 'import "estilos-globais.css";');

Hook anterior: astro:config:setup

Próximo hook: astro:server:setup quando estiver sendo executado no modo “dev” ou “preview”, ou astro:build

durante builds em produção

Quando: Após a configuração do Astro ter sido resolvida e outras integrações tiverem executado seus hooks astro:config:setup.

Por que: Para obter a configuração final para uso em outros hooks.

'astro:config:done'?: (options: { config: AstroConfig }) => void | Promise<void>;

Tipo: AstroConfig

Uma cópia de somente leitura da configuração Astro suprida pelo usuário. Esta é resolvida após outras integrações serem executadas.

Hook anterior: astro:config:done

Próximo hook: astro:server:start

Quando: Logo após o servidor do Vite ser criado no modo “dev” ou “preview”, porém antes do evento listen() ser disparado. Veja a API createServer do Vite para saber mais.

Por que: Para atualizar as configurações do servidor Vite e middleware.

'astro:server:setup'?: (options: { server: vite.ViteDevServer }) => void | Promise<void>;

Tipo: ViteDevServer

Uma instância mutável do servidor Vite usado no modo “dev” ou “preview”. Por exemplo, esta é utilizada pela nossa integração Partytown (EN) para injetar o servidor Partytown como um middleware:

export default {
  name: 'partytown'
  hooks: {
    'astro:server:setup': ({ server }) => {
      server.middlewares.use(
        function middleware(req, res, next) {
          // manejar requisições
        }
      );
    }
  }
}

Hook anterior: astro:server:setup

Próximo hook: astro:server:done

Quando: Logo após o evento listen() do servidor ser disparado.

Por que: Para interceptar requisições de rede de um endereço específico. Se você pretende utilizar esse endereço para middleware, considere utilizar astro:server:setup no lugar.

'astro:server:start'?: (options: { address: AddressInfo }) => void | Promise<void>;

Tipo: AddressInfo

O endereço, família e número de porta suprido pelo módulo Net do NodeJS.

Hook anterior: astro:server:start

Quando: Logo após o servidor de desenvolvimento ser fechado.

Por que: Para executar quaisquer eventos de limpeza que você pode ativar durante os hooks astro:server:setup ou astro:server:start.

'astro:server:done'?: () => void | Promise<void>;

Hook anterior: astro:config:done

Próximo hook: astro:build:setup

Quando: Após o evento astro:config:done, porém antes da build para produção começar.

Por que: Para definir quaisquer objetos globais ou clientes necessários durante a build para produção. Esta também pode estender as opções de configuração de build na API de adaptadores.

'astro:build:start'?: (options: { buildConfig: BuildConfig }) => void | Promise<void>;

Hook anterior: astro:build:start

Próximo hook: astro:build:ssr

Quando: Após o hook astro:build:start, executado imediatamente antes da build.

Por que: Nesse ponto, a configuração Vite para a build foi completamente construída, logo essa é sua última chance de modificá-la. Isto pode ser útil para por exemplo sobrescrever alguma configuração padrão. Se você não tiver certeza se deve utilizar este hook ou astro:build:start, então utilize astro:build:start no lugar.

'astro:build:setup'?: (options: {
  vite: ViteConfigWithSSR;
  pages: Map<string, PageBuildData>;
  target: 'client' | 'server';
}) => void | Promise<void>;

Hook anterior: astro:build:setup

Quando: Após a build para produção (SSG ou SSR) tiver sido completada.

Por que: Para conseguir acesso ao manifesto de SSR, isso é útil quando se for criar builds SSR customizadas em plugins ou integrações.

'astro:build:ssr'?: (options: { manifest: SerializedSSRManifest }) => void | Promise<void>;

Hook anterior: astro:build:ssr

Quando: Após a build para produção (SSG ou SSR) tiver sido completada.

Por que: Para acessar rotas geradas e assets para extensão (ex. copiar conteúdo do diretório gerado /assets). Se você planeja transformar assets gerados, nós recomendados explorar a API de Plugins Vite e configurá-la via astro:config:setup no lugar.

'astro:build:done'?: (options: { dir: URL; routes: RouteData[] }) => void | Promise<void>;

Tipo: URL

Um caminho de URL para o diretório final da build. Note que se você precisa de uma string de caminho absoluto válida, você deve utilizar o utilitário fileURLToPath do Node.

import { writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
export default function minhaIntegracao() {
  return {
    hooks: {
      'astro:build:done': async ({ dir }) => {
        const metadados = await getIntegrationMetadata();
        // Utilize fileURLToPath para conseguir uma string válida e multiplataforma do caminho absoluto.
        const arquivoSaida = fileURLToPath(new URL('./minha-integracao.json', dir));
        await fs.writeFile(arquivoSaida, JSON.stringify(metadados));
      }
    }
  }
}

Tipo: RouteData[]

Uma lista de todas as rotas geradas junto de seus metadados associados. Isso estará vazio quando estiver utilizando um adaptador de SSR!

Você pode ver a referência completa do tipo RouteData abaixo, mas as propriedades mais comuns são:

  • component - o caminho do arquivo de entrada relativo à raiz do projeto
  • pathname - a URL de saída do arquivo (undefined para rotas utilizando parâmetros [dinâmicos] e [...spread])

Referência do tipo RouteData

interface RouteData {
  /** Se a rota dada é uma página HTML ou um endpoint não-HTML */
  type: 'page' | 'endpoint';
  /** URL da fonte do componente */
  component: string;
  /**
   * Nome de caminho da URL de saída onde esta rota será servida
   * nota: será undefined para rotas [dinâmicas] e [...spread]
   */
  pathname?: string;
  /** 
   * regex usado para corresponder A uma URL de entrada contra a rota requisitada
   * ex. "[fruta]/sobre.astro" irá gerar o pattern: /^\/([^/]+?)\/sobre\/?$/
   * aonde pattern.test("fruta/sobre") é "true"
   */
  pattern: RegExp;
  /**
   * Parâmetros dinâmicos e spread da rota
   * ex. "/pages/[lang]/[..slug].astro" irá retornar os parâmetros ['lang', '...slug']
   */
  params: string[];
  /**
   * Similar ao campo "params", mas com mais metadados associados
   * ex. "/pages/[lang]/index.astro" irá retornar os segmentos
   * [[ { content: 'lang', dynamic: true, spread: false } ]]
   */
  segments: { content: string; dynamic: boolean; spread: boolean; }[][];
  /** 
   * Função para renderizar o componente no lugar a partir de um conjunto de dados de entrada.
   * Isto é tipicamente para uso interno, portanto utilize com cuidado!
   */
  generate: (data?: any) => string;
}

Permitindo instalação via astro add

Section titled Permitindo instalação via astro add

O comando astro add permite que usuários facilmente adicionem integrações e adaptadores em seus projetos. Se você quiser que sua integração seja instalável com essa ferramenta, adicione astro-integration no campo keywords do seu package.json:

{
  "name": "exemplo",
  "keywords": ["astro-integration"],
}

Assim que você publicar sua integração no npm, executar astro add exemplo irá instalar seu pacote com quaisquer dependências de pares especificadas em seu package.json. Isso também irá adicionar sua integração ao astro.config do usuário dessa forma:

astro.config.mjs
import { defineConfig } from 'astro/config';
+ import exemplo from 'exemplo';
export default defineConfig({
+  integrations: [exemplo()],
})

Todas as integrações são executadas na ordem em que são configuradas. Por exemplo, para o array [react(), svelte()] na astro.config.* de um usuário, react será executado antes de svelte.

Sua integração deve idealmente ser executável em qualquer ordem. Se isso não for possível nós recomendados documentar que sua integração precisar vir como primeira ou última no array de configuração integrations do seu usuário.

Combinar integrações em presets

Section titled Combinar integrações em presets

Uma integração também pode ser escrita como uma coleção de múltiplas, menores integrações. Nós chamamos estas coleções de presets. Ao invés de criar uma função de factory que retorna o objeto de uma única integração, um preset retorna um array de objetos de integração. Isso é útil para construir funcionalidades complexas a partir de múltiplas integrações.

integrations: [
  // Exemplo: aonde presetExemplo() retorna: [integracaoUm, integracaoDois, ...etc]
  presetExemplo()
]