プログラミングマガジン

プログラミングを中心にIT技術をできるだけわかりやすくまとめます。

  • ホーム
  • Next.js
  • 【Next.js】サーバーコンポーネントについて
 
 
     
  • サーバー言語  
    • Python
    • Ruby
    • PHP
    • SQL
  •  
  • インフラ  
       
    • AWS
    •  
    • 基本
    • Git
  • Web
       
    • Web開発
    • JavaScript
    • Vue.js
    • React
  •  
  • 設計  
       
    • 実装設計
    • DB設計
  • 問い合わせ
  

【Next.js】サーバーコンポーネントについて

09.02

  • miyabisan2
  • コメントを書く

この記事は4分で読めます

サーバーコンポーネントの特徴

サーバーでレンダリングされるのでjsはクライアントに送られない。

実装したJSのソースだったりとか、利用しているnpmパッケージなどすべてクライアントに送られません。あくまでサーバーでJSを実行した後の静的なHTMLなどだけが送付されることになります。

サーバーコンポーネントのメリット

サーバーでしか扱えないリソースにアクセスできる。

ファイルシステムだったり、データベースだったり。

ネットワークのレイテンシ(遅延)が小さくなる。

クライアントより性能がよいサーバー上で別サーバーにやり取りしたりするので、性能がまちまちなクライアントの端末でいろんなところにやり取りするよりも遅延が少なくなります。

環境変数を完全にシークレットにできる。

通常のReactやNext.jsの場合環境変数を使いたい場合は「REACT_APP」や「NEXT_APP」などの接頭辞を使ってアクセスしていたと思うのですがそれは完全にシークレットにすることはできませんでした。

サーバーコンポーネントであれば特にそれらの接頭辞がなくてもコンポーネント側から環境変数にアクセスできるので環境変数がクライアント側から完全シークレットになります。

環境変数にはAPIキーなどの完全に隠蔽したい情報も含まれていると思いますので、一つのメリットになります。

コンポーネントレベルで非同期処理構文(async、await)が使える。

従来のReactであれば非同期処理を記述する場合は、useEffectを使ったりとか、React Queryを使ったりとか、SWRを使ったりだとかサードパーティのライブラリを使ってデータフェッチするしかありませんでした。

バンドルサイズを低減できる。

必要な処理はサーバー側でやってしまうのでフロントエンドで必要なパッケージの数が減ります。ということで従来のNext.jsよりもバンドルサイズが減ります。

サーバーコンポーネントのデメリット

Browser API、React Hookなどは使えない。

例えば、localstrageだったりとか、windowだったりとかブラウザ特有のAPIは使えないです。ReactのuseEffectやuseStateなども使えないです。

Event listenerは利用できない。

例えば、onClickなどですね。なのでフォーム画面とかJSでアクションを実行させたい画面の場合はサーバーコンポーネントは使えないです。あくまで表示用です。

サーバーコンポーネントとクライアントコンポーネントの使い分け

用途サーバーコンポーネントクライアントコンポーネント
データフェッチを行うコンポーネント〇
シークレットにしなければならないキーがある場合〇
npmパッケージが大きいものを使う場合〇
イベントリスナーがある場合〇
React Hooksを使う場合〇
ブラウザー APIがある場合〇

実装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
async function fetchUsers() {
  const res = await fetch(リクエストURL)  if (!res.ok) {
    throw new Error('Failed to fetch data in server')
  }
  const users = await res.json()
  return users
}
 
export default async function UsersList() {
  const notes = await fetchUsers()
  return (
    <div>
      <ul className="m-3">
        {users.map((user) => (
          <li key={user.id}>
            <p> {user.name}</p>
          </li>
        ))}
      </ul>
    </div>
  )
}

featch

JavaScriptのfetch APIです。Next.jsでキャッシュ機能などの拡張がされているのでフェッチする場合はこれを使うようにしましょう。(axiosやrequestは使わないこと)

ちなみに、キャッシュオプションを指定しない場合のデフォルトは「force-cache」になっていて、従来のNext.jsでいうところのstaticなページに対応したものになります。(getStaticProps)

cacheオプションの種類

オプション使用例説明
force-cachefetch(URL,{cache: 'force-cache'})デフォルト値、従来のgetStaticPropsと同じ挙動
no-storefetch(URL,{cache: 'no-store'})レンダリングをダイナミック(getServerSideProps)のようにしたい場合
revalidatefetch(URL,{next: {revalidate:10}})ISRのようにしたい場合はこれを使う。数値は秒数です。内部的に指定した秒数経過したらHTMLを再生成します。

res.json()

これをすることでシリアライズをして文字列化しています。こうすることでJavaScript内でオブジェクト形式で値を扱えるようにできる上、軽量化できるので基本的にはfetchした場合はjsonメソッドを使用します。

起動方法

サーバーコンポーネントはnpm run devでは起動できません。

npm run buildでビルドした後に、npm startで起動して動作確認を行いましょう。

注意点

