[Next.js 13.1時点] turbopackとappDirはもうすぐGAになるのか予想
2022年12月下旬、Next.js 13.1がリリースされました。
良いタイミングということで、この記事では、appDirやturbopackの機能がもうすぐGAになるのか、筆者の予想をシェアしたいと思います。
※本当はv13.1のアップデート内容を事実ベースで紹介するというコンセプトだったのですが、大きな変更や難しい変更がなく、解説することがなくなってしまったため、上記コンセプトにしました。
この記事のゴール
- turbopackやappDirについて、筆者視点の近況理解や見方を伝えることで、読者の方に何かしら学びがあったり、考える機会になること
結論:まだ来ない
結論として、turbopackもappDirもまだまだ実用は難しいという印象を持っていますので、なぜそう思っているかを説明していきます。
Next.js 13.1時点のturbopack
改善はしているが、進化はしていない
turbopackのバグは着実に修正されているように思います。
2022年10月の発表当時は、そもそも立ち上がらずにエラーで落ちることもよくありましたが、そういった現象はなくなっているように思います。
Next.js 13.1のリリースでも、PostCSSのサポートが発表され、TailwindCSSに対応可能になりました。
筆者の方でも検証し、実際にPostCSSがturbopack上で使えることを確認できました。
※13.0の時代に使えていなかったか、までは検証していません。
一方で、総じて直近のアップデートは従来のHMRと同等の機能を提供するためのサポート強化であり、機能の進化ではないように感じられます。
TailwindCSSのサポートも、冷たい言い方をすれば、なかったことがおかしかった機能です。
というのも、もともとNext.jsはPostCSSをサポートしており、ルートディレクトリのpostcss.config.js
を自動的に読む機能がありました。
これはNext.js 12以前もそうですし、appDirもpagesディレクトリも、従来のHMR機能もそうです。
つまり、turbopackだけが検討漏れなり開発期間不足で今まで対応していなかった、というだけの話と筆者は理解しています。
まだまだ改善の途中と感じられる
では、改善を積み重ねているturbopackがもうすぐ実用できる品質になるかというと、NOと判断しています。
たしかに、next dev --turbo
が落ちるといった事象はなくなっているのですが、
- 初回立ち上げに膨大な時間がかかる
- 既存HMRに比べて速くなっているという感触がない
- Streaming SSRに対応できていない or
export const dynamic
を理解していないなど、まだサポートが不足している機能が普通にある
といった状況で、実用する価値が出てくるにはまだ時間がかかりそうな印象です。
Next.js 13.1時点のappDir
当初から動作していた印象だが、重たい課題もあり
一方のappDirは、2022年10月当初から、layout機能やhead機能、Streaming SSR、Server Componentsなど、かなりの精度で動いていたように思います。
筆者はかなりガッツリ動かしていたのですが、課題があると思っていたのは大きく2点でした。
- React Server Componentの型(jsx/tsxとの互換性問題)
- データフェッチ周りの品質
※next/fontやEdge周りはあまり動かしていないため語れません。
1.は、jsx/tsxの仕様上、Promiseを返すServer ComponentをElementとみなすことが出来ないという問題です。
これのせいで、ts-ignoreをいたるところにつけないといけなくなります。
ts-ignoreのせいで読みづらくなりますし、バグをコンパイル時に検知できず、実行時エラーにも繋がりやすくなります。
総じて開発者体験が悪く、クリティカルです。
また、2.について、Next.js 13 / appDirでは、サーバーサイドデータフェッチについて新しい指針や設計を導入しています。例えば、コンポーネント間でバケツリレーをせず、各コンポーネントからNext.jsが独自拡張しているfetch
関数を呼び出す、などです。
従来のgetXXXProps
はレンダリングとデータフェッチをひとまとめで考えていましたが、appDirでは、このやり方でデータフェッチを制御したうえで、ルーティングごとに結果的に発生するデータフェッチ頻度などを見て、レンダリング方法を決定します。
例えば、いろんなコンポーネントがデータをフェッチしているルートについて、一番頻度が高いコンポーネントはリクエストの度にフェッチしているとしたら、そのルーティングはSSR(結局リクエストのたびにルートの処理を実行する必要があるから)になる、といった動きをします。
そして、この辺はポロポロとバグのような挙動が見つかっていました。
例えば、page.tsx
にはexport const dynamic = ...
というパラメータが設定できます。これは、ルーティングのレンダリング方法を明示的に決定するパラメータです。
これを使うことで、「静的ページだがSSRして毎回ログ出力する」など、細かい動きを指定できるはずでした。
しかし、v13.0.4時点ではこのパラメータは動作しませんでした。
ひとまず型さえなんとかなれば使えそうだが...
jsx/tsx上でReact Server Componentを表示する方法がいつ対応予定なのか、少なくとも筆者には分かっていません。
おそらく以下が当該issueだと思うのですが、2023/1/4時点では特にNext.jsチームから正式な対応予定は返答されていないと認識しています。
これさえ対応されれば一旦appDirは使っていけるのでは、というのが筆者の所感です。
上記で例示したexport const dynamic
パラメータの問題も、v13.0.7までには修正されていました(動作を確認しました)。
一方で、一抹の不安も感じています。
それは、上記2.のデータフェッチ周りの問題が、実は根深いのではないかという不安です。
というのも、例えば、先ほどのdynamic
パラメータに関する説明ページを確認いただきたいです。
ここには、dynamic
以外にrevalidate
という設定値もあります。
問題は、これらの設定値は管理する挙動がかぶっていることです。
export const revalidate = 0
を指定するとSSR(Dynamic Rendering)になるので、export const dynamic = 'force-dynamic'
を指定することと同義です。
現状のNext.jsのデータフェッチとレンダリングの仕様として、「フェッチはSGにするけどロジックは毎回走らせる」「同じルートの中でデータごとに異なる更新頻度でフェッチする」といったようなことはできないからです。
何が言いたいかというと、「データフェッチ周り、export const dynamic
のバグは氷山の一角でしかなくて、根本的な設計が甘かったのでは?」という懸念をしています。(的外れだったらNext.jsチームに大変申し訳ないのですが)。
もしそうだとすると、どこかで再度メンタルモデルを整理するタイミングが必要になり、APIが安定するまでには時間がかかりそうだな、という不安でした。
補足
例えば上記の
「フェッチはSGにするけどロジックは毎回走らせる」「同じルートの中でデータごとに異なる更新頻度でフェッチする」といったようなことはできない
といった概念モデルについても、ドキュメント上に一貫性を持って記載されてはおらず、メンバごとに認識もまばらだったのでは?とドキュメント読んでいて結構感じます。
そもそも、今後も上記のようなことが細かな制御ができないのであれば、レンダリングとデータフェッチについてここまで抜本的に設計を変えたことに意味があったのだろうかとも思います。
もちろん多少はフェッチ量が減るとは思いますが、結局SSRのルートに巻き込まれたコンポーネントのフェッチ頻度はリクエストごとに毎回になってしまうわけで、最適化として中途半端と感じられます。
まとめ
appDirやturbopackがプロダクションで使えるようになるには、まだ少し時間がかかるのでは、というのが筆者の予想です。
根拠は全くないですが、2023年3月中くらいにGAになったら早いほうなんじゃないか(なってほしい)と予想しています。
品質的にはappDirのほうが現状高い気がしますが、turbopackはぶっちゃけちょっとくらいバグっていても問題ない(プロダクションで使わないから)ところもあるので、どっちが先に来るか楽しみです。
もしNext.jsチームの今後のGAまでの見通しだったり、クリティカルなissueなど一覧する方法を知っている方がいらっしゃいましたら、ぜひご教示ください。
また、Next.js 13 / appDirのレンダリングとデータフェッチのカオスについても伝わったかと思います。近いうちに解説記事にしたいと思います。
追伸
割とネガティブな記事になってしまいましたが、筆者は普通にNext.jsやReactが大好きです。
(Nuxt3に1年待たされた経験もあるので、ハードルは低いです)
動作確認は入念にしてるのですが、GitHubのIssueを洗ったりといった行儀の良い調査はあまりしていませんので、話半分でお願いできればと思います。
異なる意見や誤りの指摘などありましたら、遠慮なくコメントいただければと思います。
よければTwitterもフォローお願いします!
@sumiren_t
Discussion