AstroJS における画像ファイルの取り扱い説明書
1. はじめに
AstroJS では、デフォルトで画像処理ライブラリの Sharp が組み込まれており、同じく AstroJS にデフォルトで組み込まれている <Image>
コンポーネントを用いることで、画像を最適化してくれます。外部パッケージのインストールや設定なしで、最適化処理が行われるのはユーザーフレンドリーだと思います。その一方で、画像ファイルを読み込み際に、独特の お作法 が存在します。慣れないうちは、この お作法 のせいで頭を悩ませると思います。本記事では、AstroJS における画像ファイルの読み込み挙動について、可能な限り網羅的に解説したものになります。また、本記事は Node.js と Yarn がインストールされている前提で記述しています。
1$ node -v2v20.11.03$ yarn -v41.22.21
2. 検証環境
検証環境として、yarn create astro
で生成される blog テンプレートに、以下の画像ファイルを追加したものを使います。画像ファイルは、あくまでもサンプルなので、任意の画像ファイルで大丈夫です。
- public/Apple.jpg
- src/assets/Banana.jpg
- src/content/blog/Cherry.jpg
1$ yarn create astro2yarn create v1.22.213[1/4] Resolving packages...4[2/4] Fetching packages...5[3/4] Linking dependencies...6[4/4] Building fresh packages...7
8success Installed "create-astro@4.7.2" with binaries:9 - create-astro10[########################################] 40/4011 astro Launch sequence initiated.12
13 dir Where should we create your new project?14 ./satellite-solstice15
16 tmpl How would you like to start your new project?17 Use blog template18
19 ts Do you plan to write TypeScript?20 Yes21
22 use How strict should TypeScript be?23 Strict24
25 deps Install dependencies?26 Yes27
28 git Initialize a new git repository?29 No30 ◼ Sounds good! You can always run git init manually.31
32 ✔ Project initialized!33 ■ Template copied34 ■ TypeScript customized35 ■ Dependencies installed36
37 next Liftoff confirmed. Explore your project!38
39 Enter your project directory using cd ./satellite-solstice40 Run yarn dev to start the dev server. CTRL+C to stop.41 Add frameworks like react or tailwind using astro add.42
43 Stuck? Join us at https://astro.build/chat44
45╭─────╮ Houston:46│ ◠ ◡ ◠ Good luck out there, astronaut! 🚀47╰─────╯48Done in 46.94s.
3. Astro ファイル
3.1. <img> タグ
AstroJS で最もシンプルに画像を表示させる方法は、public
フォルダに画像ファイルを配置して <img>
タグで表示する方法です。以下の、どの記法でも画像が表示されます。AstroJS では、public
フォルダに配置されたファイルはビルド時に、そのまま root にコピーされます。GatsbyJS や Hugo の static
フォルダと同じ役割です。
1---2
3---4
5<img src="Apple.jpg" />6<img src="/Apple.jpg" />7<img src="./Apple.jpg" />
他に、<img>
タグを用いて画像ファイルを表示する方法を色々と検証してみました。結果としては、public
フォルダに配置している画像ファイルを <img>
タグで表示する場合は、上記の方法で表示するが良いと思います。また、src
フォルダに配置している画像ファイルを <img>
タグで表示する場合は、絶対パスを用いるのが良いと思います。
1---2
3---4
5<!-- 絶対パス -->6<img src="/public/Apple.jpg" /> ← WARN が出力される7<img src="/src/assets/Banana.jpg" />8<img src="/src/content/blog/Cherry.jpg" />9
10<!-- 相対パス -->11<img src="../../public/Apple.jpg" /> ← WARN が出力される12<img src="../assets/Banana.jpg" /> ← 404 Not Found13<img src="../content/blog/Cherry.jpg" /> ← 404 Not Found
AstroJS では、import 文を用いて画像ファイルを読むことが出来ます。読み込まれた画像ファイルは、ImageMetadata
型のデータとして扱うことが出来ます。絶対パスで読み込んでも、相対パスで読み込んでも、挙動は同じです。また、<img>
タグの src プロパティに直接、ファイルパスを設定する方法とは異なり、import localImage from '[ファイル名]'
で読み込むことは出来ません。
1---2// 正しい絶対パス3import localImage from '/public/Apple.jpg'4import localImage from '/src/assets/Banana.jpg'5import localImage from '/src/content/blog/Cherry.jpg'6
7// 正しい相対パス8import localImage from '../../public/Apple.jpg'9import localImage from '../assets/Banana.jpg'10import localImage from '../content/blog/Cherry.jpg'11
12// 誤ったパス13import localImage from 'Apple.jpg'14import localImage from '/Apple.jpg'15import localImage from './Apple.jpg'16---17
18<img src={localImage.src} width={localImage.width} height={localImage.height} />
3.2. <Image> コンポーネント
<img>
タグを用いて表示される画像ファイルは、最適化が行われません 1 。画像を最適化したい場合は、<Image>
コンポーネントを用いります。<Image>
コンポーネントは、src プロパティと alt プロパティが必須です。更に詳しい仕様については、AstroJS の公式ドキュメント 1 を参照ください。
1---2import { Image } from 'astro:assets'3
4import localImage from '/src/assets/Banana.jpg' // 絶対パス5or6import localImage from '../assets/Banana.jpg' // 相対パス7---8
9<Image src={localImage} alt="説明文" />
4. Markdown ファイル
4.1. コンテンツ部分
AstroJS では、src
フォルダ内の Markdown ファイルは、自動的に HTML に変換されます。画像ファイルを絶対パスで指定しても、相対パスで指定しても、画像自体は表示されます。しかし、絶対パスで指定した場合は、最適化処理が行われません。一方、相対パスで指定した場合は、最適化されます。そのため、Markdown コンテンツ部分で画像を表示する場合は、相対パスで指定する方が良いと思います。
1# 絶対パス:最適化されない2 ← WARN が出力される345
6# 相対パス:最適化される78910 ← 404 Not Found11
4.2. フロントマター部分
Markdown のフロントマター部分では、本文部分とは異なり、絶対パスで指定しても相対パスで指定しても最適化されます。ただし、Markdown ファイルと同じディレクトリに画像ファイルを配置する場合、heroImage: '[FILE]'
と heroImage: '/[FILE]'
はエラーが発生するので注意が必要です。また、Markdown のフロントマターで設定した画像は、デフォルトでは最適化されません。Markdown のフロントマターで設定した画像を最適化する方法については、筆者の別記事 2 を参照ください。
1---2# 絶対パス:最適化される3heroImage: '/public/Apple.jpg' OK4heroImage: '/src/assets/Banana.jpg' OK5heroImage: '/src/content/blog/Cherry.jpg' OK6
7# 相対パス:最適化される8heroImage: '../../../public/Apple.jpg' OK9heroImage: '../../assets/Banana.jpg' OK10heroImage: 'Cherry.jpg' ERROR11heroImage: '/Cherry.jpg' ERROR12heroImage: './Cherry.jpg' OK13---
5. おわりに
ここまで、AstroJS における画像ファイルの読み込み挙動について、可能な限り網羅的に解説してきました。上記のコードは全て念入りにレビューしていますが、ヒューマンエラーで誤った情報がないとも限りません。また、AstroJS のアップデートで、仕様が変わる可能があります。何か、おかしな点がありましたら、連絡ください。
余談ですが、GatsbyJS の場合だと GraphQL が画像ファイルの読み込み処理を抽象化してくれていたので、ここまで難しい作業になりませんでした。あの憎かった GraphQL を再評価する日が来るとは思いませんでした。
-
Astro Docs, Images:https://docs.astro.build/en/guides/images/ ↩ ↩2
-
【AstroJS】 Markdown のフロントマターで設定した画像を最適化する:https://xenexe.info/e360becc-d7d0-49f9-bf8b-0ee74430f50d/ ↩