herohoroブログ

client componentをserver componentにして速度を改善させる方法



🔄   2023-04-27

みなさま、

覚えているでしょうか!?

あれからもう4ヶ月経ちました。。。。

2022/11/28

差分 +1319 -1190

という大規模アップデート

丁寧な解説記事、

公式ドキュメントのリンク、

image block

ライブコーディング、

手厚い対応だったにも関わらず

Next.js13にしてから

この世のものとは思えない遅さの

ブログが出来上がってしまいました…..

+2246 -2271

全力で頑張った…..

何をどう修正したらいいのか分からず

途方に暮れたままだったのですが、

このドキュメントを読んで

急にひらめいたのです。

ChatGPT先生によって解決することができたので

記事にするまでもないかなと思ってたのですが、

チャベスさんからリクエストいただいたので

公式ドキュメントで特に参考になった部分を抜粋し、

NotionAIに翻訳してもらいつつ….

ChatGPTとのやりとりを含めて紹介しようと思いますwwww

原因:use clientの過剰摂取

公式ドキュメントを読むと今までのコードのままClientの設定をしてしまうと

余計遅くしてしまうんだということが分かりました。

▽ 以下、公式ドキュメント

Next.js provided an easier way to break down your application into pages and prerender on the server by generating HTML and sending it to the client to be hydrated by React. However, this led to additional JavaScript needed on the client to make the initial HTML interactive.

Next.js13以前は、アプリケーションをより簡単にページに分割し、HTMLを生成してサーバー上でプリレンダリングし、Reactによってクライアントに送信されてhydrateされる方法を提供しています。しかし、これにより、初期のHTMLをインタラクティブにするために、クライアント側で追加のJavaScriptが必要になりました。

Now, with Server and Client Components, React can render on the client and the server meaning you can choose the rendering environment at the component level.

Next.js13以降は、サーバーとクライアントのコンポーネントを使用することで、Reactはクライアントとサーバーの両方でレンダリングできるため、コンポーネントレベルでレンダリング環境を選択できます。

With Server Components, the initial page load is faster, and the client-side JavaScript bundle size is reduced. The base client-side runtime is cacheable and predictable in size, and does not increase as your application grows. Additional JavaScript is only added as client-side interactivity is used in your application through Client Components.

サーバーコンポーネントを使用すると、初期ページのロードが速くなり、クライアントサイドのJavaScriptバンドルサイズが削減されます。ベースのクライアントサイドランタイムは、キャッシュ可能で予測可能なサイズであり、アプリケーションが成長しても増加しません。追加のJavaScriptは、アプリケーションでクライアントサイドの相互作用が使用されるときにのみ、クライアントコンポーネントを通じて追加されます。

Once "use client" is defined in a file, all other modules imported into it, including child components, are considered part of the client bundle.

「use client」がファイルで定義されると、子コンポーネントを含む他のすべてのモジュールがクライアントバンドルの一部と見なされます。

In Next.js, Server Components are the default. Therefore all React components are part of the Server Component module graph unless defined or imported in a module that starts with the "use client" directive.

Next.jsでは、Server Componentsがデフォルトです。したがって、すべてのReactコンポーネントは、"use client"ディレクティブで始まるモジュールで定義された場合を除き、Server Componentモジュールグラフの一部です。

ChatGPT:なるべく専門用語を使って指示する

公式ドキュメントにある用語はなるべく使って指示すると

ベストな解答を得られるなと感じました。(あくまで個人的な感想です)

構文とかあまり詳しくないので
そのまま渡しています。

  1. 修正してほしい部分のコードを貼り付ける
  2. 何をどう変えてほしいか伝える

