Next.js 13 での「Use Client」ディレクティブの仕組み
<p>Next.js 13.4 と新しい <code>app/</code> ディレクトリを使用したサーバーサイド レンダリングについて学ぼうとしています。私が理解しているところによると、すべてのコンポーネントはデフォルトで <em>server</em> コンポーネントです (つまり、サーバー側でレンダリングされます)。 </p>
<p>ただし、<code>'use client'</code> ディレクティブを使用して、コンポーネントを強制的に <em>client</em> コンポーネントにすることができます。 </p>
<p>以下では、単純な「Hello World」コンポーネントを、最初にサーバー コンポーネントとして、次にクライアント コンポーネントとしてセットアップしました。それぞれのケースで、ページのソース コードを比較します。</p>
<h3><code>src/app/page.js</code>(サービス务器コンポーネント)</h3>
<pre class="brush:php;toolbar:false;">デフォルト関数 Home() をエクスポート {
戻る (
<メイン>
<h1>Hello World</h1>
</メイン>
)
}</pre>
<p>クローム>查看页面源代网</p>
<pre class="brush:php;toolbar:false;"><!DOCTYPE html>
<html lang="ja">
<頭>
<meta charSet="utf-8" />
<title>次のアプリを作成</title>
<meta name="description" content="次のアプリの作成によって生成されました" />
<meta name="viewport" content="width=device-width、initial-scale=1" />
<script src="/_next/static/chunks/polyfills.js" noModule=""></script>
</head>
<本体>
<メイン>
<h1>Hello World</h1>
</メイン>
<script src="/_next/static/chunks/webpack.js" async=""></script>
<script src="/_next/static/chunks/main-app.js" async=""></script>
<script>(self.__next_f = self.__next_f || []).push([0])</script>
<script>self.__next_f.push([1, "0:"$L1"n"])</script>
<script>self.__next_f.push([1, "2:I{"id":"(app-client)/./node_modules/next/dist/client/components/app-router.js","chunks ":["webpack:static/chunks/webpack.js"],"name":"","async":false}n4:I{"id":"(app-client)/./node_modules/next/ dist/client/components/error-boundary.js","chunks":["webpack:static/chunks/webpack.js"],"name":"","async":false}n6:I{"id ":"(app-client)/./node_modules/next/dist/client/components/layout-router.js","chunks":["app-client-internals:static/chunks/app-client-internals. js"],"name":"","async":false}n7:I{"id":"(app-client)/"])</script>
<script>self.__next_f.push([1, "./node_modules/next/dist/client/components/render-from-template-context.js","chunks":["app-client-internals:static /chunks/app-client-internals.js"],"name":"","async":false}n"])</script>
<script>self.__next_f.push([1, "1:[[],["$","$L2",null,{"assetPrefix":"","initialCanonicalUrl":"/","initialTree ":["",{"children":["__PAGE__",{}]},"$未定義","$未定義",true],"initialHead":["$L3",null],"globalErrorComponent" :"$4","notFound":["$","html",null,{"lang":"en","children":["$","body",null,{"children":[ "$L5","$unknown",[["$","title",null,{"children":"404: このページは見つかりませんでした。"}],["$","div", null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"" ,"height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"}, "children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;背景:#fff;マージン:0}.next-error-h1{border-right:1px ソリッド rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color: #fff;background:#000}.next-error-h1{border-right:1px Solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className" :"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize": 24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style" :{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight": "49px","margin":0},"children":"このページが見つかりませんでした。"}]}]]}]}]]]}]}],"asNotFound":false,"children":[["$","html",null,{"lang":"en","children":["$","body",null,{" Children":["$","$L6",null,{"ParallelRouterKey":"children","segmentPath":["children"],"error":"$unknown","errorStyles":"$unknown ","loading":"$unknown","loadingStyles":"$unknown","hasLoading":false,"template":["$","$L7",null,{}],"templateStyles": "$unknown","notFound":"$unknown","notFoundStyles":"$unknown","childProp":{"current":[["$","main",null,{"children":[ "$","h1",null,{"children":"Hello World"}]}],null],"セグメント":"__PAGE__"},"スタイル":[]}]}]}],null ]}]]n"])</script>
<script>self.__next_f.push([1, "5:[[["$","meta",null,{"charSet":"utf-8"}],null,null,null,null, null,null,null,null,null,null,["$","meta",null,{"name":"viewport","content":"width=デバイス幅、初期スケール=1"} ]、null、null、null、null、null、null、null、null、null、null、[]]、[null、null、null、null]、null、null、[null、null、null、null、null ],null,null,null,null,null]n3:[[["$","meta",null,{"charSet":"utf-8"}],["$","title",null ,{"children":"次のアプリの作成"}],["$","meta",null,{"name":"説明","content":"次のアプリの作成によって生成"}],null, null,null,null,n"])</script>
<script>self.__next_f.push([1, "ull,null,null,null,["$","meta",null,{"name":"viewport","content":"width=device) -width, 初期スケール=1"}]、null,null,null,null,null,null,null,null,null,null,[]],[null,null,null,null],null,null, [null,null,null,null,null],null,null,null,null,null]n"])</script>
</ボディ>
</html></pre>
<h3><code>src/app/page.js</code>(客户端组件)</h3>
<pre class="brush:php;toolbar:false;">'クライアントを使用';
デフォルト関数 Home() をエクスポート {
戻る (
<メイン>
<h1>Hello World</h1>
</メイン>
)
}</pre>
<p>Chrome > 查看页面源代码</p>
<pre class="brush:php;toolbar:false;"><!DOCTYPE html>
<html lang="en">
<head>
<meta charSet="utf-8" />
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="/_next/static/chunks/polyfills.js" noModule=""></script>
</head>
<body>
<main>
<h1>Hello World</h1>
</main>
<script src="/_next/static/chunks/webpack.js" async=""></script>
<script src="/_next/static/chunks/main-app.js" async=""></script>
<script>(self.__next_f = self.__next_f || []).push([0])</script>
<script>self.__next_f.push([1, "0:"$L1"n"])</script>
<script>self.__next_f.push([1, "2:I{"id":"(app-client)/./node_modules/next/dist/client/components/app-router.js","chunks":["webpack:static/chunks/webpack.js"],"name":"","async":false}n4:I{"id":"(app-client)/./node_modules/next/dist/client/components/error-boundary.js","chunks":["webpack:static/chunks/webpack.js"],"name":"","async":false}n6:I{"id":"(app-client)/./node_modules/next/dist/client/components/layout-router.js","chunks":["app-client-internals:static/chunks/app-client-internals.js"],"name":"","async":false}n7:I{"id":"(app-client)/"])</script>
<script>self.__next_f.push([1, "./node_modules/next/dist/client/components/render-from-template-context.js","chunks":["app-client-internals:static/chunks/app-client-internals.js"],"name":"","async":false}n8:I{"id":"(app-client)/./src/app/page.js","chunks":["app/page:static/chunks/app/page.js"],"name":"","async":false}n"])</script>
<script>self.__next_f.push([1, "1:[[],["$","$L2",null,{"assetPrefix":"","initialCanonicalUrl":"/","initialTree ":["",{"children":["__PAGE__",{}]},"$未定義","$未定義",true],"initialHead":["$L3",null],"globalErrorComponent" :"$4","notFound":["$","html",null,{"lang":"en","children":["$","body",null,{"children":[ "$L5","$unknown",[["$","title",null,{"children":"404: このページは見つかりませんでした。"}],["$","div", null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"" ,"height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"}, "children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;背景:#fff;マージン:0}.next-error-h1{border-right:1px ソリッド rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color: #fff;background:#000}.next-error-h1{border-right:1px Solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className" :"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize": 24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style" :{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight": "49px","margin":0},"children":"このページが見つかりませんでした。"}]}]]}]}]]]}]}],"asNotFound":false,"children":[["$","html",null,{"lang":"en","children":["$","body",null,{"children":["$","$L6",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"template":["$","$L7",null,{}],"templateStyles":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined","childProp":{"current":[["$","$L8",null,{"params":{},"searchParams":{}}],null],"segment":"__PAGE__"},"styles":[]}]}]}],null]}]]n"])</script>
<script>self.__next_f.push([1, "5:[[["$","meta",null,{"charSet":"utf-8"}],null,null,null,null, null,null,null,null,null,null,["$","meta",null,{"name":"viewport","content":"width=デバイス幅、初期スケール=1"} ]、null、null、null、null、null、null、null、null、null、null、[]]、[null、null、null、null]、null、null、[null、null、null、null、null ],null,null,null,null,null]n3:[[["$","meta",null,{"charSet":"utf-8"}],["$","title",null ,{"children":"次のアプリの作成"}],["$","meta",null,{"name":"説明","content":"次のアプリの作成によって生成"}],null, null,null,null,n"])</script>
<script>self.__next_f.push([1, "ull,null,null,null,["$","meta",null,{"name":"viewport","content":"width=device) -width, 初期スケール=1"}]、null,null,null,null,null,null,null,null,null,null,[]],[null,null,null,null],null,null, [null,null,null,null,null],null,null,null,null,null]n"])</script>
</ボディ>
</html></pre>
<p>ゲスト端末のコンポーネントが HTML をすでに汚染しているため、私たちは考えていますが、「Hello World」は React Root DOM ポイントに似たものであり、基本的には空であると考えています。 div 等にいくつかの HTML を埋め込んでいます。私はここに何か足りませんか?</p>