Next.js v15でopengraph-imageにCSS Modulesを読み込むと、ページでスタイルが適用されない
TL;DR
執筆時点では、Next.js v15(15.5.9)において、opengraph-image.tsx から CSS(SCSS を含む)を import すると、本番ビルド後の環境で CSS が script として扱われ、SyntaxError が発生し、スタイルが適用されないことがあります。
Next.js v16(16.1.0)では、この問題は解消されています。
v15 を使い続ける場合は、opengraph-image.tsx から CSS を直接・間接的に読み込まないようにしましょう。
関連 Issue
https://github.com/vercel/next.js/issues/72480
再現リポジトリ(Next.js v15)
https://github.com/silverbirder/nextjs-15-opengraph-image-scss
はじめに
Next.js v15.5.9 を使用したアプリケーションにおいて、本番ビルド後に一部のスタイルが適用されなくなる問題に遭遇しました。
この問題には、次のような特徴がありました。
next devでは再現しないnext build→next startした本番環境でのみ発生する- 再現性が低く、常に発生するわけではない
そのため、原因の特定が難しく、調査にかなり時間がかかりました。
調査当初は、挙動からブラウザキャッシュや CDN キャッシュの問題を疑いましたが、いずれも原因ではありませんでした。
また、Next.js のページ数が多い状態では再現性が著しく低く、不安定になります。一方で、発生している 1 ページのみに絞って検証すると、再現性が格段に高まることが分かりました。
切り分けを進めた結果、opengraph-image.tsx から CSS(SCSS)を読み込んでいることが原因であると判明しました。
本記事では、その調査過程と原因、再現方法、そして回避策についてまとめます。
発生していた問題
本番環境(next build && next start)において、次のような問題が発生しました。
- ボタンなどのコンポーネントにスタイルが適用されない
Uncaught SyntaxError: Unexpected token '.'という JavaScript エラーが発生する
一方で、next dev では問題なく表示されるため、開発中には気づきにくい点が特徴でした。
調査の過程と関連 Issue
切り分けを進める中で、次の Next.js の Issue とほぼ同じ事象であることが分かりました。
https://github.com/vercel/next.js/issues/72480
この Issue でも、opengraph-image.tsx から SCSS ファイルを import している場合に問題が発生することが報告されています。
原因:opengraph-image からの CSS 読み込み
何が起きているか
opengraph-image.tsx から CSS(SCSS)を読み込むと、ビルド後の挙動が不正になります。
具体的には、CSS ファイルが JavaScript の script として扱われ、次のような script タグが出力されます。
<script src="/_next/static/css/f2515c4387c9bb9d.css" async=""></script>
その結果、CSS ファイルが JavaScript として解釈され、Uncaught SyntaxError: Unexpected token '.' が発生します。
build-manifest.json に現れる異変
ビルド後に生成される build-manifest.json を確認すると、rootMainFiles に本来含まれるべきでない CSS ファイルが含まれていることが分かります。
このプロパティの正確な用途は把握できていませんが、正常に動作している場合は JavaScript ファイルのみが含まれている、というのがこれまでの経験則です。
この状態になると、今回のスタイル未適用の問題が発生しやすくなります。
そのため、CI などで build-manifest.json を確認し、rootMainFiles に CSS ファイルが含まれていないかを検査する方法も有効です。
再現コード
最小構成で再現するリポジトリを用意しています。
Next.js v15(問題が発生する)
https://github.com/silverbirder/nextjs-15-opengraph-image-scss
以下を実行すると、CSS のスタイルが適用されない状態になります。
npm run buildnpm run start
Next.js v16(問題が解消される)
https://github.com/silverbirder/nextjs-16-opengraph-image-scss
同じ構成でも、Next.js v16 では問題が発生しませんでした。
対処方法・回避策
Next.js v16 にアップデートできる場合
可能であれば、Next.js v16 にアップデートするのが最もシンプルな解決策です。
今回の問題は、v16 では再現しませんでした。
v15 を使い続ける場合の注意点
Next.js v15 を継続して使う場合は、次の点に注意する必要があります。
opengraph-image.tsxから CSS / SCSS を import しない- import しているファイルの中で、間接的に CSS を読み込んでいないかを確認する
特に、Nx や Turborepo などのモノレポ構成では、CSS を読み込むコンポーネントを export しているライブラリを import しただけで、問題が発生するケースがあります。
まとめ
- Next.js v15 では、
opengraph-image.tsxからの CSS import に注意が必要です - 本番ビルドのみで発生し、再現性が低いため発見しづらい問題です
build-manifest.jsonのrootMainFilesに CSS が含まれていた場合は注意が必要です- v16 にアップデートできるのであれば、それが安全な解決策です
同じように、本番環境のみで CSS が適用されない問題に遭遇した場合の参考になれば幸いです。