Next.jsではpages/ディレクトリ以下にページ用の実装ファイルを置く規約となっているが、それに追加して、このディレクトリ以下にはページ用以外のファイルは置いてはならないということが分かった。ページ用以外のファイルとは、例えばテストのファイルや共通ロジックのための実装などである。
ファイルを置くことで起こる問題と起こる理由
例えば日記サービスを考えたとして、pages/diaries.tsxのような日記一覧のページを実装するファイルがあったとする。この時、テストファイルはJestの流儀にしたがって、pages/tests/diaries.test.tsxもしくはpages/diaries.test.tsxに置きたくなる。
しかし、この時、次の問題が起こってしまう
- Next.jsはテストファイルもページ用の実装とみなし、
next build
時に成果物に含めてしまう.next/server/static/jfklanfkealknl/pages/diaries.test.js
のようなファイルができる
- ルーティングも機能してしまい、例えば
/diaries.test
のようなURLにアクセスできてしまう。ページの実装がないのでISEが返る
このようになる理由はNext.jsがpages/以下の全てのファイルをentrypointとしてwebpackでビルドしてしまうためである(このへんやこのへんを参照)。webpackのentrypointとして指定されているので、next.config.jsのwebpackの設定でIgnorePluginなどを入れたとしても解決しない。
解決策
https://github.com/zeit/next.js/issues/3728 で色々と議論されている。少なくともpagesGlobPatternのような設定や、excludePatternのようなものは提供しない方向となっていそう。
解決策としては例えば以下のようなパターンがありえる。
- pages以下にはsymlinkするパターン
- 全て別ディレクトリに置いて、pages以下ではexportだけするパターン
- pageExtensionsでpage.tsxを指定するパターン
- テスト用のディレクトリは別に切るパターン
いろいろ検討したけど、テストのために本番用のコード側を変えすぎるのは避けたい(本番用のロジックでsymlink作ったりしたくない)と考え、__pages_tests__
ディレクトリを別で切ってテストを配置することにした。__pages_tests__
というディレクトリ名にしたのは、pages/以下のテストしか置かないということを明示したかったためである。
最終形
pages/diaries.tsx __pages_tests__/diaries.test.tsx