GAE スタンダード環境 で Next.js の Image コンポーネントを使う
こんにちは。 CURUCURU の笠原です。
今日は GAE 上で Next.js を運用する際の Tips を書きたいと思います。
Image コンポーネント
Next10から組み込みの自動最適化コンポーネント next/image
が実装されました。
使い方は簡単で以下のように定義するだけです。
import Image from 'next/image'
const Wrapper = () => (
<Image src="image.png" width="400" height="400" alt="image" />
);
Image コンポーネントの特徴
- 遅延読み込み
- Image コンポーネントで表示される画像は自動的に遅延読み込みされる
- 事前に指定したサイズで領域が確保されるので画像の読み込み時にカクつきが起こることもない
- 自動画像最適化
- 元の画像が 2000x2000 のような大きな画像をスマホで表示するのは無駄
- Image コンポーネントでは組み込みの画像最適化で自動的に最適な画像を生成する
GAE(Google App Engine) スタンダード環境で Image コンポーネントを使う
タイトル詐欺ですがスタンダード環境では next/image コンポーネントは使用できません。
自動最適化で生成された画像は ./next/image
以下にキャッシュされるのですが、スタンダード環境では /tmp
フォルダ以外でのファイルの書き込みができないためです。
(issue は立っているものの進んでいない様子)
ではどうするかというと
- フレキシブル環境を利用する
- コンテナ単位でデプロイできるので自由度が上がる
- ただし、無料枠がなくなるので料金が上がる可能性があったりスタンダード環境限定の API が使えなくなるなど移行のコストが発生する
- 画像最適化 api を独自に作成して、カスタムローダーで呼び出す
loader
を Image コンポーネントのプロパティに設定することで画像のリクエスト先を変更できる- これによって独自の API にリクエストを行い画像を最適化、Google Cloud Storage に保存
- 以降は Google Cloud Storage にキャッシュされた画像を返すことでスタンダード環境でも Image コンポーネントを利用できる
カスタムローダー
import Image from 'next/image'
const myLoader = ({ src, width, quality }) => {
return `/image/${src}?w=${width}&q=${quality || 75}`;
};
const MyImage = (props) => {
return (
<Image
loader={myLoader}
src="me.png"
alt="Picture of the author"
width={500}
height={500}
/>
);
};
クライアント側の実装は以上で、あとは pages/api/image 以下に最適化 api を実装するだけです。 このように自分で画像最適化を実装する場合には組み込みの最適化は不要になるので無効化しておきましょう。
next.config.js
module.exports = {
unoptimized: true,
}
まとめ
以上で GAE のスタンダード環境でも Next.js の next/image コンポーネントが利用できるようになりますが、Next.js のアップデートで使えなくなる可能性があったり、自前で画像最適化 API を実装するのが面倒だったりなど、そもそもの Image コンポーネントの手軽で高機能な良さが失われてしまいます。
可能であればフレキシブル環境に素直に移行したり、Next.js をデプロイするためのサービス Vercel を使ったほうがはるかに簡単です(笑)
今回は「スタンダード環境から移行できないけど Image コンポーネントを使ってみたい」というニッチな需要に答えるような内容でした。
CURUCURU では新しい技術やサービス作りが好きなエンジニアを募集中です! 「ITで女性のライフスタイルを豊かにする」というミッションの元やりがいのあるサービス作りに携わる事ができます。
CURUCURU でエンジニアとして働くことに興味がある方はよければオンラインでカジュアルにお話しましょう! https://www.wantedly.com/companies/curucuru/projects