Marginalia

Astroの画像最適化を利用する

ブログ記事中の画像を表示するために、Astroの画像最適化機能を使うようにした。これまではオリジナルの画像をそのままimgタグに渡しており、widthheightも設定していなかったため、読み込みパフォーマンスの面でもレイアウトシフトの面でも問題があったが、手抜きで放置していた。

Astroの画像最適化は、Imageコンポーネントを使うのが簡単だ。だが、ブログの作りの上で工夫が必要な点があった。

ブログ記事中の画像は外部URLで配信されているものと、CMS(Notion)で管理しているローカル管理のものがある。今回はローカル管理のものに限ってImageコンポーネントを使うようにした。外部URLのものはせめてもの最適化ということでdecoding="async”だけは有効にした。

{
  external ? (
    <img src={url} decoding="async" />
  ) : (
    <AstroImage
      src={images[url]()}
    />
  )
}

ローカル画像のほうは、次のガイドを参考に動的読み込みを使って解決した。

const images = import.meta.glob<{ default: ImageMetadata }>('/src/content/images/**/*.{jpg,jpeg,png,gif,svg}');
if (!external && !images[url]) {
  throw new Error(`"${url}" does not exist in glob: "src/content/images/**/*"`);
}

はじめは直接 import(url) の戻り値をImageコンポーネントに渡していたが、astro devでは読み込めるものの、astro buildすると画像ファイルの読み込みに失敗した。Viteの内部的なビルドシステムに起因してそうだ。import.meta.globを使うやり方では問題なく動作した。

ということで、Astroのビルド時に画像の幅・高さの設定とwebpへの最適化、遅延読み込みの有効化などが自動的に行われるようになった。めでたしめでたし。