Пропустить до содержимого

API интеграции Astro

Интеграции Astro добавляют новую функциональность и поведение в ваш проект всего несколькими строками кода.

Эта справочная страница предназначена для тех, кто пишет свои собственные интеграции. Чтобы узнать, как использовать интеграцию в своем проекте, ознакомьтесь с нашим Руководством по использованию интеграций.

Официальные интеграции Astro могут служить вам в качестве примера при создании собственных интеграций.

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

Следующий хук: astro:config:done

Когда: При инициализации, перед тем как Vite или конфигурация Astro будут разрешены.

Зачем: Для расширения конфигурации проекта. Это включает обновление конфигурации Astro, применение плагинов Vite, добавление рендеров компонентов и внедрение скриптов на страницу.

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

Тип: AstroConfig

Доступная только для чтения копия пользовательской конфигурации Astro. Это разрешается до запуска любых других интеграций. Если вам нужна копия конфигурации после того, как все интеграции завершили обновление своих конфигураций, см. хук astro:config:done.

Тип: 'dev' | 'build' | 'preview'

  • dev — Проект выполняется с помощью astro dev
  • build — Проект выполняется с помощью astro build
  • preview — Проект выполняется с помощью astro preview

Тип: boolean

false когда сервер разработки запускается, true когда происходит перезагрузка. Полезно для определения, когда эта функция вызывается более одного раза.

Тип: (newConfig: DeepPartial<AstroConfig>) => AstroConfig;

Функция обратного вызова для обновления предоставленной пользователем конфигурации Astro. Любая предоставленная вами конфигурация будет объединена с пользовательской конфигурацией + обновлениями конфигурации других интеграций, поэтому вы можете не включать ключи!

Например, предположим, что вам нужно добавить в проект пользователя плагин Vite:

import bananaCSS from '@vitejs/official-banana-css-plugin';
export default {
name: 'banana-css-integration',
hooks: {
'astro:config:setup': ({ updateConfig }) => {
updateConfig({
vite: {
plugins: [bananaCSS()],
}
})
}
}
}

Тип: (renderer: AstroRenderer ) => void; Примеры: lit, svelte, react, preact, vue, solid

Функция обратного вызова для добавления рендерера фреймворка компонентов (например, React, Vue, Svelte и т. д.). Вы можете просмотреть примеры и определение типа выше для более продвинутых опций, но вот два основных варианта, о которых стоит знать:

  • clientEntrypoint - путь к файлу, который выполняется на клиенте при каждом использовании вашего компонента. Это в основном для рендеринга или гидратации вашего компонента с помощью JS.
  • serverEntrypoint - путь к файлу, который выполняется во время запросов с сервера или статической сборки всякий раз, когда используется ваш компонент. Они должны рендерить компоненты в статическую разметку, с хуками для гидратации, если это применимо. Классическим примером является обратный вызов renderToString от React.

Тип: URL | string

Если ваша интеграция зависит от какого-то конфигурационного файла, за которым Vite не следит и/или для вступления в силу которого требуется полный перезапуск сервера разработки, добавьте его с помощью addWatchFile. Каждый раз, при изменении этого файла, сервер разработки Astro будет перезагружен (вы можете проверить, когда произойдет перезагрузка с помощью isRestart).

Пример использования:

// Путь должен быть абсолютным!
addWatchFile('/home/user/.../my-config.json');
addWatchFile(new URL('./tailwind.config.js', config.root));

Добавлено в: astro@2.6.0

Тип: (directive: ClientDirectiveConfig ) => void;

Добавляет пользовательскую директиву клиента, которая будет использоваться в файлах .astro.

Обратите внимание, что точки входа директив поставляются только через esbuild и должны быть небольшими, чтобы не замедлять гидратацию компонентов.

Пример использования:

astro.config.mjs
import { defineConfig } from 'astro/config';
import clickDirective from './astro-click-directive/register.js'
// https://astro.build/config
export default defineConfig({
integrations: [
clickDirective()
],
});
astro-click-directive/register.js
/**
* @type {() => import('astro').AstroIntegration}
*/
export default () => ({
name: "client:click",
hooks: {
"astro:config:setup": ({ addClientDirective }) => {
addClientDirective({
name: "click",
entrypoint: "./astro-click-directive/click.js",
});
},
},
});
astro-click-directive/click.js
/**
* Гидрация при первом нажатии на окно
* @type {import('astro').ClientDirective}
*/
export default (load, opts, el) => {
window.addEventListener('click', async () => {
const hydrate = await load()
await hydrate()
}, { once: true })
}

Вы также можете добавить типы для директив в файл определения типов вашей библиотеки:

astro-click-directive/index.d.ts
import 'astro'
declare module 'astro' {
interface AstroClientDirectives {
'client:click'?: boolean
}
}

