[Next.js]RSCとRCCを分かりやすく定義して混乱を防ぐ
問題提起
ReactとNext.jsはサーバーコンポーネント(RSC)とクライアントコンポーネント(RCC)の2種類のコンポーネントを扱えます。
import 'server-only'
を使うと必ずRSCとしてレンダリングされ、'use client'
を使うとRCCとしてレンダリングされます。
(正確に言うと、server-onlyを付けることでRCCとして動かそうとするとエラーになる)
問題になるのが何もつけなかったときで、これは親コンポーネントと同じ属性でレンダリングされます。
そのため、何もつけないコンポーネントはRSCとしてもRCCとしても動くコンポーネントでなければなりません。
しかし単純にimport 'server-only'
もuse client
も書き忘れている可能性もあります。
また、親コンポーネントが明確であるため記述を省略しているかもしれません。
このようなコンポーネントは意図しない場所からインポートされ、エラーが発生する可能性があります。
今回はその対策を考えてみます。
対象読者
- Next.jsを使って開発をしているフロントエンドエンジニア
- チーム開発でコンポーネントの管理を明確にしたいと考えている人
提案内容
'use client'
ディレクティブについて、Next.jsの公式ドキュメントでは、以下のように説明されています。
"use client" is used to declare a boundary between a Server and Client Component modules. This means that by defining a "use client" in a file, all other modules imported into it, including child components, are considered part of the client bundle.
Next.jsドキュメント - Using Client Components in Next.js
'use client'
はRCCとしてレンダリングされる境界を示すと書かれています。
これは正しいのですが、'use client'
は境界以外に記述してもよいです。
そして、私はすべてのRCCに'use client'
を書くことを提案します。
コンポーネントを定義してから、それを使って画面を組み立てる以上、実装時にはどこが境界になるか分からないことがよくあります。
また、コンポーネントが意外なところで使われる可能性もあります。
そのため、チーム開発では以下のルールを守るのが無難です。
提案ルール
- RSCとして定義したコンポーネントには
import 'server-only'
を必ずつける - RCCとして定義したコンポーネントには
'use client'
を必ずつける - どちらでも動かせるコンポーネントに
'use universal'
と書く
'use universal'
に特別な意味はありませんが、あえて書きます。
何も書かないことに意味を持たせると「書き忘れなのか、意図的に書いていないのか」が判断できません。
そのため、RSCでもRCCでも動作するコンポーネントには明示的に'use universal'
と記述するとレビュー時や後から見返したときにすぐに理解できます。
eslintでディレクティブが何も書かれていないコンポーネントはエラーにすることで、さらに統制を強められるでしょう。
このように明示的に分類することで、意図しない動作を防ぎ、チーム開発における混乱を減らすことができます。
Discussion