Вышел Astro 4.10 с экспериментальными типобезопасными переменными окружения, а также улучшениями Container API и Rewrites.
Основные новинки:
- Экспериментально: модуль astro:env
- Rewrite для всех HTTP-методов
- Встраивание Astro в серверные фреймворки
- Хелперы Container API
Чтобы обновить существующий проект, используйте CLI @astrojs/upgrade. Или обновите вручную:
# Рекомендуется:npx @astrojs/upgrade
# Вручную:npm install astro@latestpnpm upgrade astro --latestyarn upgrade astro --latestExperimental: astro:env
Astro 4.10 представляет экспериментальный встроенный модуль astro:env для удобной работы с переменными окружения.
Переменные окружения позволяют настраивать приложение разными значениями в разных средах. Но это сложно:
- часть переменных нужна на клиенте, часть — только на сервере;
- серверные переменные часто секреты — API-ключи, которые нельзя показывать на клиенте и встраивать в server build;
- некоторые переменные обязательны, другие — опциональны;
- переменные задаются в shell,
.envили build config; - рантаймы вроде Cloudflare и Deno имеют разные API чтения переменных — разница dev/prod.
Мы создали astro:env для структуры и контроля через схему прямо в конфиге:
import { defineConfig, envField } from 'astro/config';
export default defineConfig({ experimental: { env: { schema: { API_PORT: envField.number({ context: 'server', access: 'secret', default: 7000 }), PUBLIC_DASHBOARD_V2: envField.boolean({ context: 'server', access: 'public', default: false }), } } }})Используйте переменные через импорт из astro:env/server и astro:env/client:
import { PUBLIC_DASHBOARD_V2, getSecret } from 'astro:env/server';
if (PUBLIC_DASHBOARD_V2) { const API_PORT = getSecret("API_PORT") // number await fetch(`https://my-secret-api.com:${API_PORT}/v2`)}Клиентский astro:env/client — в компонентах, скриптах и любом клиентском коде. Например, показать улучшенную функцию только при включённом feature flag:
import { SOME_FEATURE_FLAG } from 'astro:env/client';
export default function() { return ( <section> { SOME_FEATURE_FLAG && ( <div id="fancy-enhanced-feature"></div> )}
... </section> )}Для переменных вне схемы — getSecret(), работает в любом рантайме (Cloudflare, Node.js, Deno).
import { getSecret } from 'astro:env/server';
function getServerEndpoint(num: number) { return getSecret(`BACKUP_SERVER_${num}`); // string | undefined}astro:env экспериментален и может измениться. Спасибо Florian Lefebvre за RFC и реализацию! Обратная связь: RFC.
Rewrite for all HTTP methods
Rewriting — экспериментальная функция из 4.9. Первая версия была для GET. В 4.10 rewrites работают для любых запросов через клонирование исходного request.
Пример rewrite в middleware для направления на версию API по умолчанию:
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(({ request, url }, next) => { if(request.method === 'POST' && url.pathname === '/api') { return next('/api/v2'); }});При rewrite создаётся новый request с новым URL. Заголовки и body копируются.
Embedding Astro
В 4.9 мы представили Container API — рендеринг Astro-компонентов вне Astro. Первый фокус — тестирование: container, container.renderToString(), проверка HTML.
Мы знали, что API захотят использовать иначе. В 4.10 можно рендерить любые компоненты из astro build — вне Astro-сайта!
Демо: Astro-in-PHP. Не судите строго, PHP-эксперты! 😅
Часть с container:
import * as components from './dist/server/all.mjs';import { renderers } from './dist/server/renderers.mjs';import { manifest } from './dist/server/entry.mjs';import { experimental_AstroContainer as AstroContainer } from 'astro/container';
const container = await AstroContainer.create({ manifest, renderers, resolve(s) { const found = manifest.entryModules[s]; if(found) { return `/astro-project/dist/client/${found}`; } return found; }});
const html = await container.renderToString(components.ReactWrapper);
// Log to the console so that PHP injects the HTML into its page.console.log(html);Container API низкоуровневый — отражает внутренний рендеринг Astro. Ждём интеграции от сообщества для упрощения встраивания. Попробуйте и покажите, куда добавили Astro!
Container API helpers
Добавлены хелперы для Container API в Vite-окружениях (vitest, Astro integrations и т.д.) при рендеринге UI framework компонентов.
Больше не нужно знать прямые пути к client/server rendering scripts каждого пакета. getContainerRenderer() даёт нужные скрипты из официальных интеграций (@astrojs/react, @astrojs/preact, @astrojs/solid-js, @astrojs/svelte, @astrojs/vue, @astrojs/lit, @astrojs/mdx). Обновите интеграции одновременно!
loadRenderers() из astro:container загружает renderers из каждого пакета:
import { experimental_AstroContainer as AstroContainer } from 'astro/container';import ReactWrapper from '../src/components/ReactWrapper.astro';import { loadRenderers } from "astro:container";import { getContainerRenderer } from "@astrojs/react";
test('ReactWrapper with react renderer', async () => { const renderers = await loadRenderers([getContainerRenderer()]) const renderers = [ { name: '@astrojs/react', clientEntrypoint: '@astrojs/react/client.js', serverEntrypoint: '@astrojs/react/server.js', }, ]; const container = await AstroContainer.create({ renderers, }); const result = await container.renderToString(ReactWrapper);
expect(result).toContain('Counter'); expect(result).toContain('Count: <!-- -->5');});Изменение типа renderers также позволит средам без Vite загружать renderer modules вручную.
Подробнее: документация Container API.
Bug Fixes
Как обычно, Astro 4.10 включает исправления и улучшения, не вошедшие в этот пост! Полные release notes, и полное раскрытие релиза 4.10 с Astro Together! Спасибо Sarah, Erika, Bjorn, Ema, Chris, Florian и всем остальным контрибьюторам релиза.
