Next.jsで作ったWebサイトのホスティング先をvercelからCloudflare Pagesに移しました。
Cloudflare Pagesは現行、next exportで静的にエクスポートされたHTMLのみホストできます。
そうなると、next/imageがそのままでは使えないので、設定を直して使えるようにしました。
1. TL;DR
next.config.jsにimages : {loader : 'custom'}
を設定する。
next.config.js
/**
* @type { import('next').NextConfig}
*/
module.exports = {
images: {
loader: 'custom',
},
};
next/imageコンポーネントを使用する際に、loaderを設定する。
import Image from 'next/image';
import { imageLoader } from 'lib/imageLoader';
.
.
.
<Image
loader={imageLoader}
alt={...}
src={...}
height={...}
width={...}
layout="..."
/>
2. loaderの設定
2-1. 外部の画像最適化APIを利用する場合
例えばContentfulやGraphCMSなどのヘッドレスCMSは画像最適化のAPIがあります。
その場合、loaderを使用して、画像のsrcからsrcsetを生成して返すことができます。
ここでは、imageLoader関数を作成してsrcsetを返す例を紹介します。
作成した後は、next/imageで、loader={imageLoader}
を指定してください。
例1: Contentfulの場合
imageLoader.tsx
type PropTypes = {
src: string;
width: number;
};
export const imageLoader = (props: PropTypes) => {
const { src, width } = props;
const MAX_WIDTH = 640;
const resizeWidth = width > MAX_WIDTH ? MAX_WIDTH : width;
return `${src}?w=${resizeWidth}&q=75&fm=webp`;
};
export default imageLoader;
下記の変更を加えたsrcsetを返しています。
- next/imageに指定したwidthを元にリサイズ(最大幅は640に設定)
- フォーマットをWebPに変換
- クオリティは75%に
例2: GraphCMSの場合
imageLoader.tsx
type PropTypes = {
src: string;
width: number;
};
export const imageLoader = (props: PropTypes) => {
const { src, width } = props;
const relativeSrc = (targetSrc: string) =>
targetSrc.split('/').pop();
return `https://media.graphassets.com/resize=width:${width}/output=format:webp/${relativeSrc(
src
)}`;
};
export default imageLoader;
下記の変更を加えたsrcsetを返しています。
- next/imageに指定したwidthを元にリサイズ
- フォーマットをWebPに変換
2-2. 特に変更が必要ない場合
import Image from 'next/image';
.
.
.
<Image
loader={({ src }) => src}
alt={...}
src={...}
height={...}
width={...}
layout="..."
/>
srcをそのまま返します。
99. おわりに
next exportが使えるとホスティング先の選択肢が増えて便利です。