Добавлено в: astro@3.4.0

Тип: (pluginEntrypoint: string) => void;

Добавляет пользовательское приложение панели инструментов разработчика.

Пример использования:

astro.config.mjs
import { defineConfig } from 'astro/config';
import devToolbarIntegration from './astro-dev-toolbar-app/integration.js'
// https://astro.build/config
export default defineConfig({
integrations: [
devToolbarIntegration()
],
});
astro-dev-toolbar-app/integration.js
/**
* @type {() => import('astro').AstroIntegration}
*/
export default () => ({
name: "dev-toolbar-app",
hooks: {
"astro:config:setup": ({ addDevToolbarApp }) => {
addDevToolbarApp("./astro-dev-toolbar-app/plugin.js");
},
},
});
astro-dev-toolbar-app/plugin.js
/**
* @type {import('astro').DevToolbarApp}
*/
export default {
id: "my-plugin",
name: "My Plugin",
icon: "<svg>...</svg>",
init() {
console.log("I'm a dev toolbar app!")
},
};

Добавлено в: astro@3.5.0

Тип: (middleware: AstroIntegrationMiddleware ) => void;

Добавляет промежуточное ПО,, которое будет запускаться при каждом запросе. Принимает модуль entrypoint, содержащий промежуточное ПО, и order, указывающий, должно ли оно запускаться до (pre) других промежуточных программ или после (post).

@my-package/integration.js
/**
* @type {() => import('astro').AstroIntegration}
*/
export default () => ({
name: "my-middleware-package",
hooks: {
"astro:config:setup": ({ addMiddleware }) => {
addMiddleware({
entrypoint: '@my-package/middleware',
order: 'pre'
});
},
},
});

Промежуточное ПО определяется в пакете с функцией onRequest, также как и с пользовательским промежуточным ПО.

@my-package/middleware.js
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(async (context, request) => {
if(context.url.pathname === '/some-test-path') {
return Response.json({
ok: true
});
}
});

Тип: ({ pattern: string, entrypoint: string }) => void;

Функция обратного вызова для инъекции маршрутов в проект Astro. Инжектируемые маршруты могут быть страницами .astro или обработчиками маршрутов .js и .ts.

injectRoute принимает объект с pattern и entrypoint.

  • pattern - куда маршрут должен быть выведен в браузере, например /foo/bar. Шаблон может использовать синтаксис пути к файлу Astro для обозначения динамических маршрутов, например /foo/[bar] или /foo/[...bar]. Обратите внимание, что расширение файла не требуется в pattern.
  • entrypoint - обычный модульный указатель, указывающий на страницу .astro или обработчик маршрута .js/.ts, который обрабатывает маршрут, обозначенный в pattern.

Пример использования:

injectRoute({
// Используйте синтаксис шаблонов Astro для динамических маршрутов.
pattern: '/subfolder/[dynamic]',
// Используйте синтаксис относительного пути для локального маршрута.
entrypoint: './src/dynamic-page.astro'
});

Для интеграции, предназначенной для установки в другие проекты, используйте имя пакета для ссылки на точку входа в маршрут. В следующем примере показан пакет, опубликованный в npm под именем @fancy/dashboard, инжектирующий маршрут панели инструментов:

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

При публикации вашего пакета (в данном случае @fancy/dashboard) на npm, вы должны экспортировать dashboard.astro в ваш package.json:

