Skip to content

Latest commit

 

History

History
724 lines (538 loc) · 28.7 KB

integrations-reference.mdx

File metadata and controls

724 lines (538 loc) · 28.7 KB
title i18nReady
API de Integrações Astro
true

import Since from '~/components/Since.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.

Exemplos

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

Referência Rápida da API

interface AstroIntegration {
  name: string;
  hooks: {
    'astro:config:setup'?: (options: {
      config: AstroConfig;
      command: 'dev' | 'build' | 'preview';
      isRestart: boolean;
      updateConfig: (newConfig: DeepPartial<AstroConfig>) => AstroConfig;
      addRenderer: (renderer: AstroRenderer) => void;
      addWatchFile: (path: URL | string) => void;
      addClientDirective: (directive: ClientDirectiveConfig) => void;
      addMiddleware: (middleware: AstroIntegrationMiddleware) => void;
      addDevToolbarApp: (pluginEntrypoint: string) => void;
      injectScript: (stage: InjectedScriptStage, content: string) => void;
      injectRoute: ({ pattern: string, entrypoint: string }) => void;
      logger: AstroIntegrationLogger;
    }) => void | Promise<void>;
    'astro:config:done'?: (options: { config: AstroConfig; setAdapter: (adapter: AstroAdapter) => void; logger: AstroIntegrationLogger; }) => void | Promise<void>;
    'astro:server:setup'?: (options: { server: vite.ViteDevServer; logger: AstroIntegrationLogger; }) => void | Promise<void>;
    'astro:server:start'?: (options: { address: AddressInfo; logger: AstroIntegrationLogger; }) => void | Promise<void>;
    'astro:server:done'?: (options: { logger: AstroIntegrationLogger; }) => void | Promise<void>;
    'astro:build:start'?: (options: { logger: AstroIntegrationLogger; }) => void | Promise<void>;
    'astro:build:setup'?: (options: {
      vite: ViteConfigWithSSR;
      pages: Map<string, PageBuildData>;
      target: 'client' | 'server';
      logger: AstroIntegrationLogger;
    }) => void | Promise<void>;
    'astro:build:generated'?: (options: { dir: URL; logger: AstroIntegrationLogger; }) => void | Promise<void>;
    'astro:build:ssr'?: (options: {
        manifest: SerializedSSRManifest;
        entryPoints: Map<RouteData, URL>;
        logger: AstroIntegrationLogger;
    }) => void | Promise<void>;
    'astro:build:done'?: (options: { dir: URL; routes: RouteData[]; logger: AstroIntegrationLogger; }) => void | Promise<void>;
  };
}

Hooks

astro:config:setup

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' | 'preview';
  isRestart: boolean;
  updateConfig: (newConfig: DeepPartial<AstroConfig>) => AstroConfig;
  addRenderer: (renderer: AstroRenderer) => void;
  addClientDirective: (directive: ClientDirectiveConfig) => void;
  addMiddleware: (middleware: AstroIntegrationMiddleware) => void;
  addDevToolbarApp: (pluginEntrypoint: string) => void;
  addWatchFile: (path: URL | string) => void;
  injectScript: (stage: InjectedScriptStage, content: string) => void;
  injectRoute: ({ pattern: string, entrypoint: string }) => void;
  logger: AstroIntegrationLogger;
}) => void | Promise<void>;

Opção config

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.

Opção command

Tipo: 'dev' | 'build' | 'preview'

  • dev - O projeto é executado com astro dev
  • build - O projeto é executado com astro build
  • preview - O projeto é executado com astro preview

Opção isRestart

Tipo: boolean

false quando o servidor de desenvolvimento inicia, true quando um recarregamento é provocado. Útil para detectar quando esta função é chamada mais de uma vez.

Opção updateConfig

Tipo: (newConfig: DeepPartial<AstroConfig>) => AstroConfig;

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()],
        }
      })
    }
  }
}

Opção addRenderer

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.

Opção addWatchFile

Tipo: URL | string

Se sua integração depende em algum arquivo de configuração que o Vite não observa e/ou precisa de um reinício completo do servidor de desenvolvimento para funcionar, o adicione com addWatchFile. Sempre que o arquivo mudar, o servidor de desenvolvimento do Astro será recarregado (você pode verificar quando um recarregamento acontece com isRestart).

Exemplo de uso:

