🚀

【Next.js和訳】Basic Features/Image Optimization

8 min read

この記事について

株式会社 UnReact はプロジェクトの一環としてNext.js ドキュメントの和訳を行っています。

この記事は、Basic Features/Image Optimizationの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

画像コンポーネントと画像の最適化

バージョン10.0.0以降、Next.jsにはImage ComponentとAutomatic Image Optimizationが組み込まれています。

Next.jsのImage Component(next/image)は、HTMLの<img>要素を拡張したもので、現代のウェブ用に進化しています。

自動画像最適化では、ブラウザがサポートしている場合、WebPなどの最新フォーマットで画像をリサイズ、最適化して提供します。これにより、ビューポートが小さいデバイスに大きな画像を配信することがなくなります。また、Next.jsは将来の画像フォーマットを自動的に採用し、それらのフォーマットをサポートするブラウザに提供することができます。

自動画像最適化は、どんな画像ソースにも対応します。画像がCMSなどの外部データソースでホストされている場合でも、画像を最適化することができます。

Next.jsは、構築時に画像を最適化するのではなく、ユーザーからのリクエストに応じて、オンデマンドで画像を最適化します。静的サイトジェネレーターや静的サイトのみのソリューションとは異なり、10枚の画像でも1,000万枚の画像でも、ビルド時間は長くなりません。

画像はデフォルトでレイジーロードされます。つまり、ビューポートの外側にある画像に対して、ページスピードが低下することはありません。画像は、ビューポートにスクロールされたときに読み込まれます。

画像は、Googleが検索ランキングで使用しているCore Web VitalであるCumulative Layout Shiftを避けるように、常にレンダリングされます。

画像コンポーネント

アプリケーションに画像を追加するには、next/imageコンポーネントをインポートします。

import Image from 'next/image'
function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src="/me.png"
        alt="Picture of the author"
        width={500}
        height={500}
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}
export default Home

画像のインポート

プロジェクト内に存在する画像をimportすることができます。(requireはサポートされていません。importのみです。)

直接importする場合は、widthheightblurDataURLが自動的に画像コンポーネントに提供されます。Altテキストは別途必要です。

import Image from 'next/image'
import profilePic from '../public/me.png'
function Home() {
  return (
    <>
      <h1>My Homepage</h1>
      <Image
        src={profilePic}
        alt="Picture of the author"
        // width={500} 自動的に指定される
        // height={500} 自動的に指定される
        // blurDataURL="data:..." 自動的に指定される
        // オプションで、ロード中に画像のぼかしバージョンを追加することができます
        // placeholder="blur"
      />
      <p>Welcome to my homepage!</p>
    </>
  )
}

ダイナミックイメージやリモートイメージの場合は、widthheightblurDataURLを手動で指定する必要があります。

プロパティ

next/imageコンポーネントで利用可能なすべてのプロパティを表示します。

構成

next/imageコンポーネントで利用可能なプロパティに加えて、オプションとして、next.config.jsを介して、より高度なユースケースのために画像最適化を設定することができます。

ドメイン

外部のウェブサイトでホストされている画像に対して画像最適化を有効にするには、画像のsrcに絶対URLを使用し、最適化を許可するdomeinsを指定します。これは、外部URLが悪用されないようにするために必要です。loaderが外部イメージサービスに設定されている場合、このオプションは無視されます。

module.exports = {
  images: {
    domains: ['example.com'],
  },
}

ローダー

Next.jsに内蔵されている画像最適化機能を使わずに、クラウドプロバイダーを使って画像を最適化したい場合は、ローダーとパスのプレフィックスを設定できます。これにより、画像のsrcに相対URLを使用しても、プロバイダー用の正しい絶対URLを自動的に生成することができます。

module.exports = {
  images: {
    loader: 'imgix',
    path: 'https://example.com/myaccount/',
  },
}

以下のImage Optimizationのクラウドプロバイダーが含まれます。

  • Vercel: Vercelにデプロイすると自動的に動作し、設定は不要です。詳細はこちら
  • Imgixloaderimgix
  • Cloudinaryloadercloudinary
  • Akamai:loaderAkamai
  • Custom: loader: custom next/image コンポーネントに loader prop を実装することで、カスタムクラウドプロバイダーを使用します。
  • デフォルト。next devnext start、またはカスタムサーバーで自動的に動作します。

