0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js + App Router + TypeScriptでサブディレクトリ運用時の画像パス問題を解決する

Posted at

Next.jsのプロジェクトをサブディレクトリで運用する場合、例えば本番環境で /blog-sample のようなパス配下にデプロイするケースを想定すると、画像パス周りでちょっとした工夫が必要になります。

next/image コンポーネントを使う際、デフォルトではルート(/)からのパスを基準に画像を読み込むため、サブディレクトリ環境だとパスがずれてしまい、画像が正しく表示されないことがあります。
今回は、この問題を解決するために私が実装した方法を紹介します。

課題: サブディレクトリ環境での画像パス調整

開発環境では通常ルート(/)で動作するので問題ないのですが、本番環境でサブディレクトリ(/blog-sample)配下にデプロイすると、next/imagesrc に渡したパスがそのままでは意図した場所を指さなくなります。
例えば、src="/images/sample.jpg" のように指定しても、本番では /blog-sample/images/sample.jpg にならないと正しく読み込まれません。
これを手動で毎回調整するのは面倒だし、環境による条件分岐もスマートとは言えません。
そこで、環境変数を使ってベースパスを動的に設定しつつ、next/image をラップしたカスタムコンポーネントを作ることで、開発環境と本番環境の両方で一貫して動作するようにしました。

解決策: カスタムImageコンポーネントの実装

以下のように、next/image をラップした Image コンポーネントを作成しました。


import NextImage, { ImageProps } from 'next/image';

const basePath = process.env.NEXT_PUBLIC_BASE_PATH || '';

export const Image: React.FC<ImageProps> = ({ src, ...rest }) => {
  const normalizedSrc =
    typeof src === 'string' && src.startsWith('/') ? src.slice(1) : src;

  return <NextImage src={`${basePath}/${normalizedSrc}`} {...rest} />;
};

このコードのポイントは以下の通りです:

  1. 環境変数の利用: NEXT_PUBLIC_BASE_PATH を環境変数として定義し、本番環境では /blog-sample のようなサブディレクトリを指定します。開発環境では空文字('')をデフォルト値として設定。

  2. パスの正規化: src が文字列で、先頭にスラッシュ(/)が付いている場合、それを削除してベースパスと組み合わせるようにしています。これで、例えば src="/images/sample.jpg" が渡された場合、本番環境では /blog-sample/images/sample.jpg に、開発環境では /images/sample.jpg に自然に変換されます。

  3. 柔軟性: src が文字列以外(例えば StaticImageData)の場合でも、そのまま next/image に渡すので、エラーにならずに動作します。

ビルド時の設定

本番環境向けのビルドでは、以下のように package.json にスクリプトを追加して環境変数を指定しています。


"build:prod": "NEXT_PUBLIC_BASE_PATH=/blog-sample next build",

この設定により、本番ビルド時に NEXT_PUBLIC_BASE_PATH/blog-sample にセットされ、生成されるHTMLやアセットのパスに反映されます。開発環境では特に何も指定しないので、basePath は空文字のままとなり、ルート基準で動作します。

使い方

実際のコードでは、以下のように使います。


import { Image } from '@/components/Image';

export default function Home() {
  return (
    <div>
      <Image src="/images/sample.jpg" alt="サンプル画像" width={500} height={300} />
    </div>
  );
}

これで、開発環境でも本番環境でも、特別な条件分岐を書かずに画像が正しく表示されます。

まとめ

Next.jsでサブディレクトリ運用をする場合、画像パス問題は地味にハマりがちなポイントですが、環境変数とカスタムコンポーネントを組み合わせることで簡単に解決できます。今回の方法は、コードのメンテナンス性も高く、他のプロジェクトでも応用しやすいのでおすすめです。サブディレクトリ名が変わっても、ビルド時の環境変数を調整するだけで対応できるのも嬉しいポイントですね。
もし似たような課題に直面している方がいたら、ぜひ試してみてください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?