これだけです(๑`·ᴗ·´๑)

❓ Prompt

```
import { Link as Scroll } from 'react-scroll'
import styles from '../styles/page.module.css'

const TopJump = () => {
return (
<Scroll to="topJump" className={styles.topJump} smooth={true}>
Top
</Scroll>
)
}
```
Client-coomponentをserver-componentにしたいので、修正してください。

💬 Answer

To avoid using the react-scroll package, which is a client-side solution, you can implement a server-side solution using an anchor tag and an id attribute. Here's a modified version of your code:

import styles from '../styles/page.module.css'

const TopJump = () => {
  return (
    <a href="#topJump" className={styles.topJump}>
      Top
    </a>
  )
}

export default TopJump

In your target component where you want to scroll to, add an id attribute with the value "topJump". For example:

<div id="topJump">
  {/* Your component content */}
</div>

This solution uses a simple anchor tag to navigate to the element with the specified id. The browser will handle the scrolling without any client-side JavaScript. Note that this approach won't have a smooth scrolling effect like the react-scroll package. If you still want the smooth scrolling effect, you can enable it using CSS:

/* Add this to your styles/page.module.css or any global CSS file */
html {
  scroll-behavior: smooth;
}

This CSS rule will enable smooth scrolling for the entire document when navigating through anchor links.

修正した内容

import styles from '../styles/page.module.css'

const TopJump = () => {
  return (
    <a href="#topJump" className={styles.topJump}>
      Top
    </a>
  )
}

export default TopJump

ChatGPT:VSCodeの使い方を教えてもらう

use clientの修正をしてyarn devしてみると

エラーになってしまったので

また手直しする必要が出てきました。

image block

どのファイルかが分からないので修正しようがない….。

これもChatGPTに教えてもらうことにしました。

❓ Prompt

VSCodeの検索機能でonClickを見つける方法を教えて下さい

💬 Answer

Visual Studio Code (VSCode) で onClick を見つける方法を以下に説明します。

  1. VSCode を開いて、対象のプロジェクトフォルダを開きます。
  2. サイドバーの上部にある「検索」アイコン(虫眼鏡)をクリックするか、Ctrl + Shift + F(Windows)または Cmd + Shift + F(Mac)を押して、全体検索を開きます。
  3. 検索バーに onClick と入力し、Enter キーを押して検索を開始します。
  4. 検索結果に一致するファイルと行が表示されます。ファイル名や行番号をクリックすると、該当箇所にジャンプできます。

これにより、プロジェクト内のすべての onClick を含む箇所を見つけることができます。検索結果を注意深く確認して、問題のあるコードを修正してください。

また、検索オプションを利用して、より具体的な検索を行うことができます。例えば、<aonClickを同時に含む行を検索するには、検索バーに<a.*onClickと入力し、正規表現検索を有効にするために検索バー右側の「.*」アイコンをクリックしてください。


教えてもらった通りに操作したら該当ファイルを発見\(^o^)/

image block

🤔
onClickをどう修正したらいいのか分からない…..
❓ Prompt

```
export const BackPageLink = ({ firstPost, posts }) => {
if (!firstPost) return null
if (posts.length === 0) return null

const lastPost = posts[posts.length - 1]

if (firstPost.Date !== lastPost.Date) return null

const handleBack = () => {
if (typeof window !== 'undefined') {
window.history.back()
}
}

return (
<div className={styles.nextContainer}>
<div className={styles.buttonSubContainer}>
<a className={styles.backButton} onClick={handleBack}>
{' '}
< Back{' '}
</a>
</div>
</div>
)
}

```
修正したファイルから心当たりを見つけられました。
このコードはserver-componentに修正したものです。
エラーをなくすにはどうしたらいいですか?

💬 Answer

エラーが発生している原因は、サーバーコンポーネントにインタラクティブなイベントハンドラ(この場合は onClick)を渡しているためです。これを解決するには、クライアントコンポーネントにインタラクティブな部分を移動させる必要があります。

1つの方法は、BackPageLinkをサーバーコンポーネントとクライアントコンポーネントの2つに分割することです。以下はその方法を示す例です:

BackPageLink.server.js (サーバーコンポーネント):

import { BackPageLinkClient } from './BackPageLink.client';

export const BackPageLink = ({ firstPost, posts }) => {
  if (!firstPost) return null;
  if (posts.length === 0) return null;

  const lastPost = posts[posts.length - 1];

  if (firstPost.Date !== lastPost.Date) return null;

  return <BackPageLinkClient />;
};

BackPageLink.client.js (クライアントコンポーネント):

import React from 'react';
import styles from './BackPageLink.module.css';

export const BackPageLinkClient = () => {
  const handleBack = () => {
    if (typeof window !== 'undefined') {
      window.history.back();
    }
  };

  return (
    <div className={styles.nextContainer}>
      <div className={styles.buttonSubContainer}>
        <a className={styles.backButton} onClick={handleBack}>
          {' '}
          < Back{' '}
        </a>
      </div>
    </div>
  );
};

この方法では、BackPageLink.server.jsがサーバーコンポーネントであり、条件に基づいてBackPageLinkClient(クライアントコンポーネント)をレンダリングします。クリックイベントはクライアントコンポーネント内で処理されるため、エラーが解決されるはずです。

修正した内容

import { BackPageLinkClient } from './backpage.client'

export const BackPageLink = ({ firstPost, posts }) => {
  if (!firstPost) return null
  if (posts.length === 0) return null

  const lastPost = posts[posts.length - 1]

  if (firstPost.Date !== lastPost.Date) return null

  return <BackPageLinkClient />
}
component/backpage.tsx

import styles from '../styles/blog-parts.module.css'

export const BackPageLinkClient = () => {
  const handleBack = () => {
    if (typeof window !== 'undefined') {
      window.history.back()
    }
  }

  return (
    <div className={styles.nextContainer}>
      <div className={styles.buttonSubContainer}>
        <a className={styles.backButton} onClick={handleBack}>
          {' '}
          < Back{' '}
        </a>
      </div>
    </div>
  )
}
component/backpage.client.tsx

まとめ

  1. use clientを使わずに記述できる部分はなるべくserver-componentにする
  2. 切り分けが必要な部分は別途client用のファイルを作っってserver用ファイルにつなげる

この2つをやるだけでだいぶ良くなりました\(^o^)/

このブログはだいぶ改造してしまっているので

役に立つか分かりませんが一応添付しておきます〜〜

ではまた~ ꉂ(σ▰˃̶̀ꇴ˂̶́)σ✧


Xではたま〜にする更新のお知らせを行っています

興味ある方はLet'sフォロー★

▼ この記事に興味があったら同じタグから関連記事をのぞいてみてね

Buy Me A Coffee

新着記事を通知したい??


RSSリーダーにatomのリンクを登録すると通知が行くよ🐌

https://herohoro.com/atom

やってみてね(*´ω`*)(*´ω`*)

Twitter Timeline


フォロー大歓迎\(^o^)/