別のプロバイダーが必要な場合は、next/imageloader prop を使用できます。

next/imageコンポーネントのデフォルトローダーは、next exportの使用時にはサポートされません。ただし、他のローダオプションは動作します。

next/imageコンポーネントのデフォルトローダーはsquooshを使用していますが、これはインストールが早く、開発環境に適しているためです。本番環境でnext startを使用する場合は、プロジェクトディレクトリでyarn add sharpを実行してsharpをインストールすることを強くお勧めします。Vercelのデプロイメントでは、sharpが自動的にインストールされるため、この作業は必要ありません。

キャッシング

ここでは、デフォルトローダーのキャッシングアルゴリズムについて説明します。その他のloaderについては、クラウドプロバイダーのドキュメントを参照してください。

画像はリクエストに応じて動的に最適化され、<distDir>/cache/images ディレクトリに保存されます。最適化された画像ファイルは、その後のリクエストに対して、有効期限に達するまで提供されます。キャッシュされているが期限切れのファイルにマッチするリクエストがあると、新しい最適化された画像を生成して新しいファイルをキャッシュする前に、キャッシュされたファイルが削除されます。

有効期限(というかMax Age)は、上流のサーバーのCache-Controlヘッダーで定義されます。

Cache-Controls-maxage がある場合は、それが使用されます。s-maxageが見つからない場合は、max-ageが使用されます。max-age が見つからない場合は、minimumCacheTTL が使用されます。

アップストリームイメージにmax-ageが含まれていない場合、minimumCacheTTLを設定してキャッシュ期間を長くすることができます。

また、deviceSizes および imageSizes を設定して、生成可能なイメージの総数を減らすこともできます。

上級者向け

以下の設定は、高度なユースケースのためのもので、通常は必要ありません。以下のプロパティを設定した場合、今後のアップデートでNext.jsのデフォルトが変更されても上書きされます。

デバイスサイズ

ウェブサイトのユーザーから予想されるデバイス幅がわかっている場合、deviceSizesプロパティを使ってデバイス幅のブレイクポイントのリストを指定することができます。これらの幅は、next/imageコンポーネントがlayout="responsive "またはlayout="fill"を使用する際に使用され、ウェブサイトにアクセスするデバイスに対して正しい画像が提供されるようになります。

何も設定されていない場合は、以下のデフォルト値が使用されます。

module.exports = {
  images: {
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },
}

画像サイズ

imageSizesプロパティを使って、画像の幅のリストを指定することができます。これらの幅は、配列が連結されるため、deviceSizesで定義された幅とは異なる(通常は小さい)必要があります。これらの幅は、next/imageコンポーネントでlayout="fixed"またはlayout="intrinsic"が使用されている場合に使用されます。

設定がなされていない場合は、以下のデフォルトが使用されます。

module.exports = {
  images: {
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
  },
}

最小キャッシュTTL

最適化された画像をキャッシュする際のTTL(Time To Live)を秒単位で設定できます。多くの場合、ファイルの内容をハッシュ化して永久にキャッシュするスタティックイメージインポートを使用した方が良いでしょう。

module.exports = {
  images: {
    minimumCacheTTL: 60,
  },
}

ブラウザに Cache-Control ヘッダを追加する必要がある場合(推奨しません)、/_next/image 自体ではなく、/some-asset.jpg などのアップストリーム画像にheadersを設定することができます。

静的インポートの無効化

デフォルトの動作では、import icon from './icon.pngとして、それをsrcプロパティに渡すといった静的ファイルのインポートが可能です。

しかし、インポート時に異なる動作をする他のプラグインと競合する場合、この機能を無効にしたい場合があります。

以下の設定を行うことで、静止画像のインポートを無効にすることができます。

module.exports = {
  images: {
    disableStaticImages: true,
  },
}

関連

次に何をすべきかについては、以下のセクションをお勧めします。

https://nextjs.org/docs/api-reference/next/image

Discussion

ログインするとコメントできます