🎨
Next.js SSGでImageタグのエラーに対処する方法
Imageタグエラー
Next.jsで静的サイト生成(SSG)を行う際に、Image
タグでエラーが発生しました。
エラー内容は以下の通りです。
Error: Image Optimization using Next.js' default loader is not compatible with `next export`.
Possible solutions:
- Use `next start` to run a server, which includes the Image Optimization API.
- Use any provider which supports Image Optimization (like Vercel).
- Configure a third-party loader in `next.config.js`.
- Use the `loader` prop for `next/image`.
next exportはNext.jsデフォルトローダーのImage Optimizationと互換性がなく、要は<Image>
タグはSSGには使えないようです。
仕方がないので画像を<img>
タグに置き換えてビルドするとにしました。
ESLintエラー
今度はESLintのエラーが発生しました。
warn - Statically exporting a Next.js application via `next export` disables API routes and middleware.
This command is meant for static-only hosts, and is not necessary to make your application static.
Pages in your application without server-side data dependencies will be automatically statically exported by `next build`, including pages powered by `getStaticProps`.
Learn more: https://nextjs.org/docs/messages/api-routes-static-export
next exportは静的ホスト専用でAPIルートとミドルウェアが無効化されてそれの影響らしい。
こちらはESLintの対象から除外することで回避しました。
.eslintrc
{
"extends": "next/core-web-vitals",
+ "rules": {
+ "@next/next/no-img-element": "off"
+ }
}
画像が表示されない
これでビルドは通ったのですが、今度は画像が正しく読み込まれない事象が発生しました。
Image
からimg
タグに置き換えたことで、正しいPathが生成されなくなったみたいです。
Pathを考慮したStaticImage
というcomponentを作成して、img
タグと置換して対応しました
component/StaticImage.tsx
import React from 'react'
const isProd = process.env.NODE_ENV === 'production'
const prefixPath = !isProd ? '/portfolio' : ''
function withPrefix(path: string) {
return `${prefixPath}${path}`
}
interface StaticImageProps {
src: string
alt: string
className?: string
width?: number
height?: number
}
export default function StaticImage({ src, alt, ...props }: StaticImageProps) {
return <img src={withPrefix(src)} alt={alt} {...props} />
}
pages/index.tsx
import Image from "next/image";
import StaticImage from "../component/StaticImage";
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });
export default function Home() {
return (
// ...
<StaticImage
src="/vercel.svg"
alt="Vercel Logo"
className="dark:invert"
width={100}
height={24}
/>
// ...
);
}
これにより、事象は解消しました!
ただ画像周りはまだ色々問題が出てきそうですね。。。
Discussion