package.json
{
"name": "@fancy/dashboard",
// ...
"exports": { "./dashboard.astro": "./dashboard.astro" }`
}

Тип: (stage: InjectedScriptStage, content: string) => void;

Функция обратного вызова для вставки строки содержимого JavaScript на каждую страницу.

Параметр stage указывает на то, как должен быть вставлен этот скрипт (content). Некоторые этапы позволяют вставлять скрипты без модификации, другие - оптимизировать во время шага сборки Vite:

  • "head-inline": Вставляется в тег <script> в <head> каждой страницы. Не оптимизирован или разрешен Vite.

  • "before-hydration": Импортируется на стороне клиента, перед запуском скрипта гидратации. Оптимизируется и разрешается Vite.

  • "page": Аналогично head-inline, за исключением того, что импортируемый фрагмент обрабатывается Vite и объединяется с любыми другими тегами <script>, определенными внутри компонентов Astro на странице. Скрипт будет загружен с помощью <script type="module"> в конечный вывод страницы, оптимизирован и разрешен Vite.

  • page-ssr: Импортируется как отдельный модуль в frontmatter каждого компонента страницы Astro. Поскольку на этом этапе импортируется ваш скрипт, глобальный Astro недоступен, и ваш скрипт будет запущен только один раз при первой оценке import.

    Основное применение этапа page-ssr - это вставка CSS импорта на каждую страницу для оптимизации и разрешения Vite:

    injectScript('page-ssr', 'import "global-styles.css";');

Предыдущий хук: astro:config:setup

Следующий хук: astro:server:setup при работе в режиме “dev”, или astro:build:start при “production” сборке.

Когда: После того, как конфигурация Astro была разрешена, и другие интеграции выполнили свои хуки astro:config:setup.

Зачем: Для получения окончательной конфигурации для использования в других хуках.

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

Тип: AstroConfig

Доступная только для чтения копия предоставленной пользователем конфигурации Astro. Это разрешается после выполнения других интеграций.

Предыдущий хук: astro:config:done

Следующий хук: astro:server:start

Когда: Сразу после создания сервера Vite в режиме “dev”, но перед событием listen(). См. API createServer Vite для получения дополнительной информации.

Зачем: Для обновления параметров сервера Vite и промежуточного ПО.

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

Тип: ViteDevServer

Изменяемый экземпляр сервера Vite, используемый в режиме “dev”. Например, это используется нашей интеграцией Partytown для вставки сервера Partytown в качестве промежуточного ПО:

export default {
name: 'partytown',
hooks: {
'astro:server:setup': ({ server }) => {
server.middlewares.use(
function middleware(req, res, next) {
// handle requests
}
);
}
}
}

Предыдущий хук: astro:server:setup

Следующий хук: astro:server:done

Когда: Сразу после срабатывания события listen() сервера.

Зачем: Для перехвата сетевых запросов по указанному адресу. Если вы намерены использовать этот адрес для промежуточного ПО, рассмотрите возможность использования astro:server:setup вместо этого.

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

Тип: AddressInfo

Адрес, семейство и номер порта, предоставленные модулем Net Node.js.

Следующий хук: astro:server:start

Когда: Сразу после закрытия сервера разработки.

Зачем: Для выполнения любых событий очистки, которые могут быть запущены во время хуков astro:server:setup или astro:server:start.

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

Предыдущий хук: astro:config:done

Следующий хук: astro:build:setup

Когда: После события astro:config:done, но перед началом производственной сборки.

Зачем: Для настройки любых глобальных объектов или клиентов, необходимых во время производственной сборки. Это также может расширить параметры конфигурации сборки в API адаптера.

'astro:build:start'?: () => void | Promise<void>;

Предыдущий хук: astro:build:start

Следующий хук: astro:build:ssr

Когда: После хука astro:build:start, запускается непосредственно перед сборкой.

Зачем: На этом этапе конфигурация Vite для сборки полностью сконструирована, это ваш последний шанс ее изменить. Это может быть полезно, например, для перезаписи некоторых значений по умолчанию. Если вы не уверены, следует ли использовать этот хук или astro:build:start, используйте вместо этого astro:build:start.

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

Предыдущий хук: astro:build:setup

Когда: После завершения статической производственной сборки, генерирующей маршруты и ассеты.

Зачем: Для доступа к сгенерированным маршрутам и ресурсам до очистки артефактов сборки. Это очень редкий случай использования. Мы рекомендуем использовать astro:build:done, если вам действительно нужен доступ к сгенерированным файлам перед очисткой.

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

Предыдущий хук: astro:build:setup

Когда: После завершения производственной сборки с SSR.

Зачем: Для доступа к манифесту SSR и карте излученных точек входа. Это полезно при создании пользовательских сборок SSR в плагинах или интеграциях.

  • entryPoints сопоставляет маршрут страницы с физическим файлом, созданным после сборки;
  • middlewareEntryPoint - путь файловой системы к файлу промежуточного ПО;
'astro:build:ssr'?: (options: {
manifest: SerializedSSRManifest,
entryPoints: Map<RouteData, URL>,
middlewareEntryPoint: URL
}) => void | Promise<void>;

Предыдущий хук: astro:build:ssr

Когда: После завершения сборки (SSG или SSR).

Зачем: Чтобы получить доступ к сгенерированным маршрутам и ассетам для расширения (например, скопировать содержимое в сгенерированную директорию /assets). Если вы планируете преобразовывать сгенерированные ассеты, мы рекомендуем использовать API плагинов Vite и настройку через astro:config:setup вместо этого.

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

Тип: URL

URL-путь к выходному каталогу сборки. Обратите внимание, что если вам нужна корректная строка абсолютного пути, вам следует использовать встроенную в Node утилиту fileURLToPath.

import { writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
export default function myIntegration() {
return {
hooks: {
'astro:build:done': async ({ dir }) => {
const metadata = await getIntegrationMetadata();
// Use fileURLToPath to get a valid, cross-platform absolute path string
const outFile = fileURLToPath(new URL('./my-integration.json', dir));
await writeFile(outFile, JSON.stringify(metadata));
}
}
}
}

Тип: RouteData[]

Список всех сгенерированных маршрутов вместе с их метаданными.

Вы можете ссылаться на полный тип RouteData ниже, но наиболее часто используемые свойства:

  • component — путь к входному файлу относительно корня проекта
  • pathname — URL выходного файла (не определен для маршрутов с параметрами [dynamic] и [...spread])
interface RouteData {
/** Определяет, является ли данный маршрут HTML-страницей или конечной точкой без HTML */
type: 'page' | 'endpoint';
/** URL исходного компонента */
component: string;
/**
* Путь URL-адреса вывода, по которому будет обслуживаться этот маршрут
* Примечание: будет неопределен для маршрутов с параметрами `[dynamic]` и `[...spread]`
*/
pathname?: string;
/**
* Регулярное выражение, используемое для сопоставления входного URL с запрошенным маршрутом
* Например, "[fruit]/about.astro" создаст шаблон: /^\/([^/]+?)\/about\/?$/
* где pattern.test("banana/about") возвращает "true"
*/
pattern: RegExp;
/**
* Параметры динамического и развернутого маршрута
* Например, "/pages/[lang]/[..slug].astro" выведет параметры ['lang', '...slug']
*/
params: string[];
/**
* Аналогично полю "params", но с дополнительной связанной метаданными
* Например, "/pages/[lang]/index.astro" выведет сегменты
* [[ { content: 'lang', dynamic: true, spread: false } ]]
*/
segments: { content: string; dynamic: boolean; spread: boolean; }[][];
/**
* Функция для рендеринга компонента на месте из набора входных данных.
* Обычно используется для внутреннего использования, поэтому вызывайте с осторожностью!
*/
generate: (data?: any) => string;
}

Тип: { pathname: string }[]

Список всех сгенерированных страниц. Это объект с одним свойством.

  • pathname — окончательный путь страницы.

Команда astro add позволяет пользователям легко добавлять интеграции и адаптеры в свой проект. Если вы хотите, чтобы ваша интеграция могла быть установлена с помощью этого инструмента, добавьте astro-integration в поле keywords в вашем package.json:

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

Как только вы опубликуете свою интеграцию на npm, запуск astro add example установит ваш пакет с любыми зависимостями, указанными в вашем package.json. Это также применит вашу интеграцию к пользовательскому astro.config, как показано ниже:

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

Экземпляр логгера Astro, полезный для записи логов. Этот логгер использует тот же уровень логирования, настроенный через CLI.

Доступные методы для записи в терминал:

  • logger.info("Сообщение");
  • logger.warn("Сообщение");
  • logger.error("Сообщение");
  • logger.debug("Сообщение");

Все сообщения дополняются меткой, которая имеет то же значение, что и интеграция.

integration.ts
import type { AstroIntegration } from "astro";
export function formatIntegration(): AstroIntegration {
return {
name: "astro-format",
hooks: {
"astro:build:done": ({ logger }) => {
// делаем что-то
logger.info("Интеграция готова.");
}
}
}
}

Приведенный выше пример будет регистрировать сообщение, которое включает предоставленное сообщение info:

Terminal window
[astro-format] Интеграция готова.

Чтобы записать в журнал несколько сообщений с другой меткой, используйте метод .fork, чтобы указать альтернативу стандартному name:

integration.ts
import type { AstroIntegration } from "astro";
export function formatIntegration(): AstroIntegration {
return {
name: "astro-format",
hooks: {
"astro:config:done": ({ logger }) => {
// делаем что-то
logger.info("Интеграция готова.");
},
"astro:build:done": ({ logger }) => {
const buildLogger = logger.fork("astro-format/build");
// делаем что-то
buildLogger.info("Сборка завершена.")
}
}
}
}

Приведенный выше пример по умолчанию будет создавать логи с [astro-format], и [astro-format/build] при указании:

Terminal window
[astro-format] Интеграция готова.
[astro-format/build] Сборка завершена.

Все интеграции запускаются в том порядке, в котором они настроены. Например, для массива [react(), svelte()] в пользовательском файле astro.config.*, react будет запущен раньше svelte.

В идеале ваша интеграция должна выполняться в любом порядке. Если это невозможно, мы рекомендуем документировать, что ваша интеграция должна быть первой или последней в массиве конфигурации integrations пользователя.

Интеграция также может быть написана как набор нескольких более мелких интеграций. Мы называем эти наборы пресетами. Вместо создания функции-фабрики, возвращающей единственный объект интеграции, пресет возвращает массив объектов интеграции. Это полезно для создания сложных функций из нескольких интеграций.

integrations: [
// Пример: где examplePreset() возвращает: [integrationOne, integrationTwo, ...etc]
examplePreset()
]