Slide 1

Slide 1 text

そのコンポーネント、 サーバー?クライアント? App Routerの不明瞭なコンポーネント実行環境を可視化する 2025.08.27 実践Next.js!「AIアウトプットとコンポーネント設計」 最新Tips Makoto Tateno

Slide 2

Slide 2 text

2 / 26 自己紹介 Makoto Tateno / 舘野 真 株式会社カオナビ github.com/makotot x.com/makototdev

Slide 3

Slide 3 text

3 / 26

Slide 4

Slide 4 text

4 / 26 話すこと 1. React Server Componentsのおさらい 2. 実行環境はどうやって決まる? 3. 不明瞭さと向き合う取り組みの事例紹介

Slide 5

Slide 5 text

5 / 26 RSCのおさらい (1/2) React Server Components とは: サーバーでのみ実行するサーバーコンポーネントと従来のクライアントコンポーネントを組み合わせて、 サーバーとクライアントを行き来する新しい仕組み Next.js App Routerで利用可能 利点: サーバーでのみ実行することでJavaScriptバンドルサイズを削減 秘匿情報やサーバーリソースへのアクセスが容易に 新たな課題: サーバーかクライアントか、開発者自身が実行環境を意識する必要性

Slide 6

Slide 6 text

6 / 26 RSCのおさらい (2/2) サーバーコンポーネントはサーバー環境で利用可能なものだけ実行できる クライアントコンポーネントはブラウザー環境で利用可能なものだけ実行できる この実行環境による違いをビルドエラーで気づく経験は多くの開発者がしているはず

Slide 7

Slide 7 text

7 / 26 1つのプログラム サーバーとクライアントを行き来することを1つのプログラムとして扱ってシームレスに行える サーバー・クライアントいずれの実行環境で動くコンポーネントかは、開発者自身で意識する必要がある They let you model a client/server application as a single program spanning the two machines without losing sight of the reality of the network and serialization gap. That, in turn, allows seamless composition across the network. 引用元:https://overreacted.io/what-does-use-client-do/

Slide 8

Slide 8 text

8 / 26 実行環境はどうやって決まる?

Slide 9

Slide 9 text

9 / 26 境界はuse client ディレクティブ デフォルトは、サーバーコンポーネント use client ディレクティブによってオプトインでクライアントコンポーネントに "use client"; // クライアントコンポーネントとして扱うディレクティブ export function ClientComponent() { return
Client Component
; }

Slide 10

Slide 10 text

10 / 26 import で伝播してクライアントコンポーネントに クライアントコンポーネントになるのは、 use client ディレクティブの記述があるファイル use client ディレクティブがあるファイルから import するファイル 以降すべてクライアントコンポーネントとして扱う コンポーネントの use client 呼び出し元のコンポーネントの種類 コンポーネントとしての扱い ❌ サーバー サーバー ✅ サーバー クライアント ❌ クライアント クライアント ✅ クライアント クライアント ❌ クライアント (Props経由) サーバー (Propsとして渡す場合は親の影響を受けない)

Slide 11

Slide 11 text

11 / 26 図にして見る実行環境 App Header import Page import Container import Article import Container import Comments import 'use client'; Comment Button import import Context children 'use client'; Text import import Heading import use client ディレクティブがあるコンポーネントから先 の import はクライアントコンポーネントに コンポジションによりサーバーコンポーネントをクライアン トコンポーネントよりも深い階層に配置できる 複数箇所で利用されるサーバーコンポーネントは、利用元に よって実行環境が変わり得る

Slide 12

Slide 12 text

12 / 26 ルールは明確でも… メンタルモデルの変化が必要 従来はクライアントコンポーネントにあたるコンポーネントしか無かった あるファイルのコンポーネントの実行環境を知りたければ、依存関係を辿る必要がある use client ディレクティブがあるファイルは、実行環境の把握が容易 use client ディレクティブがないファイルは、実行環境が別のファイルに依存 レンダーツリーの深い階層になるほど、実行環境を把握することが困難に

Slide 13

Slide 13 text

13 / 26 コンポーネントの実行環境を 明確にするには

Slide 14

Slide 14 text

14 / 26 サーバーコンポーネントを避ける レンダーツリーの上位で use client を宣言すれば、実行環境をあまり意識しないで済むようになるが JavaScriptバンドルサイズの削減 柔軟なサーバーリソースへのアクセス といった利点を手放すことに 😢

Slide 15

Slide 15 text

