新規プロジェクトにおけるフロントエンドフレームワークの選定

はじめに

アソビュー株式会社の髙木です。

2023年に新卒でアソビューに入社し、現在はフロントエンドメインで新規プロジェクトの開発を行っています。
今回は新規プロジェクトを開発するうえでおこなった、フロントエンド周りのフレームワーク選定についてお話できればと思います。 技術的な話というより、「なぜ選んだのか」という点にフォーカスした話になっています。

背景

今年の3月から部署異動し、新規事業の開発を行うことになりました。
いきなり話はそれますが、実は入社してから携わるプロダクトすべてが新規事業で、貴重な経験をさせてもらっていると日々感じています。頑張るぞー!
前部署は新規事業とはいえ、私がジョインしたタイミングではすでに技術選定も終わっていましたが、今回は全くのゼロからの開発なので、まず自分たちで最初に技術選定をする必要があり、私はフロントエンド周りのフレームワーク選定を担当しました。

要件

選定を行ううえで以下のような要件がありました。

ビジネス的観点

今回の新規プロジェクトでは、SEOの観点からマーケティング的なコンテンツ(例えば記事コンテンツなど)を多く作成し、それらを部品として様々な画面に差し込むことを想定しています。
というのも、今回のプロジェクトは新規であり、競合他社と比較して後発のサービスで知名度が低いため、オーガニックサーチ経由でのセッションを増やすことが重要になってきます。
ビジネス要件をクリアするために、技術的に以下の点が重要です。
差し込むコンテンツが多いため、如何にパフォーマンスを維持できるか

選定

前提として、すでに社内でNext.jsの採用事例があり、ある程度ノウハウが溜まっているため、Next.jsを用いることは決めていました。 ただ、Pages Routerを用いるのか、それともApp Routerを用いるのかは決まっていませんでしたが、App Routerが要件に合致する点が多いため採用を決めました。
まずは以下に要件に対するApp RouterのGOODな機能を簡単に説明します。

React Server Components(以下、RSC)とRequest Memoization

まず、RSCとはサーバーでコンポーネントの生成を行い、そのコンポーネントデータをクライアントで取得、レンダリングするという技術です。
ウェブページの完全なHTMLコンテンツがサーバーから生成され、クライアントに送信されることで、検索エンジンのクローラーがページを訪れたとき、完全なコンテンツをすぐにインデックスしやすくなりSEOに有利に働きます。
Request Memoizationとは、ルートのレンダリングを行う際にリクエストをキャッシュするもので、これにより、コンポーネントツリー内に同じリクエストが複数回あった場合に最初の一回のみ実行されるものです。

これら2つの機能があることで、共通のAPIフェッチを必要とするコンポーネントを複数の場所で使用しても、サーバーサイドでのフェッチ処理を簡単に記述できます。また、リクエストが重複しないように効率的に処理してくれるため、Pages Routerを使ったSSRよりも簡単にSSRを実現できるようになります。

ストリーミング

ページのHTMLを小さなチャンクに分割し、準備が整ったチャンクからレスポンスを開始するという機能です。 でデータ取得などの非同期アクションを実行するコンポーネントをラップし、実行中はフォールバックUIを表示し、アクションが完了したらコンポーネントを入れ替えることが可能です。
また、ストリーミングは、Time To First Byte (TTFB)や First Contentful Paint (FCP) を削減できるため、長いデータリクエストがページのレンダリングをブロックするのを防ぎたい場合に特に有益です。
これがあることで、ウォーターフォール問題(全てのリクエストが解決するまでデータの表示がブロックされ、ユーザーをローディング画面で待機させてしまうこと)を回避し、優れたUXをユーザーに提供できます。

要件に対してどのような効果があるのか

今回の要件に対して上記2つの機能がどう働くかというと、
まず今回のプロジェクトでは、記事などのマーケティング的なコンテンツが様々なコンポーネントとして画面に差し込まれる想定です。
例えば今後SEOの観点で、ニュースサイトとAPI連携をしそれをコンポーネントで差し込まれる場合を想定します。何度もコンポーネントツリー内で同じAPIを呼んでいては、パフォーマンスの悪化になってしまいますが、RSCとRequest Memoizationを用いることでSSRを実現でき、何回レンダリングしようがAPIを叩かずに済むのでパフォーマンスやAPIサーバーに余計な負荷をかけなくて良さそうです。

また差し込みコンテンツが多いと全画面表示までロードに時間がかかりユーザーを待たせてしまい、離脱を招く可能性があります。
ただ、ストリーミング機能を利用することで、ウォーターフォール問題を回避し表示パフォーマンスを維持することができ、無駄にユーザーを待たせずに、離脱も防げそうです。
記事コンテンツを差し込む場合は、以下のようなコードになる想定です。

import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'
 
export default function Item() {
  return (
    <section>
      <h1>おすすめ商品</h1>
      ・・・・
      <Suspense fallback={<p>Loading...</p>}>
        <Article />
      </Suspense>
    </section>
  )
}

記事コンポーネントをSuspenseで囲み、Articleの箇所はレスポンスが返ってくるまで「Loading...」を出しておけば、その他のh1を含めた部分は先行して表示することができるので良いですね。

上記の機能は要件に対して有利に働いてくれると感じたため、App Routerを採択しました。

まとめ

今回は私がどのように新規事業開発のフレームワークを選定したのかについて紹介させていただきました。新規プロジェクトにおいて、最適な技術選定を行うことは非常に重要です。特に、今回のようにゼロからの開発では、初期の選定がプロジェクト全体の成功に大きく影響を与えるため、慎重に検討する必要があります。

このブログを通じて、私たちがどのようにフロントエンドフレームワークの選定を行ったのか、そのプロセスや考え方を共有することで、他の開発者やチームにとっても参考になれば幸いです。皆さんのチームがどのような観点で技術選定を行っているのか、ぜひコメントで教えてください。お互いに学び合い、より良いプロダクトを作り上げていきましょう。

最後に

アソビューではより良いプロダクトを世の中に届けられるよう共に挑戦していくエンジニアを募集しています。
カジュアル面談もやっておりますので、お気軽にエントリーください! お待ちしております。

www.asoview.co.jp

参考記事

Rendering: Server-side Rendering (SSR) | Next.js

Server Components | Next.js 公式ドキュメント 日本語翻訳プロジェクト

Reactのさまざまなデータフェッチ方法を比較して理解して正しく使用する - SSR + App Router Cache編

Routing: Loading UI and Streaming | Next.js