Lesson 5
画像参照方法
Lesson 5
Chapter 1
publicディレクトリ
publicディレクトリとは
本チャプターではアプリケーションを作成していく上で必須の画像やテキストファイルを配置するpublicディレクトリについて学んでいきます。
publicディレクトリに保存するファイルは静的ファイルと呼ばれ動的に変更が起きないファイルを配置し参照する為に使用します。
publicディレクトリの名前を変更する、もしくはpublic以外の静的ファイルを参照しようとするとエラーとなってしまいますのでご注意ください。
画像を参照する方法については、下記2つの方法があります。
・デフォルトの機能のimgタグを使用して参照する方法
・Imageコンポーネントを使用する方法
上記の2つ方法があり本チャプターではデフォルトのimgタグ
チャプター2ではImageコンポーネントを使用した方法について触れていきます。
publicディレクトリから画像参照
それでは実際にpublicディレクトリから画像を参照してみましょう。 参照する画像は任意でよろしいですが、当レッスンでは下記画像を"logo.png"として publicディレクトリに画像を保存して使用していきます。

pages/Image.tsxというファイルを新規作成して下記のコードを記述してみましょう。
pages/image.tsx
const Image = () => {
return <img src="/logo.png" />;
}
export default Image;
上記の様に記述するとpublic/logo.pngが表示できます。
コードを見ていきましょう。
コードを記述しているディレクトリは「pages」となりますので本来は、
public以下に「logo.png」という画像があるのであれば、相対パスとして
<img src="/logo.png" />
ではなく
<img src="../public/logo.png" />
とすると思います。
ですが、 Next.jsではimgタグのパスに「/」を打つことでpublic内のファイルを自動で参照してくれます。
とても便利な機能ですが、Webページで実際に表示すると以下の様な問題がおきます。
上記の様なデメリットを改善する為には次チャプターで解説する「Imageコンポーネント」という機能を使用すると 解決できます。

Lesson 5
Chapter 2
Imageコンポーネント
Imageコンポーネントとは
前チャプターではデフォルトのimgタグを使用した画像の参照方法について見ていき色々なデメリットがあることを学びました。 本チャプターでは、上記のデメリットを解決してくれるNext.jsが提供しているImageコンポーネント(next/image)という便利なコンポーネントについて学んでいきます。 Imageコンポーネントは2020/10/27にNext.js 10でリリースされたかなり新しいコンポーネントです。
Imageコンポーネントの特徴・メリット
Imageコンポーネント (next/image) を使用すると、img要素をそのまま配置するのに比べて 次のようなメリットがあります。
遅延ロード(Lazy loading)
Imageコンポーネントを使用した画像をクライアント側で表示する際、Next.jsはデフォルトで遅延ロードという処理を行います。 遅延ロードではページの読み込み時に画像は読み込みまず、スクロール等で画面内に画像が表示されて初めて読み込まれます。 これにより、ページの読み込み速度を向上させることができます。
画像の最適化
画像最適化に関しては、Next.js サーバー上でホスティングしている時しか動作しないといった制約がありますが 遅延ロードがデフォルトで有効になるのはとても便利ですね。
Imageコンポーネントの使い方
それでは実際にImageコンポーネントを使用して、画像を表示してみましょう。 pages/components/image.tsxというファイルを新規作成して下記コードを記述しましょう。
pages/components/image.tsx
import Image from 'next/image'
const image = () => (
<Image src="/logo.png" width={300} height={200} alt="" />
)
export default image;

img要素を使用して表示したページと同様のページが出力されましたね。
それではコードの説明をしていきます。
1行目のimport Image from 'next/image'
でImageコンポーネントをインポートして使う準備をします。
そして5行目でタグ名をImageと記載し、以降はimgタグでの画像参照方法と同様です。
上記の様にImageコンポーネントは<img />要素を少し書き換えるだけで導入できます。
またaltなどの<img />要素の属性はImageコンポーネントでも同じように使用できます。(width/height属性の指定は後の章で解説します。)
これだけで画像の読み込みが最適化されるとは素晴らしい機能ですね。
Imageコンポーネントを使用する際に知っておきたいこと
ここからはnext/imageを導入する前に特に知っておきたいことを見ていきます。
画像最適化の全体設定はnext.config.jsで行う
画像最適化についての設定はnext.config.jsのimagesプロパティで行います。 ここでの設定がプロジェクト内のすべてのnext/imageコンポーネントに反映されるイメージです。
next.config.js
module.exports = {
images: {
// ここ
},
}
詳しい設定方法は割愛させていただきますが、設定項目の一覧は公式ドキュメントにまとまっていますので是非ご覧ください。
Image Optimization #Configuration →
画質はコンポーネント毎に変えられる
画質はコンポーネント毎に1〜100の間で指定できます。(デフォルトでは75)
画質を落としたい場合は、コンポーネント使用時に以下のようにqualityをセットします。
<Image src="..." quality={50} width={600} height={300} />
画像の拡大・縮小
Imageコンポーネントでは基本的に幅(width)と高さ(height)を数字で指定するようにします。
<Image src="..." width={600} height={300} />
<img />タグと同じくpxや%などの単位をつけることはできませんが、Imageコンポーネントではレスポンシブに画像サイズを調整してくれます。
例えば親要素の幅がwidthより小さくなっても、縦横比を保ったまま画像を小さく表示してくれます。
ただし画像ファイルの縦横比を考慮して指定しないと、下の例のように変形して表示されてしまうので注意してください。
<Image src="/logo.png" width={200} height={400} alt="" />

親コンポーネントのサイズに連動させる (layout=fill)
Imageコンポーネントのwidth、heightプロパティを指定する代わりに、 layoutプロパティをfillに設定すると、親要素のサイズがImageコンポーネントのサイズとして使われます。
<div style={{ position: 'relative', width: '100%', height: 150 backgroundColor: 'gray'}}>
<Image src="/logo.png" layout="fill" objectFit="contain" />
</div>
※position: 'relative'は子要素の位置を親要素の中に限定するプロパティです。
上記の例でいうと、上の階層に配置した div 要素のサイズが、Image 要素のサイズになります。
Image コンポーネントのサイズをlayout="fill"
で親要素のサイズに合わせるときは、
objectFit="contain"
という
アスペクト比を保って拡縮表示するプロパティを使用するとよいです。
これを指定しないと、デフォルトの objectFit="fill" が使われて、画像が親要素の形に変形して表示されてしまいます。
灰色の範囲が親要素の範囲
ウィンドウの大きさに合わせて画像サイズを変更する (layout=responsive)
<Image src="/logo.png" width={600} height={300} layout="responsive" />
上記で画像を画面が小さい際には縮小、大きい際には拡大するように設定できます。
ウィンドウのサイズを変更すると設定がわかりやすいです。
まとめ
本レッスンではimg要素とImageコンポーネントでの画像参照方法について学びました。 Imageコンポーネントは導入も簡単で画像の最適化や遅延ロードと普通にimg要素を使用するよりもメリットがたくさんあります。 またレスポンシブも自動対応で開発効率が非常に良くなります。 ImageコンポーネントはNext.jsを使用して画像参照を行ううえで非常に重要な機能になりますので是非活用していきましょう。 次のレッスンでは各レンダリング方式のデータ取得方法について詳しく解説していきます。