// Deve ser um caminho absoluto!
addWatchFile('/home/usuario/.../minha-configuracao.json');
addWatchFile(new URL('./tailwind.config.js', config.root));

Opção addClientDirective

Tipo: (directive: ClientDirectiveConfig ) => void;

Adiciona uma diretiva de cliente customizada para ser usada em arquivos .astro.

Note que entrypoints de diretivas são agrupados somente através do esbuild e devem ser mantidos pequenos para que não deixem a hidratação de componentes mais lenta.

Exemplo de uso:

import { defineConfig } from 'astro/config';
import diretivaClique from './astro-diretiva-clique/registrar.js'

// https://astro.build/config
export default defineConfig({
  integrations: [
    diretivaClique()
  ],
});
/**
 * @type {() => import('astro').AstroIntegration}
 */
export default () => ({
  name: "client:click",
  hooks: {
    "astro:config:setup": ({ addClientDirective }) => {
      addClientDirective({
        name: "click",
        entrypoint: "./astro-diretiva-clique/clique.js",
      });
    },
  },
});
/**
 * Hidrata no primeiro clique da janela
 * @type {import('astro').ClientDirective}
 */
export default (load, opts, el) => {
  window.addEventListener('click', async () => {
    const hidrate = await load()
    await hidrate()
  }, { once: true })
}

Você também pode adicionar tipos para as diretivas no seu arquivo de definição de tipos da sua biblioteca:

import 'astro'
declare module 'astro' {
  interface AstroClientDirectives {
    'client:clique'?: boolean
  }
}

Opção addDevToolbarApp

Tipo: (pluginEntrypoint: string) => void;

Adiciona um aplicativo de barra de ferramentas de desenvolvimento personalizado.

Exemplo de uso:

import { defineConfig } from 'astro/config';
import integracaoDevToolbar from './app-dev-toolbar-astro/integracao.js'

// https://astro.build/config
export default defineConfig({
  integrations: [
    integracaoDevToolbar()
  ],
});
/**
 * @type {() => import('astro').AstroIntegration}
 */
export default () => ({
  name: "app-dev-toolbar",
  hooks: {
    "astro:config:setup": ({ addDevToolbarApp }) => {
      addDevToolbarApp("./app-dev-toolbar-astro/plugin.js");
    },
  },
});
/**
 * @type {import('astro').DevToolbarApp}
 */
export default {
  id: "meu-plugin",
  name: "Meu Plugin",
  icon: "<svg>...</svg>",
  init() {
    console.log("Sou um aplicativo de barra de ferramentas de desenvolvimento!")
  },
};

Opção addMiddleware

Tipo: (middleware: AstroIntegrationMiddleware ) => void;

Adiciona um middleware para ser executado em cada requisição. Recebe o módulo entrypoint que contém o middleware e um order para especificar se ele deve ser executado antes (pre) de outro middleware ou depois (post).

/**
 * @type {() => import('astro').AstroIntegration}
 */
export default () => ({
  name: "meu-pacote-de-middleware",
  hooks: {
    "astro:config:setup": ({ addMiddleware }) => {
        addMiddleware({
          entrypoint: '@mew-pacote/middleware',
          order: 'pre'
        });
    },
  },
});

O middleware é definido em um pacote com uma função onRequest, como acontece com o middleware definido pelo usuário.

import { defineMiddleware } from 'astro:middleware';

export const onRequest = defineMiddleware(async (context, request) => {
  if(context.url.pathname === '/algum-caminho-de-teste') {
    return Response.json({
      ok: true
    });
  }
});

Opção injectRoute

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({
  // Usa o padrão de sintaxe do Astro para rotas dinâmicas.
  pattern: '/subpasta/[dinamico]',
  // Usa a sintaxe de caminho relativo para uma rota local.
  entrypoint: './src/pagina-dinamica.astro'
});

Para uma integração projetada para ser instalada em outros projetos, utilize o nome do seu pacote para referenciar o entrypoint da rota. O seguinte exemplo mostra um pacote publicado para o npm como @chique/painel injetando uma rota de painel:

injectRoute({
  pattern: '/painel-chique',
  entrypoint: '@chique/painel/painel.astro'
});

Ao publicar seu pacote (@chique/painel, neste caso) no npm, você deve exportar painel.astro em seu package.json:

{
  "name": "@chique/painel",
  // ...
  "exports": { "./painel.astro": "./painel.astro" }
}

Opção injectScript

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";');

astro:config:done

Hook anterior: astro:config:setup

Próximo hook: astro:server:setup quando estiver sendo executado no modo "dev", ou astro:build:start 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>;

Opção config

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.

astro:server:setup

Hook anterior: astro:config:done

Próximo hook: astro:server:start

Quando: Logo após o servidor do Vite ser criado no modo "dev", 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>;

Opção server

Tipo: ViteDevServer

Uma instância mutável do servidor Vite usado no modo "dev". Por exemplo, esta é utilizada pela nossa integração Partytown 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
        }
      );
    }
  }
}

astro:server:start

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>;

Opção address

Tipo: AddressInfo

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

astro:server:done

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>;

astro:build:start

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'?: () => void | Promise<void>;

astro:build:setup

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>;

astro:build:generated

Hook anterior: astro:build:setup

Quando: Após uma build estática de produção terminou de gerar rotas e assets.

Por que: Para acessar rotas geradas e assets antes que artefatos de build sejam limpos. Este é um uso de caso bem incomum. Nós recomendamos usar astro:build:done a não ser que você realmente precise acessar oss arquivos gerados antes da limpeza.

'astro:build:generated'?: (options: { dir: URL }) => void | Promise<void>;

astro:build:ssr

Hook anterior: astro:build:setup

Quando: Após uma build SSR para produção tiver sido completada.

Por que: Para conseguir acesso ao manifesto de SSR e mapa dos pontos de entrada emitidos. Isso é útil quando se for criar builds SSR customizadas em plugins ou integrações.

  • entryPoints mapeia uma rota de página para o arquivo físico emitido após a build.
  • middlewareEntryPoint é o caminho de arquivo no sistema do arquivo do middleware;
'astro:build:ssr'?: (options: {
    manifest: SerializedSSRManifest,
    entryPoints: Map<RouteData, URL>,
    middlewareEntryPoint: URL
}) => void | Promise<void>;

astro:build:done

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[], pages: { pathname: string }[] }) => void | Promise<void>;

Opção dir

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));
      }
    }
  }
}

Opção routes

Tipo: RouteData[]

Uma lista de todas as rotas geradas junto de seus metadados associados.

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;
}

Opção pages

Tipo: { pathname: string }[]

Uma lista de todas as páginas geradas. É um objeto com uma propriedade.

  • pathname - o caminho finalizado da página.

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()],
})

:::caution Isso assume que a definição da sua integração é 1) uma exportação default e 2) uma função. Garanta de que isso é verdade antes de adicionar a palavra-chave astro-integration! :::

AstroIntegrationLogger

Uma instância do Astro logger, útil para escrever logs. Esse logger usa o mesmo nível de log configurado pelo CLI.

Métodos disponíveis para escrever no terminal:

  • logger.info("Mensagem");
  • logger.warn("Mensagem");
  • logger.error("Mensagem");
  • logger.debug("Mensagem");

Todas as mensagens são precedidas com um rótulo que possui o mesmo valor da integração.

import type { AstroIntegration } from "astro";
export function integraocaoFormat(): AstroIntegration {
    return {
        name: "astro-format",
        hooks: {
            "astro:build:done": (options, { logger }) => {
                // faça algo
                logger.info("Integração pronta.");
            }
        }
    }
}

O exemplo acima registrará uma mensagem que inclui a mensagem info fornecida:

[astro-format] Integração pronta.

Para registrar algumas mensagens com um rótulo diferente, use o método .fork para especificar uma alternativa ao name padrão:

import type { AstroIntegration } from "astro";
export function integracaoFormat(): AstroIntegration {
    return {
        name: "astro-format",
        hooks: {
            "astro:config:done": ({ logger }) => {
                // faça algo
                logger.info("Integração pronta.");
            },
            "astro:build:done": ({ logger }) => {
                const buildLogger = logger.fork("astro-format/build");
                // faça algo
                buildLogger.info("Build terminado.")
            }
        }
    }
}

O exemplo acima produzirá logs com [astro-format] por padrão e [astro-format/build] quando especificado:

[astro-format] Integração pronta.
[astro-format/build] Build terminado.

Ordenação de Integrações

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

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()
]

Recursos da comunidade