Astro 5.9

Автор
Emanuele Stoppa
Matt Kane

Astro 5.9 защищает ваш сайт: экспериментальная поддержка Content Security Policy, рендеринг Markdown в content loaders и многое другое!

🔒 Закручиваем гайки:

Чтобы обновить существующий проект, используйте CLI @astrojs/upgrade. Или обновите вручную:

# Рекомендуется:
npx @astrojs/upgrade
# Вручную:
npm install astro@latest
pnpm upgrade astro --latest
yarn upgrade astro --latest

Experimental Content Security Policy support

Cross-site scripting (XSS) — одна из самых частых угроз. По умолчанию страницы могут загружать любые скрипты и стили откуда угодно. Content Security Policy (CSP) ограничивает это — мощная защита от XSS.

Реализовать вручную сложно — проще, если фреймворк делает за вас. Astro 5.9 добавляет экспериментальную поддержку CSP из коробки. Самый upvoted feature request — надеемся, ожидание того стоило!

Функция для всех render modes (static, dynamic, SPA) с гибкостью и type-safety. Можно отказаться от unsafe-inline, использовать любые фичи Astro, любой адаптер и runtime — дополнительный слой безопасности.

How it works

Astro работает везде — static, serverless, Node, edge, React, Vue, Svelte. CSP должен работать везде с любой библиотекой.

Два подхода:

  • nonce header — случайное значение на запрос в HTML.
  • hashes всех ресурсов — только ожидаемые скрипты и стили выполняются.

nonce проще, но нужен server/edge для генерации и перезаписи HTML — не для static hosts и SPA с динамической инъекцией.

Хеши сложнее — нужно знать точное содержимое каждого script и stylesheet. Но поддерживает больше сценариев — наш выбор.

CSP через Content-Security-Policy header или <meta http-equiv='content-security-policy'>. Header не подходит для static и SPA — выбрали <meta>.

Astro генерирует <meta> с хешами всех скриптов и стилей на странице, включая динамически загружаемые!

Usage

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
experimental: {
csp: true
}
})

Если CSP header уже есть через middleware — браузер использует более строгую политику из header и <meta>.

Дополнительный контроль через конфигурацию:

astro.config.mjs
import { defineConfig } from "astro/config"
export default defineConfig({
experimental: {
csp: {
algorithm: "`SHA-512",
directives: [
"default-src: 'self'",
"image-src: 'https://images.cdn.example.com'"
],
styleDirective: {
hashes: [
"sha384-somehash"
],
resources: ["self", "https://styles.cdn.example.com"]
},
scriptDirective: {
hashes: [
"sha384-somehash"
],
resources: ["self", "https://script.cdn.example.com"],
strictDynamic: true
}
}
}
})

experimental CSP documentation.

Rendering Markdown in content loaders

Content collections поддерживали Markdown через render() и <Content />; Astro 5 — любой loader может рендерить HTML. Markdown в loader требовал собственного парсинга — несогласованно с остальным сайтом и настройками Markdown.

Astro 5.9 добавляет renderMarkdown в контекст loader — тот же renderer и плагины, что для Markdown-файлов.

Возвращает html и metadata — как rendered у entries:

import type { Loader } from 'astro/loaders';
import { loadFromCMS } from './cms';
export function myLoader(settings): Loader {
return {
name: 'my-loader',
async load({ renderMarkdown, store }) {
const entries = await loadFromCMS();
store.clear();
for (const entry of entries) {
store.set(entry.id, {
id: entry.id,
data: entry,
rendered: await renderMarkdown(entry.content),
});
}
},
};
}

С кастомным loader — render() и <Content /> как для локального Markdown:

---
import { getEntry, render } from 'astro:content';
const entry = await getEntry('my-collection', Astro.params.id);
const { Content } = await render(entry);
---
<Content />

content loaders documentation.

Disable default styles in experimental responsive images

При experimental responsive images Astro применяет дефолтные стили для корректного ресайза. Обычно это нужно — низкая специфичность, ваши стили перекрывают.

Иногда дефолты не нужны — особенно с Tailwind 4 и CSS cascade layers.

image.experimentalDefaultStyles (с Astro 5.8.1), по умолчанию true:

export default {
image: {
experimentalDefaultStyles: false,
},
experimental: {
responsiveImages: true,
},
};

responsive images documentation.

Allow adapters to suppress logs about feature support

Адаптеры декларируют поддержку функций Astro. При сборке Astro логирует предупреждения о неподдерживаемых функциях. Адаптеры могут логировать свои сообщения — путаница с Astro-логами.

Astro 5.9: suppress: "all" или suppress: "default":

setAdapter({
name: 'my-astro-integration',
supportedAstroFeatures: {
staticOutput: "stable",
hybridOutput: "stable",
sharpImageService: {
support: "limited",
message: "The sharp image service isn't available in the deploy environment, but will be used by prerendered pages on build.",
suppress: "default",
},
}
})

Adapters API reference.

Community

Команда Astro:

Ben Holmes, Caleb Jasik, Chris Swithinbank, Emanuele Stoppa, Erika, Florian Lefebvre, Fred Schott, Fuzzy, HiDeoo, Luiz Ferraz, Matt Kane, Matthew Phillips, Nate Moore, Reuben Tier, Sarah Rainsberger, and Yan Thomas.

Спасибо , Adriel Martinez, Alexander Niebuhr, Ankur Oberoi, Ariel K, Armand Philippot, Arpan Patel, Ben Limmer, Bjorn Lu, Bugo, Cansin Acarer, Daniel Puscher, Elliot Dong, Hiromasa Fujimori, Hunter Bertoson, Igor Teplostanski, JiPai, Joe, Jonás Perusquía Morales, Junseong Park, Juraj Kapsz, kato takeshi, Kenzo Fachin, knj, liruifengv, Louis Escher, Nin3, Paul Valladares, Reuben Tier, Robin Bühler, Stephen Hendricks, sugardave, Thomas Bonnet, and vivek lokhande.