ここ半年くらいのReactとNext.jsのトレンドを確認する
はじめに
半年〜1年くらいあんまりReactやってなくて、久しぶりにNext.jsをインストールして動かしていたら、初期のディレクトリ構成が結構変わってたり、何かエラーになって"use client";
って入れてよ!って言われたりして、よくわからんけどなんか取り残されてた気がしました。
で、改めてきちんと調べました。同じように流行に乗り損ねたけど、Reactやるぜって方の参考になればと思います。トレンド追うって大事ですよね。。時代遅れてる。。
ここでは、React18とNext.js13についてわかったことをお話します。
React
並行機能
18から大きく追加された機能として、並行処理機能が挙げられていました。この機能はいわばReactの本質的な変更に迫るものらしく、以下のように解説されています。
我々が API を設計する際には、開発者に実装の詳細を見せないように努力しています。React 開発者としてみなさんはユーザ体験をどんな見た目にしたいかを考えることに集中し、その見た目をどのように実現するのかは React が受け持ちます。React 開発者が、裏で並行処理機能がどのように働いているのかを知る必要はありません。
しかし、React の並行処理機能は、普通の「実装の詳細」と比べてより重要なものであり、React のコアのレンダリングモデルに対する本質的な変更です。ですので並行処理の動作について詳しく知ることがもの凄く重要ということではないにせよ、どのようなものかについて高レベルの概観を知っておくことは有用かもしれません。
参考
どこが重要かというと、処理を中断可能ということです。中断して後で行う、みたいなことができるようになるらしいです。
Reactのレンダリング方法は、ざっくり大まかに言えば以下のような感じなのですが、このレンダー処理部分がどうやら並行で行えるみたいです。
- state等が変更を検知する(トリガ)
- ComponentからDOMを構成する(レンダー)
- 現在のDOMと構成したDOMを差し替える(コミット)
Vue.jsなんかはdataやcomputedが変更を検知してその部分だけポッと変更をかけてくれたりするのですが、Reactは基本的に1つでも監視対象の変更を検知したComponentに対しては、(メモ化例外は置いといて)まるっとレンダーし直す構成です。
↑のこととかを考えていると、どうしてもDOMが大きくなればなるほど再レンダーには時間がかかっているはずなので、こういう並行処理はパフォーマンスに有用なのかなと。機能自体は、基本的に中の方に隠蔽してくれているらしいので、「そうなんだ」と思うことにしました。
新機能
自動バッチング
レンダー時に複数のstateをグループ化して、単一の再レンダーにまとめてくれる機能です。パフォーマンス改善のために取り込まれた機能で、通常はあまり意識する必要はないですが、逆に「バッチしたくない」という時にはバッチをオプトアウトする必要が出てきそうです。
トランジション
トランジションはstartTransition
でラップして処理することにより、「緊急性は高くない」と伝えることができる機能です。デフォルトでは今まで通り緊急性が高いものとして認識され、この関数でラップされたものは、通常のstateの更新等が発生した場合、処理を中断して最後の更新に合わせてレンダーし直してくれます。
早速、並行レンダー機能が使われているなと思いました。
サスペンス
思い処理を行う時、これまではローディング用のstateを1つ用意して、処理中はloading = true
にしておいて、処理を終えたらloading = false
にする、みたいなことを行っていましたが、このローディング機能をサスペンスが担ってくれるらしいです。
<Suspense fallback={<Spinner />}>
<Comments />
</Suspense>
初回読み込みが早くなると思いました。また、自前で用意するローディング系の処理がなくなることで、コンポーネント自体もすっきりする気がします。
その他: ハイドレーション
新しくuseId
というフックが誕生したのですが、こちらを理解するためには、事前にハイドレーションというキーワードについて理解を深める必要がありました。ハイドレーションはClientComponentとServerComponentを考える上で重要だったので、備忘録として残しました。
ハイドレーションは以下の通り、サーバーサイドでレンダリングされたHTMLをクライアントのDOMにいい感じに接続するために利用します。
In React, “hydration” is how React “attaches” to existing HTML that was already rendered by React in a server environment. During hydration, React will attempt to attach event listeners to the existing markup and take over rendering the app on the client.
参考
ハイドレーションする際にはクライアントのHTMLとサーバーで生成したHTMLを合わせる必要があり、ハイドレーションの不整合はバグの温床のため、Reactに厳しくチェックされます。
useIdはクライアントとサーバで一意な ID を生成するためのフックです。
利用方法は以下がとてもわかりやすかったです。
Next.js
Server Component
次にNext.jsの方を見てみようかなと思ったのですが、Next.js初手のページで、重要なReactの概念としてReact Server Componentに触れられてみました。せっかくなので、こちらもきちんと理解をしようかなと思って、残しました。
もはやすべてここに書いてあるといっても過言ではないのですが、最近のNext.jsはコンポーネントのレンダリングをサーバーに任せるかクライアントサイドで行うかについては基本的に考えて設計しながら進めることをが必要不可欠みたいですね。考え方的にはシンプルで、データフェッチを行うコンポーネントはServer、イベント処理やstateを利用した状態遷移などを行う場合はClientという形で分けるのが良い。
で、この思想を元にここから13アップデート内容みたいなのですが、基本的にはServerに寄せるのが良いから、デフォルトではこちらにされて、もしもClient Componentにしたい場合は"use client";
と明示的に指定する必要があるみたいです。
冒頭の私の場合は、hooksを利用していたので、「それはClient componentよ!」と怒られていたわけでした。
appディレクトリ
pagesがなくなってたの、驚きました。
このappディレクトリの中で(昔はpages直下で行っていた)ルーティングの処理を行うことができます。イメージは以下です。
- app/page.tsx ※
pages/index.tsx
と同じ- URLPath: /
- app/blog/page.tsx
- URLPath: /blog
また、同じディレクトリ内にlayout.tsx
という名前でレイアウトを定義すると、そのレイアウトコンポーネントが複数ページで共有される仕組みになるそうです。
Streaming
コンポーネントを漸次読み込んでレンダリングしてくれるので、パフォーマンスが良くなるよという話でした。デフォルトでNext.jsがやってくれるみたいなので、特に私たちは意識する必要がないかなと思いました。
その他、Webpackの後継となるTurbopackの紹介や、next/link
やnext/image
等の強化、middlewareの新機能にも触れていました。が、めぼしいところで言えばディレクトリの構造が大きく変更になったところが大きいかなと思います。
おわりに
React機能そのものにしても、私たちReact開発者にしても、パフォーマンスには気を配らなきゃいけない時代だなと思った次第でした。そういった目的の機能やアップデートが多い気がしてます。
常々思うのですが、Reactは基本公式として覚えることは結構少ないと思っています。なので、すぐにサクサクかけると思ってます。が、Reactが裏で色々としてくれる分、裏側をよく知らないといざエラーの意味に出くわした時に、全く検討がつかない…といったことが多い気もします。Reactの思想や最新の情報をきちんと追うようにしていきたいなと思いました。
Discussion