この記事は 実践 Next.js の書評です。 見本誌を頂いた上での記事です。(PR記事?)
tl;dr
App Router のメリットを理解しつつも、学習コストに割り合わないと思っている人にオススメ!ドキュメントを読めるようになるし、学習コストが下がる。
はじめに
自分はどちらかというと今の Next.js に対しては否定的な感情の割合の方が高く、仕事で困らない程度の最低限の知識しか持っていない。 しかし、なんだかんだ勉強の必要性に駆られていて、そのキャッチアップとして同書の発売を楽しみにしていた。 そんな折に @takepepe さんから見本誌をいただいたことで、この週末に読んだので書評を書きたい。
俺は今のNext.jsが好きではない
書評を書く前にポエム書かせてくれ!
Next.jsを始めたきっかけ
自分は Next.js に対する思い入れは人一倍あると思う。 なぜなら自分が前職でプログラマーにキャリアチェンジして初めて触ったツールだからだ。 その当時の職場にはアプリが2つあって、一つは webpack2 でビルドされている複雑怪奇な古典的なReact製のSPAで、もう一つがその反省を活かして作られた Next.js のアプリだ。 もともと職場にはフロントエンドエンジニアとしてインターン生が1人いて、彼が作ったものを引き継ぐ形で2人で作っていた。 当時のNext.js は React を使いやすくするための便利なFWという立ち位置であった。 それでもかなり荒削りで dynamic routing なんて存在しないし、SSR時に redux を初期化するという設計が流行って振り回されたりと、今から振り返るととんでもない時代だった。 それでも自分が最初に触れたFWであったから、今でも親のようなライブラリだと思っている。
このNext.jsだが、当時は貧者のライブラリという評されていたと思う。 時期的には2018年で丁度 SPA のバンドルサイズをいかに削るかというトピックが盛り上がっていた。 他にもSPAだとOGP辛い問題があって、そのための prerendering やら色々で全員が迷走して疲弊していた。 そして、それらの解決策としてSSRが盛り上がっていた。 そしてさらに疲弊していた。
SSRはいわゆるクライアントサイドしか書いたことない人間からすると、全くわからない新しい概念がたくさん登場して大変であった。 例えば、express の管理だったり、認証への理解だったり、Node.js そのものの理解だったりが壁になっていた。 サーバーでReactを実行するという言葉の意味も全く理解できなかった。 何が嬉しいねん。 そんなことを関連会社にいた知人に相談へ持ち込んだら redux-pluto なるもっと訳のわからないものを提案されて怖かったのも覚えている。 今となっては redux-pluto が目指していたものを理解できるが、インターン生からプログラミングを教わっていただけの初心者からすると、いきなりこんなもの渡されてどうにかできるものではなかった。 一方で何も理解せずにいい感じに動いてくれる Next.js は本当に素晴らしかった。 Next.js はチームにビルドやNode.jsやサーバーサイドプログラミングに詳しくない人がいなくても、SSRを始められる唯一の選択肢だった。
貧者のライブラリからUXのためのライブラリへ
だからこそNext.jsは貧者のライブラリと言われていたし、自分もそう思っていた。 Next.js は getServerSideProps と dynacmic routing だけ知っとけばなんとかなるライブラリだ。 スタイリング も CSS Modules で楽々にできる。 webpack の設定も書かなくてもいい。 何も勉強しなくていい、それがNext.jsの素晴らしいところで自分の大好きなところだった。 プログラミングが苦手だろうが関係ない、Nextに乗っかっておけばそこそこ早いWebサイトを作れる。
そんな中、App Router 以後はらくらくNext.jsではなくなってしまった。 気づいたら色々なことを学び直さなくてはなってしまった。 RSCが入ってきて、getServerSideProps は使わなくなり、設定より規約な性質も強まり、常識も根本から変わってしまった。 覚えるべきことが増え、シンプルではなくなってしまった。
そのような苦労や勉強の引き換えに手に入れたのはUXだ。 今のNext.jsはUXを追求するのためのライブラリになってしまったと思う。 だが、自分はPages Routerでもあまり困っていなかったし、Webサイトが早ければ早いのは理解できるが、それに引き換える学習コストが高すぎると思っていた。 それに App Router だろうが、DBやAPIGWの裏側が本当に遅いときはどうしようもないのだから解決しようがないし、あまり効果がないように思っている。 無理やり解決する場合も自分は CDN のレイヤーで戦えるのでそれで対応してしまえばいいと思っていたし、反対にApp Router以降のNext.jsはCDNと相性が悪いしで、むしろ嫌いだった。 だから自分は App Router 以後のNext.jsはなるべく使いたくなかった。
App Router を学ぶ理由
そんなこんなでApp Routerをする気はなかったし、Next.jsからも離れるつもりだった。 自分が設計したわけではないのだが、実際のところ今の職場でNext.jsを使わず自前でSSRしたり、そもそも普通のテンプレートエンジンで開発していると、これが結構よくて App Router なんてものは俺には不要と思っていた。 少なくとも Pages Router をずっと使い続ければいいと思っていた。
だが、最近はそんなことも言ってられなくってきた。
Pages Router だけの問題がでてきている
とはいえ Next のバージョン追従は必要だ。 そして最近は Next v13 x Pages Router でぶつかる問題を踏み抜き始めている。 例えば、https://github.com/vercel/next.js/issues/43585 が放置されていたりするのは困った。 Next.js 13 にあげるときに Pages のままでも、App Router でしか起きないはずのエラーが出る問題だ。 これは結局 compat の router を使えばいいのだが、そうすると router が nullable になって、色々な箇所を修正しないといけない。 基本は optional chain すればいいのだが、それだけで対処できない場面も多々あり対応が大変だった。 もう2度とやりたくない。 このように App Router 移行しないと踏み抜く問題を踏んでみて、渋々 App Router 移行を始めている。
古い知識が使えない
そんなこんなで App Routerに手を出してみるが、まず覚えるべき用語が多すぎるのと、ドキュメントを読む順番が分からなくなる。 これは先に思想を学んでから出ないと頭に入ってこず、思想を学ばないといけなかった。 内容が難しくなるのは仕方ないが、もっと楽に学べるコンテンツはないものかと困っていた。 つまり、きちんと勉強して理解することが求められ始めたのである。
Cache はいつでも危険
そして App Router には色々な落とし穴があり、その中でも Cache はとても危険だった。 なぜならCacheを使うと一気に個人情報流出や誤った情報の拡散につながってしまうことが増えるからだ。 App Router は App Router 特有の難しさがたくさんある。 さまざまな種類のCacheがあり、使い方を間違えると Cache したつもりでなくてもCacheされて事故になりうるし、かなり独特な仕組みだからCache-Conrolの知識も使えなくて困る。 本腰を入れてちゃんと学ぶ必要のあるものだ。
Nextの学び直しとしての実践 Next.js
そんなこんなで、App Router を手っ取り早くも確実に学ばなければいけないというニーズが自分にあった。 そこで出会ったのが 実践 Next.js だ。 結論からいうと良い本だった。
自分の読み方
Pages Router を知っているからと、読み飛ばす前提で最初は目次だけ見て、必要そうなところを読んでいた。 けど、それだけだとあまり読むべき箇所があるように思えなかった。 なので結局、全部頭から流し読みしてみて、知らないところがあったらそこを熟読するという形にした。 結構大事なことが、ハンズオンの章に書かれているので、とりあえず全部ざっと読んでみた方が良い。 本の中に「この節で学べること」というのが節ごとにあるので、自分はそこを見て知らないものだったら読むようにしていた。
各章の見どころ
そうやって各章で自分が学んだことをざっと書き出してみる。 もし自信のないところがあれば、手に取ってもらえると良い。
第2章: Server Componentとレンダリング
- dynamic rendering
- static rendering
公式ドキュメントだと https://nextjs.org/docs/app/building-your-application/rendering/server-components#server-rendering-strategies という深いところにあるものが最初から出てくる。 App Router の割と根幹な考え方だ。 最初に思想が提示されるので後々の学習が捗った。
第6章: データ取得とキャッシュ
- request のメモ化
- fetch のキャッシュ
- fetch以外のmemo化
- fetch以外のキャッシュ
App Router と一緒に語られがちな機能だがそれがいろんなパターンで知れて良かった。 fetch の場合は知っていたが、cache や unstable_cache などの、fetch 以外の場合でキャッシュやメモ化する方法を知らなかったのでそれは助かった。
第8章: モーダル表示とデータ連携
- pararell routers と intercepting routers のメリット
いわゆるモーダル画面を作る。 Next Conf か何かでpararell routers と intercepting routersを使ってインスタぽいものを作るトークがあったが、「こんなUI作る仕事じゃないし」と思ってスルーしていた機能だ。 モーダル画面にURLが発行されて、spa としての遷移と、navigateion requestで挙動が変わることに対して嬉しさを理解できていなかったのだが、ちゃんと解説されていて納得できた。
第9章: データ更新とUI
- server action の実践
server action を知った後に実際に使ってみると、できることが少なかったり、痒いところに届かなくてモヤモヤしていた。 そのモヤモヤを晴らしてくれる章だった。 いろんな実装パターンやテクニックを紹介してくれる。
cache purge と refresh を同じ場所に置いたり、useFormState, useFormStatus といったserver action前提のhoooksや、useOptismic との組み合わせを学べる。 実例があることが本当に嬉しかった章だ。
第10章: パフォーマンスとキャッシュ
- データの並列取得
- キャッシュされないときの対処
まず、RSCで末端コンポーネントでデータ取得すると並列取得できることの解説がある。 これはNextの嬉しさでよく語られているものなのでその解説があって嬉しかった。
あと、実務あるあるな意図しない Cache MISS の原因として親コンポーネントが認証情報持っているパターンなどの解説があった。 リクエストがバッチで行われているので、確かに一緒に巻き込まれるfetchはキャッシュしてはいけないと思われそうだ。 HTTP Cachingでもset-cookieされるとshared cacheにキャッシュしないみたいな挙動があったりするので、納得できた。 その場合に認証情報使うところだけCSRにした上で、キャッシュ制御を指示できるオプションがあることを学んだ。 章タイトルが「コンポーネント構造のパフォーマンスへの影響」なのだが、納得できた。 最後にCacheが4つのcacheとして整理されているのも良かった。 キャッシュされないことの問題と同様に、認証が原因で静的レンダリングも動的レンダリングに切り替わることの解説もある。
総評として
潤沢なサンプルコードから思想を学べる本。 これを読んでから公式ドキュメントを読み直すとすいすい入ってきた。 確かに公式ドキュメントを読み返すと同じことは書いてあるのだけれども、思想やキーワードが埋め込まれていないと読めなかった。 例えば、Segment, RouteHandler, DataCache, Dynamic Rendering などと聞いて説明できない人は買った方が良いと思う。 あとはNextやReactを追っていないけど、useFormStateなどのキーワードだけ聞いたことある人など。 公式ドキュメントの最後の方まで読まないと知れない思想も、最初から噛み砕かれて説明されていて、とても良かった。 「App Router は学習コストを引き換えに、少しUXが良くなるだけだし勉強したくない」と思っている人は、一度この本を読んでみると良いと思う。 学習コストをかけずにUXを良くできるようになると思う。 知らんけど。