Улучшенные изображения в Astro

Автор
Erika
Fred Schott

В прошлом году мы опубликовали первую интеграцию изображений Astro (@astrojs/image) вместе с Astro 1.0. Цель была проста: сделать оптимизацию изображений effortless в Astro.

Теперь, через год и 2,5 миллиона загрузок, мы готовы поделиться новым видением работы с изображениями в Astro: полностью переработанным, с новыми функциями, более высокой скоростью и лучшим пользовательским опытом:

Это обновление будет доступно всем пользователям начиная с Astro 3.0, но вы можете подключиться уже сегодня, установив флаг experimental.assets в конфигурации. Также можно включить, передав флаг --experimental-assets в Astro CLI.

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

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

Как это работает

С самого начала мы хотели API изображений, максимально минимальный. Мы начали с оригинального API компонента <Image /> из интеграции @astrojs/image и добавили несколько новых штрихов и изменений.

---
// Import the <Image /> component
import { Image } from "astro:assets"
// Import a reference to the image itself
import myImage from "../assets/penguin.png"
---
<Image src={myImage} alt="A very cool penguin!" />
<!-- Result: -->
<img
src="/_astro/penguin.XXXXXX.webp"
width="300"
height="300"
loading="lazy"
decoding="async"
alt="A very cool penguin!"
/>

Но не дайте минимальному API обмануть вас:

  • Astro оптимизирует изображение в современном формате WebP (по умолчанию).
  • Для доступности обязательный prop alt улучшает сайт для screen reader и других инструментов.
  • Для ещё более быстрой загрузки страницы атрибуты loading и decoding добавляются по умолчанию.
  • Для пользовательского опыта атрибуты width и height всегда включены, чтобы предотвратить layout shift (подробнее ниже).

Гибкость была ещё одной целью. Мы добавили функцию getImage() для оптимизации изображения в проекте по требованию без компонента <Image />. Используйте её для собственного Image-компонента под любой use case.

---
// Example: Instead of creating an `img` tag,
// apply an optimized image to a div using CSS.
import { getImage } from "astro:assets"
import myImage from "../assets/penguin.png"
const optimizedBackgroundImage = await getImage({ src: myImage })
---
<div style={`background-image: url('${optimizedBackgroundImage.src}')`}></div>
<!-- Result: -->
<div style="background-image: url('/_astro/penguin.XXXXXX.webp')"></div>

Автоматическая защита от layout shift

Cumulative Layout Shift (CLS) — важная метрика для оптимизации производительности сайта. Она входит в 3 Core Web Vitals Google и сильно влияет на оценку производительности Lighthouse.

Новый компонент <Image /> Astro автоматически защищает сайт от layout shift. Он выводит явную высоту и ширину для каждого изображения и включает их в сгенерированный тег <img>. С явными размерами изображение не сдвигает layout страницы при загрузке.

Выходной HTML — всегда простой элемент <img>, поэтому можно применять дополнительные CSS-стили для продвинутых адаптивных layouts вроде fill и cover без риска layout shift.

<Image
src={myImage}
alt="A very cool penguin!"
style="height: 100%; width: 100%; object-fit: cover;"
/>

Автоматическая поддержка Markdown и MDX

Одно из крупнейших улучшений по сравнению с оригинальной интеграцией @astrojs/image — полная поддержка Markdown, Markdoc и MDX. Теперь можно ссылаться на изображения относительным путём в Markdown-контенте или frontmatter, и Astro автоматически их оптимизирует.

![A starry night sky](../../assets/stars.png)
<!-- Result: -->
<img
src="/_astro/stars.XXXXXX.webp"
width="300"
height="300"
loading="lazy"
decoding="async"
alt="A starry night sky"
/>

Вот и всё! Изображение stars.png будет автоматически оптимизировано в финальном HTML. Можно также использовать компонент <Image /> прямо в MDX для более тонкого контроля атрибутов, но в большинстве случаев настроек по умолчанию достаточно для оптимального размера файла и отличного качества.

Интеграция со сторонними сервисами изображений

Некоторые пользователи неизбежно захотят использовать Astro со внешним image service, вроде Cloudinary или Vercel. С учётом расширяемости мы создали Astro Image Services API для подключения Astro к выбранному стороннему image service.

Этот API содержит небольшой набор hooks, управляющих обработкой изображений внутри Astro. Большинству пользователей Astro не нужно трогать этот API напрямую, но авторы интеграций могут использовать его для расширения поведения Astro по умолчанию своей логикой обработки изображений.

Простой image service экспортирует функцию getURL() для создания src URL каждого изображения, указывающего на домен image service или кастомный URL path:

// Example: A basic image service that generates custom URLs
export const service = {
getURL({ src, width, height }) {
return `https://mywebsitethatgeneratesimages.com/${src}?width=${width}&height=${height}`
},
}

Более сложные image services могут использовать hooks вроде transform() для прямой генерации и возврата изображения на этапе сборки. Полный walkthrough API — в документации Image Services.

Пользователи Vercel могут попробовать это сегодня с официальным Vercel adapter для Astro. При использовании этого adapter изображения будут использовать Vercel-специфичный URL endpoint, позволяя Vercel заниматься оптимизацией за вас.

Мы с нетерпением ждём, как сообщество использует эту функцию для интеграции Astro с любимыми сервисами и пополнения растущего списка интеграций Astro!

Что дальше?

Мы продолжим собирать вашу обратную связь по мере приближения к официальному релизу в Astro 3.0 позже в этом году. Если найдёте проблемы, не стесняйтесь сообщить — создайте issue или напишите в нашем Discord.

Здесь мы не успели затронуть кэширование между сборками, управление форматом файла и поддержку MDX. Подробнее об использовании функции — в документации assets.