🎥 На этот раз в прямом эфире — и мы всегда отзывчивы к вашим потребностям.
Astro 5.10: responsive images для всех, экспериментальные live content collections, улучшения CSP и многое другое!
- Экспериментальные live content collections
- Responsive images теперь стабильны
- Улучшения экспериментального Content Security Policy
- Настраиваемый Cloudflare Workers entrypoint
Чтобы обновить существующий проект, используйте CLI @astrojs/upgrade. Или обновите вручную:
# Рекомендуется:npx @astrojs/upgrade
# Вручную:npm install astro@latestpnpm upgrade astro --latestyarn upgrade astro --latestExperimental live content collections
Live content collections — загрузка контента в runtime вместо build time.
Build-time collections идеальны для редко меняющегося контента. Live collections — для частых обновлений и персонализации.
How it works
Live loaders выполняются при посещении страниц. Для производительности — build-time где возможно; live — для актуальности и фильтрации по пользователю.
export default defineConfig({ experimental: { liveContentCollections: true, },});src/live.config.ts:
import { defineLiveCollection } from 'astro:content';import { storeLoader } from './loaders/store';
export const products = defineLiveCollection({ type: 'live', loader: storeLoader({ apiKey: process.env.STORE_API_KEY, endpoint: 'https://api.mystore.com/v1', }),});Fetching live data
getLiveCollection() и getLiveEntry():
---import { getLiveEntry } from 'astro:content';
const { entry: product, error } = await getLiveEntry( 'products', Astro.params.slug,);
if (error) { console.error('Failed to load product:', error); return Astro.rewrite('/404');}---
<h1>{product.data.name}</h1><p> { Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format( product.data.price, ) }</p>Rendering live content
---import { getLiveEntry, render } from 'astro:content';
const { entry: product, error } = await getLiveEntry( 'products', Astro.params.slug,);
if (error) { console.error('Failed to load product:', error); return Astro.rewrite('/404');}
const { Content } = await render(product);---
<h1>{product.data.name}</h1>
<Content />Flexible filtering
---import { getLiveCollection } from 'astro:content';
const { entries, error } = await getLiveCollection('products', { category: 'electronics', priceRange: { min: 10, max: 100 },});---Error handling
Результат с data или error — предсказуемое поведение в runtime.
Type safety
Полная типобезопасность API и query options.
experimental live content collections documentation. RFC.
Responsive images are now stable
Responsive images стабильны и готовы к production!
Автоматические srcset, sizes и стили — меньше layout shift, лучше Core Web Vitals.
Get started with responsive images
layout: constrained, fixed, full-width:
export default defineConfig({ image: { responsiveStyles: true, layout: 'constrained', },});<Image src="/hero.jpg" alt="A panoramic view of the mountains" layout="full-width"/>Priority loading:
<Image src="/hero.jpg" alt="Hero image" priority />priority → loading="eager", decoding="sync", fetchpriority="high". Не более одного на страницу — для LCP element.
Enhanced cropping controls:
<Image src="/profile.jpg" alt="Profile photo" fit="cover" position="center top" width={300} height={300}/>Upgrading from experimental responsive images
Удалите experimental flag, перенесите image.experimental в stable:
export default defineConfig({ experimental: { responsiveImages: true, }, image: { responsiveStyles: true, },});Improvements to experimental Content Security Policy
Astro 5.9 — experimental CSP meta tags. 5.10: Response headers, включая static pages. On-demand — headers вместо meta (лучше в Chrome, больше директив). Static — через adapters с experimentalStaticHeaders:
import { defineConfig } from 'astro/config';import netlify from '@astrojs/netlify';
export default defineConfig({ adapter: netlify({ experimentalStaticHeaders: true, }), experimental: { csp: true, },});experimental CSP documentation.
Customizable Cloudflare Workers entrypoint
Durable Objects, Queues, Cron Triggers требуют custom entrypoint. workerEntryPoint:
import { defineConfig } from 'astro/config';import cloudflare from '@astrojs/cloudflare';
export default defineConfig({ adapter: cloudflare({ workerEntryPoint: { path: 'src/worker.ts', namedExports: ['MyDurableObject'] } }),});import type { SSRManifest } from 'astro';
import { App } from 'astro/app';import { handle } from '@astrojs/cloudflare/handler'import { DurableObject } from 'cloudflare:workers';
class MyDurableObject extends DurableObject<Env> { constructor(ctx: DurableObjectState, env: Env) { super(ctx, env) }}
export function createExports(manifest: SSRManifest) { const app = new App(manifest); return { default: { async fetch(request, env, ctx) { await env.MY_QUEUE.send("log"); return handle(manifest, app, request, env, ctx); }, async queue(batch, _env) { let messages = JSON.stringify(batch.messages); console.log(`consumed from our queue: ${messages}`); } } satisfies ExportedHandler<Env>, MyDurableObject, }}Cloudflare adapter documentation.
Спасибо Alexander Niebuhr!
Bug fixes
С релиза 5.9 — changelog.
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.
Спасибо Alexander Niebuhr, Anshul Gupta, Armand Philippot, benosmac, Han Seung Min - 한승민, Junseong Park, kato takeshi, knj, liruifengv, Martin Haug, Martin Trapp, Nin3, Paul Valladares, Quinn Blenkinsop, Thomas Bonnet, and zaitovalisher