ビルド時に生成されたHTMLがCDNにキャッシュされるのでサーバー側のデータが変更されてもその変更が画面に反映されません。ビルド時のデータになっている。(staticレンダリング)

staticレンダリングされたhtmlの場所(cacheオプションにforce-cacheを指定した場合)

1
.next/server/app/index.html

サーバーコンポーネント←→クライアントコンポーネントを相互に呼び出せるか。

「サーバーコンポーネント」から「クライアントコンポーネント」の呼び出しは可能です。

ただし、逆に「クライアントコンポーネント」から「サーバーコンポーネント」を呼び出すということはできません。

例外

以下のようにしてサーバーコンポーネント内でクライアントコンポーネントを呼び出してさらにその中にサーバーコンポーネントを入れ込むというchildrenとしてであれば定義することは可能です。

1
2
3
4
5
6
function サーバーコンポーネント() {
return (
<ClientComponent>
  <ServerComponent />
</ClientComponent>
);}

理由としては、上記の形を見た際にReact側がサーバーコンポーネントだけを事前にビルドしておかないといけないと判断できるためです。

ページをリロードせずにサーバーコンポーネントでフェッチする内容を最新化するには?

これはクライアントコンポーネントだけで使えるrouter.refreshという機能を使えば実現できます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'use client'
import { useRouter } from 'next/navigation'
 
export default function AAA() {
  const router = useRouter()
  return (
    <button
 
      onClick={() => {
        router.refresh()
      }}
    >
      Refresh
    </button>
  )
}

上記のように実装しサーバーコンポーネントの中にこのクライアントコンポーネントを組み込んであげたうえでボタンを押すことでサーバーコンポーネントの内容をページリロードすることなく最新化することが可能です。

なお、router.refreshは「クライアントコンポーネントのuseStateの内容は初期化されない」という特徴があります。(再レンダリングは普通に行われます。)あくまでサーバーコンポーネントの初期化だけ行う構文になります。

認証機能などを取り入れる際の設計上の注意点

例えば、認証基盤とかでアクセストークンをサーバーコンポーネントとクライアントコンポーネントで同じものを使っていることが要件などがあるかと思います。

そのばあい、同じトークンを使うようにしないといけないのでクライアントコンポーネント側で都度チェックするようにして、もしトークンが異なった場合はrouter.refreshなどでサーバーコンポーネントを再レンダリングさせてあげる必要があります。(でないとサーバーコンポーネントとクライアントコンポーネントで別ユーザーの情報が取得されてしまうということになってしまうため。)

スポンサーリンク
  • 2023 09.02
  • miyabisan2
  • コメントを書く
  • Next.js
  • Tweets Twitter
  • このエントリーをはてなブックマークに追加
  • LINEで送る

関連記事

  1. 2022 05.12

    【React、Next.js】「環境変数」の組み込み方について

  2. 2021 05.09

    【Next.js】「getStaticProps」、「Dynamic routes」について

  3. 2022 01.20

    【Next.js】「エラーハンドリング」

  4. 2023 09.16

    【Next.js】デプロイ先検討

  5. 2021 05.16

    【Next.js】Next.jsの基本コンポーネント、ページ遷移、ページのテスト

  6. 2021 05.16

    【Next.js】「CSR(UseSWR)」について

  • コメント ( 0 )
  • トラックバック ( 0 )
  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

返信をキャンセルする。

【Next.js】App Routerについて

【React】カスタムフックについて

RETURN TOP

著者プロフィール

エンジニア歴10年で過去に業務系、Webデザイン、インフラ系なども経験あります。現在はWeb系でフロントエンド開発中心です。

詳細なプロフィールはこちら

スポンサーリンク

カテゴリー

  • Android
  • AngularJS
  • API
  • AWS
  • C++
  • CSS
  • cursor
  • C言語
  • DDD
  • DevOps
  • Django
  • Docker
  • Figma
  • Git
  • GitLab
  • GraphQL
  • gRPC
  • Hasura
  • Java
  • JavaScript
  • Kubernetes
  • Laravel
  • linux
  • MySQL
  • Next.js
  • nginx
  • Node.js
  • NoSQL
  • Nuxt.js
  • Oracle
  • PHP
  • Python
  • React
  • Redux
  • Rspec
  • Ruby
  • Ruby on Rails
  • Sass
  • Spring Framework
  • SQL
  • TypeScript
  • Unity
  • Vue.js
  • Webサービス開発
  • Webデザイン
  • Web技術
  • インフラ
  • オブジェクト指向
  • システム開発
  • セキュリティ
  • その他
  • データベース
  • デザインパターン
  • テスト
  • ネットワーク
  • プログラミング全般
  • マイクロサービス
  • マイクロソフト系技術
  • マルチメディア
  • リファクタリング
  • 副業
  • 未分類
  • 業務知識
  • 生成AI
  • 設計
  • 関数型言語
RETURN TOP

Copyright ©  プログラミングマガジン | プライバシーポリシー