🖼️

Vercel 以外のホスティングサービスで Next.js の next/image を使う

2023/09/11に公開

Next.js で画像ファイルを表示する場合、next/image というプラグインを使うことが推奨されています。このプラグインを使うと自動的に画像をリサイズ、最適化して表示され、サイトのパフォーマンスが大幅に向上します。

https://nextjs.org/docs/pages/api-reference/components/image

/app/page.js
import Image from 'next/image'
 
export default function Page() {
  return (
    <Image
      src="/profile.png"
      width={500}
      height={500}
      alt="Picture of the author"
    />
  )
}

ただし注意点として、next/image のデフォルトの設定は Vercel 以外のホスティングサービスではサポートされていません。
ローカル環境で動作確認する分には問題ないのですが、いざホスティングサービスにデプロイしようとするとエラーになってしまいます。

Vercel 以外のホスティングサービスで next/image を使う方法

Vercel 以外のホスティングサービスで next/image を使うには二つの手段があります。ひとつは Cloudinary などの外部の画像配信サービスを利用すること です。もうひとつは、カスタムローダーを定義すること です。今回はより手軽な後者について紹介します。

まずは、next.config.js を以下のように編集します。

next.config.js
/** @type {import('next').NextConfig} */
module.exports = {
  reactStrictMode: true,
  swcMinify: true,
  images: {
    loader: "custom",
  },
};

次に、next/image を呼び出すコンポーネントを作成します。実際に画像を表示したいときはこのコンポーネントを使えば OK です。

/components/ImageBlock.tsx
import Image from "next/image";

type CustomLoaderProps = {
  src?: string;
  width?: number;
  quality?: number;
};
const customLoader = ({ src, width, quality }: CustomLoaderProps) => {
  return `${src}?w=${width}&q=${quality || 75}`;
};

type Props = {
  src?: string;
  alt?: string;
  height?: number;
  width?: number;
  className?: string;
};
const ImageBlock: React.FC<Props> = ({
  src,
  alt,
  height,
  width,
  className,
}: Props) => {
  src = src || "dummy";
  alt = alt || "dummy";
  height = height || 512;
  width = width || 768;
  return (
    <Image
      src={src}
      alt={alt}
      height={height}
      width={width}
      style={{
        objectFit: "cover",
        height: "100%",
        width: "100%",
      }}
      loader={customLoader}
      className={className}
    />
  );
};

export default ImageBlock;

<Image> タグの loader 部分で、作成したカスタムローダーを呼んでいます。

おまけ:next.config.js 編集時にエラーが出るときの対処法

next.config.js ファイルの編集時に ESLint のエラーが出るときは、ESLint の設定に以下のように追記することでエラーを回避できます。

.eslintrc.json
{
  "extends": "next/core-web-vitals",
+  "ignorePatterns": ["*.config.js"]
}

Discussion