
爆速静的サイトジェネレーター「Astro」での、基本的な画像の取り扱いと、便利な画像最適化の手法についてまとめてみました。
この記事は、Astroのバージョン2.1.4に対応しています。
Astroのインストール
npmでAstroのプロジェクトを作成します。
# npmで新しいプロジェクトを作成する
npm create astro@latest
インストールガイドの中で、Include sample files
を選択し、以下のような構成でAstroが展開された状態になっているとします(一部省略)。
(以後、TypeScriptを使用している前提で説明していきます)
astro-project/
├── astro.config.mjs
├── node_modules
├── package.json
├── public
├── src
│ ├── layout
│ │ └── Layout.astro
│ ├── pages
│ │ └── index.astro
│ └── env.d.ts
└── tsconfig.json
画像の表示方法3選
Astroでは、ページ内に画像を表示するのに複数の手段があるため、Webページ用の挿絵としては少しヘビーな以下の画像を使ってそれぞれの手法を検証します。
検証用画像:

画像サイズ:2048px × 1533px
画像形式:JPEG
画像容量:647KB
publicディレクトリとimgタグを使用する
public
ディレクトリの中にimages
というディレクトリを作成し、その中にsample.jpg
を配置します。
astro-project/
├── node_modules
├── public
│ └── images
│ └──sample.jpg
├── src
│ ├── layout
│ │ └── Layout.astro
│ ├── pages
│ │ └── index.astro
続いて、pages/index.astro
に通常のimgタグを記述し、public
ディレクトリ内のsample.jpg
を指定します。
このとき、imgのsrc
はpublic
ディレクトリから見た相対パスにします。
---
import Layout from '../layouts/Layout.astro';
---
<Layout title="Astroでの画像の表示方法">
<img src="/images/sample.jpg" alt="Sample" />
</Layout>
<style>
img {
max-width: 100%;
height: auto;
}
</style>
ここまで記述したら、
npm run dev
で、画像が表示されていることを確かめてみましょう。

画像が正しく表示されていたら、
npm run build
で、Astroをビルドすると、dist
ディレクトリ内に静的ファイル一式が生成されます。
astro-project/
├── node_modules
├── dist
│ ├── _astro
│ ├── images
│ │ └──sample.jpg
│ └── index.html
├── public
└── src
先ほどpublic/images/sample.jpg
に配置した画像は、dist/images/sample.jpg
として展開されています。展開後の画像情報を見ると、画像サイズも容量も同じ状態でコピーされていることがわかります。

画像サイズ:2048px × 1533px
画像形式:JPEG
画像容量:647KB
このように、public
配下に配置したファイルは画像を含め、ビルド後に(Astroによる最適化の処理をされずに)dist
ディレクトリにそのまま展開されるため、深く考えずにimgタグによる記述で画像を表示することができます。
srcディレクトリとimgタグを使用する
次に、astroファイルなどと同じ、src
ディレクトリに画像を配置して表示するパターンです。
src
ディレクトリの中にimages
というディレクトリを作成し、その中にsample.jpg
を配置します。
astro-project/
├── node_modules
├── public
├── src
│ ├── images
│ │ └──sample.jpg
│ ├── layout
│ │ └── Layout.astro
│ ├── pages
│ │ └── index.astro
この状態で、pages/index.astro
でsrc/images/sample.jpg
をimportして利用することができます。
(importするパスは、astroファイルから見た相対パスになります)
index.astro
側には、先ほどと同じくimgタグで、importした画像をsrc
として記述します。
---
import Layout from '../layouts/Layout.astro';
import localImage from '../images/sample.jpg';
---
<Layout title="Astroでの画像の表示方法">
<img src={localImage} alt="Sample" />
</Layout>
<style>
img {
max-width: 100%;
height: auto;
}
</style>
プレビューすると先ほどと同じく画像が表示されます。

これをビルドすると、
astro-project/
├── node_modules
├── dist
│ ├── _astro
│ │ ├──index.10c61ba9.css
│ │ └──sample.a9447241.jpg
│ └── index.html
├── public
└── src
dist/_astro
ディレクトリに画像が展開されます(このとき、src
ディレクトリ内での画像が配置された階層に関係なく、_astro
直下に展開されるようです)。展開後の画像は、ファイル名は自動的に一意のものに変換されますが、サイズや画像形式、容量は同一となっています。