15 / 26 推測しやすく設計しておく 辿る範囲が限定的になるほど、実行環境を推測しやすくなる 例として、今取り組んでいるプロジェクトでは、以下のような設計を採用 機能単位でディレクトリーを構成して、関連性の高いファイルをコロケーション Container/Presentationalパターン ファイル名・ディレクトリー名規約でクライアントコンポーネントになる範囲を明示 use client ディレクティブを使用する場合、 .client.tsx にするなど なお、Reactの当初のRFCでは、ファイル名で実行環境を分けることが提案されていた 汎用的なクライアントコンポーネントは、明示的に use client を宣言することで自己完結

Slide 16

Slide 16 text

16 / 26 Lint 実行環境を誤っていることをLintで防げるなら防ぎたいが Next.js公式のESLintプラグインでは、包括的に防ぐことが現時点では難しい状況 @next/next/no-async-client-component は、 use client が記述されているファイル自体にしか適用されない

Slide 17

Slide 17 text

17 / 26 ブラウザー拡張機能 React Developer Toolsでは、サーバーコンポーネントにラベルが付くので、ブラウザー上でコンポーネント の実行環境を確認できる

Slide 18

Slide 18 text

18 / 26 でも、本当に欲しいのは 「コードを書いている、その瞬間」に 「エディターで」実行環境を知ること

Slide 19

Slide 19 text

19 / 26 エディターで可視化する方法 3つのことが実現できれば、エディターでフィードバックを得られる コンポーネントの依存関係を解析 ts-morphを使えばTypeScriptのプロジェクトの依存関係はコンパイラーAPIを通じて生成できそう use client ディレクティブの検出 AST解析してディレクティブの存在チェックすれば良い 解析した結果をエディター上に表示 VS CodeのAPIでおそらく実現できそう

Slide 20

Slide 20 text

20 / 26 VS Code拡張機能の全体イメージ この3つの要素を元に、拡張機能の大まかな設計 をすると、必要なのは、 App Routerの依存関係を解決して、コンポーネント実行環 境を判定して依存関係を抽出するモジュール VS Codeの各所に実行環境を可視化するモジュール VSCode ファイルツリー 開いているファイルの現在の行 ステータスバー VSCode Extension APIs ComponentFileDecorationProvider ClientComponentLineDecorator ClientComponentStatusbar Core Logic DependencyGraph 実行環境を判別 (Server/Client/Shared) 依存グラフをts-morph で生成 結果を渡す 表示 表示 表示

Slide 21

Slide 21 text

21 / 26 AIエージェントの活用 実現イメージできたが、自分で実装は面倒... 開発を支援するツールだし、試作するのはAIエー ジェントがちょうどいいのでは? yo code でVS Code拡張機能の雛形を生成したら あとはお任せしよう ほぼ、GitHub Copilot Agentによる実装 人間は、大枠の指示と、APIの使い方の誤りなどを指摘する だけ

Slide 22

Slide 22 text

22 / 26 VS Code拡張機能としてリリース ファイルの実行環境を一目でわかるように   サーバーコンポーネント(デフォルトなので、何も出さない) ⚡️ クライアントコンポーネント ♾️ 両方あり得るコンポーネント 実装中に実行環境を認識できる「補助輪」のような存在 $ code --install-extension makotot.vscode-nextjs-component-boundary-visualizer

Slide 23

Slide 23 text

23 / 26

Slide 24

Slide 24 text

24 / 26 課題感 成果物が求めているものかどうか、AIエージェントによるコード生成スピードに追いつくのが大変 コア機能となる依存グラフ生成のモジュールが期待通りかは最低限単体テストを書かせた 対象プロジェクトの規模が大きくなると、パフォーマンスに大きな課題がある コンポーネント数が多いプロジェクトほど実行環境の把握を効率的に行うために可視化したいが... ts-morphの代替案があれば検討したいが...

Slide 25

Slide 25 text

25 / 26 まとめ React Server Componentsによって、1つのプログラムとしてサーバーとクライアントを行き来しやすくなっ た反面、実行環境の不明瞭さが生まれた コンポーネントの実行環境の不明瞭さは、工夫次第で最小化できる 開発補助ツールの実現にAIエージェントは有効な手段 期待したものを生成しているか最低限テストが必要 今日お話しした内容は、Zennの記事、 「Next.js App RouterのコンポーネントをVS Codeでサーバー・クライ アント別に可視化する」がベースになっているので、こちらもぜひご覧ください

Slide 26

Slide 26 text

ありがとうございました!