画像サイズ:2048px × 1533px
画像形式:JPEG
画像容量:647KB
正直言うと、このやり方をするくらいなら、先のpublicディレクトリを使った手法か、後述する画像インテグレーションを使用したほうが良いと思います。
Astro画像インテグレーションを使用する
最後に、Astro画像インテグレーションを使って、画像の最適化を行う方法です。
まず、以下のように@astrojs/image
をクイックインストールします。
npx astro add image
@astrojs/image
をクイックインストールすると、astro.config.mjs
にインテグレーションの記述が自動的に追加されます。
astro.config.mjs
import { defineConfig } from 'astro/config';
import image from "@astrojs/image";
// https://astro.build/config
export default defineConfig({
integrations: [image()]
});
続いて、env.d.ts
において@astrojs/image
を使用する際に必要な型情報に差し替えます。
env.d.ts
// <reference types="astro/client" />
/// <reference types="@astrojs/image/client" />
そして、src
ディレクトリの中にimages
というディレクトリを作成し、その中にsample.jpg
を配置します。
astro-project/
├── node_modules
├── public
├── src
│ ├── images
│ │ └──sample.jpg
│ ├── layout
│ │ └── Layout.astro
│ ├── pages
│ │ └── index.astro
index.astro
側は、@astrojs/image/components
からImage
コンポーネントをimpotしておきます(1行目)。そしてsrcディレクトリの画像を相対パスでimpotし、imgタグではなくImage
を使って記述します。
---
import { Image } from '@astrojs/image/components';
import Layout from '../layouts/Layout.astro';
import localImage from '../images/sample.jpg';
---
<Layout title="Astroでの画像の表示方法">
<Image src={localImage} alt="Sample" />
</Layout>
<style>
img {
max-width: 100%;
height: auto;
}
</style>
これをビルドすると、
astro-project/
├── node_modules
├── dist
│ ├── _astro
│ │ ├──index.10c61ba9.css
│ │ └──sample.a9447241_ZWbci4.jpg
│ │ └──sample.a9447241.jpg
│ └── index.html
├── public
└── src
dist/_astro
ディレクトリに元画像(sample.a9447241.jpg)の他に、最適化された画像(sample.a9447241_ZWbci4.jpg)が展開されます。最適化された画像は、サイズと画像形式は同じですが、容量が低下しています。

画像サイズ:2048px × 1533px
画像形式:JPEG
画像容量:258KB
HTMLのソースコードは、以下のようにimgタグにwidthとheightが自動的に追加され、loading="lazy"
とdecoding="async"
属性が追加された状態になります。
<img src="/images/sample.jpg" alt="Sample" class="astro-J7PV25F6"><img alt="Sample" class="astro-J7PV25F6" width="2048" height="1533" src="/_astro/sample.a9447241_ZWbci4.jpg" loading="lazy" decoding="async">
また、Imageコンポーネントにはいくつかのオプションがあり、代表的なものは以下になります。
width(height)を指定する
<Image src={localImage} alt="Sample" width={800} />
width、もしくはheightを指定するとHTMLのコード上だけではなく、ビルド後の画像サイズが変わります。

画像サイズ:800px × 599px
画像形式:JPEG
画像容量:41KB
formatを指定する
<Image src={localImage} alt="Sample" format="webp" />
format(画像形式)を指定することで、以下のような形式に変換することができます。
(ビットマップ画像からsvgへの変換はできない)
‘avif’ | ‘jpeg’ | ‘jpg’ | ‘png’ | ‘svg’ | ‘webp’

画像サイズ:2048px × 1533px
画像形式:WebP
画像容量:254KB
qualityを指定する
<Image src={localImage} alt="Sample" width={960} format="webp" quality={80} />
qualityを数値で指定することで、画像の圧縮率を変えることができます(数値が高いほうが圧縮率が低い)。

画像サイズ:960px × 719px
画像形式:WebP
画像容量:66KB
まとめ
Astroでは、大きく分けて以下の3つの画像の表示方法があり、それぞれの特徴を持っています。
- publicディレクトリに画像を配置して、imgタグで表示する
(自分で最適化済みの画像を用意するなら最もお手軽、LP構築などに良いかも) - srcディレクトリに画像を配置して、imgタグで表示する
(画像をimportする必要があるのと、最適化もされないのであまり使わない) - @astro/imageを使って画像を最適化する
(適当に用意した画像をフロントエンド側で最適化できるため、HeadlessCMS構築などに良いかも)
@astro/imageは、sharpパッケージを使った画像変換オプションや、pictureによる画像の出し分け機能もあるため、また別途詳しくご紹介します。