⚖️

【コードベースで比較する】React VS Next.js

2023/10/12に公開
4

はじめに

今回の記事では、類似しているWeb技術であるReactとNext.jsをコードベースで比較する。

対象とする読者

  • ReactとNext.jsの違いがわからない
  • 技術選定で、ReactとNext.jsのどちらにしようか悩んでいる

Reactとは

React(リアクト)は、Meta(旧Facebook)が開発しオープンソースとして公開しているJavaScriptライブラリで、ユーザインターフェースの構築に特化している。

Reactの特徴は以下の通りだ。

  • コンポーネントベース:Reactの中核となる考え方は、UIを再利用可能なコンポーネントに分割することにある。これにより、大規模なアプリケーションでも管理を簡単にできる。
  • 仮想DOM:Reactは仮想DOMを使ってページの更新やレンダリングを行う。
  • 宣言的UI:Reactは宣言的UIを採用しており、アプリケーションの各状態に対してUIをコード単位で記述する。これによりコードが読みやすくなり、デバッグが簡単になる。
  • 豊富なエコシステム:Reactは数多くの情報、ライブラリやツールが存在する。そのため、何らかの問題に遭遇したときにGoogle検索等で問題を解決しやすい。Reactが応用されている技術の代表例として、ReduxやReact Routerが挙げられる。
  • 柔軟性:ReactはUIのレンダリングに特化しているので、他のライブラリやフレームワークと組み合わせて使える。

Reactの強み

Reactの強みの一つとして、以下の2点が挙げられる。

  • コンポーネントベースのアーキテクチャ
  • 仮想DOMを組み合わせたUIのレンダリング

それぞれ順番に解説する。

コンポーネントベースのアーキテクチャ

ReactではUIを再利用可能なコンポーネントに分割する。これにより、コードを再利用できる。

仮想DOM

Reactでは実際のDOMの変更を最小限にするために仮想DOMが使われる。これを使うことで、高速にUIを更新できる。

下記に示す差分計算と更新のプロセスを再結合と呼ぶ。

  1. ユーザのアクション等があると、新しく仮想DOMが作られる
  2. 新しい仮想DOMと前の仮想DOMが比較され、差分が計算される
  3. この差分が実際のDOMに適用される

以下に示すコードは、仮想DOMを用いた簡単なカウンターアプリのReactコンポーネントである。

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  increment = () => {
    this.setState(prevState => ({ count: prevState.count + 1 }));
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

Reactが解決できる問題

複雑なUIの状態管理

Reactではコンポーネントの状態(state)を使って、UIの状態を局所的に管理する。

// トグル(Toggle)を表現したReactコンポーネント
class ToggleButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isToggled: false };
  }

  toggle = () => {
    this.setState(prevState => ({ isToggled: !prevState.isToggled }));
  }

  render() {
    return (
      <button onClick={this.toggle}>
        {this.state.isToggled ? 'ON' : 'OFF'}
      </button>
    );
  }
}

似たようなUIの部品を生成すること

Reactでは再利用可能なコンポーネントを使うことで、似たようなUIを何度も作る必要がなくなる。

function WelcomeBanner(props) {
  return <h1>Welcome, {props.name}!</h1>;
}

// このコンポーネントを様々な場所で再利用
<WelcomeBanner name="Alice" />
<WelcomeBanner name="Bob" />

DOMの更新

前述の通り、Reactでは仮想DOMへの変更を最小限にできる。

class List extends React.Component {
  // ... (中略)

  render() {
    return (
      <ul>
        {this.props.items.map(item => <li key={item.id}>{item.name}</li>)}
      </ul>
    );
  }
}

// このコンポーネントでは、itemsの配列が変更された場合でも、変更があった<li>のみが更新される。

UIの状態と表示が一致しないこと

Reactでは宣言的なUIを提供し、アプリの状態に応じて表示するべきUIを明示的に記述する。

function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  if (props.isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

// ユーザーのログイン状態に基づいて、適切なメッセージが表示される

Next.jsとは

Next.jsはReactのフレームワークの一つで、SSR(サーバサイドレンダリング)やSSG(静的サイト生成)、APIルートの機能を備えている。Reactを基盤としたアプリケーションの開発を得意とする。Vercelによって開発された。

Next.jsの主な特徴は以下の通りだ。

  • SSR(Server Side Rendering):初回のページロードの際にサーバサイドでHTMLを生成できる。これにより、SEOの改善やページロード速度の高速化が期待される。
  • SSG(Static Site Generator)getStaticPropsgetStaticPathsというようなAPIを用いてビルド時に静的なHTMLを生成できる。
  • APIルートpages/apiディレクトリ内にファイルを配置することで、簡単にAPIエンドポイントを作れる。
  • ルーティングの自動化pagesディレクトリ内のファイル構造で、自動的にルーティングが行われる。
  • ホットリロード:開発中にソースコードを変更すると、自動的にブラウザが更新される。
  • TypeScriptサポート:デフォルトでTypeScriptをサポートしている。型安全なコードを書いたり、開発の生産性を高めたりできる。
  • 拡張性が高い:Next.jsは多種多様なプラグインやミドルウェアをサポートしており、カスタマイズや拡張が簡単だ。

Next.jsの強み

ルーティングの自動化

pagesディレクトリ内にファイルを追加するだけで、新しくルートが自動的に作られる。

// pages/about.js
function About() {
  return <div>About us</div>;
}

export default About;

上述のコードは/aboutのURLでアクセスできるページを作れる。

SSG

getStaticPropsを使うことで、ビルド時にページのデータを取得して静的に生成できる。

// pages/posts/[id].js
function Post({ post }) {
  return <div>{post.title}</div>;
}

export async function getStaticProps(context) {
  const { id } = context.params;
  const post = await fetchPostData(id); // 例: 外部APIからのデータ取得
  return { props: { post } };
}

export default Post;

SSR

getServerSidePropsで、リクエストごとにデータを取得してページをサーバサイドでレンダリングできる。

// pages/users/[id].js
function User({ user }) {
  return <div>{user.name}</div>;
}

export async function getServerSideProps(context) {
  const { id } = context.params;
  const user = await fetchUserData(id); // 例: データベースからのデータ取得
  return { props: { user } };
}

export default User;

APIルートの作成

pages/apiディレクトリ内にファイルを追加することで、APIエンドポイントを簡単に作れる。

// pages/api/hello.js
export default (req, res) => {
  res.status(200).json({ text: 'Hello' });
};

画像の最適化

Next.jsのImageコンポーネントで画像の最適化等を簡単に実現できる

import Image from 'next/image';

function MyComponent() {
  return <Image src="/path/to/image.jpg" width={500} height={500} alt="Description" />;
}

Next.jsが解決できる問題

SEOの問題

Next.jsでは、SSRを用いてクローラが解釈しやすいHTMLページを提供できる。

// pages/product/[id].js
function Product({ product }) {
  return <div>{product.name}</div>;
}

export async function getServerSideProps(context) {
  const product = await fetchProduct(context.params.id);
  return { props: { product } };
}

export default Product;

ルーティングの煩雑さ

Next.jsではファイルベースのルーティングを提供し、pagesディレクトリの構造で自動でルートを生成する。

// pages/about.js
function About() {
  return <div>About us</div>;
}

export default About;
// これは自動的に /about ルートにマッピングされる。

フロントエンドとバックエンドのAPI統合

Next.jsでは、pages/apiディレクトリを使ってAPIルートを簡単に作る。

// pages/api/user.js
export default (req, res) => {
  res.status(200).json({ name: 'John Doe' });
};

向いている人

React

Reactが向いている人は以下のとおりだ。

  • 基本から学びたい人:ReactはUIの構築に特化したライブラリだ。Reactの基礎概念(propsstate)を学ぶことで、フロントエンド開発の基本を学べる。
  • カスタマイズ性を求める人:Reactは柔軟性が高く、ルーティングや状態管理等の方法を自由に選択できる。
  • 既存のプロジェクトに統合したい人:Reactは他のフレームワークやライブラリとの統合が簡単なので、既存のプロジェクトに追加できる。

Next.js

前提として、Next.jsはReactの技術を応用しているのでReactに関する前提知識を学ぶ必要がある。

向いている人は以下の通りだ。

  • SEOやパフォーマンスを重視する人:Next.jsに搭載されているSSRやSSGは、SEO最適化や初回のページロード
  • バックエンドとの統合を検討する人:Next.jsのAPIルート機能を使うことで、フロントエンドとバックエンドを同じプロジェクト内で管理できる。
  • TypeScriptをフロントエンドで活用したい人:Next.jsはデフォルトでTypeScriptをサポートしているので、フロントエンドをTypeScriptで書きたい人には最適な技術だ。

おわりに

ReactとNext.jsのそれぞれの特徴を表にまとめると以下のようになる。

React Next.js
概要 JavaScriptで開発されたUIライブラリ Reactの技術を応用したフロントエンドフレームワーク
会社 Meta(旧Facebook) Vercel
特徴 仮想DOM、宣言的UI、豊富なエコシステム SSR・SSG対応、自動ルーティング
強み コンポーネント、宣言的UI SEO最適化、TypeScriptサポート

今回の記事が、読者のフロントエンドの技術選定で参考になれば幸いである。

余談

SSRやSSG等がわからないなら、以下の記事を確認しておこう。今後Next.jsを触る上で重要な概念になる。

https://zenn.dev/rinda_1994/articles/e6d8e3150b312d

https://zenn.dev/bitarts/articles/37260ddb28ae5d

https://qiita.com/amakawa_/items/e7d0720e1ab8632769bf

参考サイト一覧

https://react.dev/

https://nextjs.org/docs

https://www.freecodecamp.org/news/next-vs-react/

https://www.toptal.com/next-js/next-js-vs-react

https://blog.logrocket.com/next-js-vs-react-developer-experience/

GitHubで編集を提案

Discussion

Kenji SaitoKenji Saito

React.js 単体と Next.js の機能の違いはこの記事にある通りだと思います。(ファイルシステムベースのルーティングが煩雑かどうかは議論が分かれそうですが。。。煩雑なら、後発の SvelteKit とかには採用されないはずだけど、むしろ採用されているし)

ちなみに、参考サイトの1つ目の React.js の公式ドキュメントは https://react.dev が最新です。

class コンポーネントは非推奨のはずで、状態管理は React hooks を使うことになるので、サンプルコードが大きく変わるかと。
そして、フレームワークなしで新規プロジェクトを作成するのも非推奨となっていて、初学者の方がこの記事を読んだときに最新の React.js のドキュメントとの乖離が大きすぎて混乱してしまうのではないでしょうか?

vincent.maverickvincent.maverick

この手のVS攻勢には辟易とする。
NextJS は React ベースで開発されたフレームワークであって単品では何もできない。にも関わらず違い?
同一線上では成立しないのだから対立させる構造そのものが間違いだ。
NextJS は React 側も推挙している React のラッパーフレームワークだ。戦わせてはいけない。

ChieeeenoChieeeeno

React=ライブラリ
Next.js=フレームワーク
だと思うので、比較対象がそもそも違うような。。。

Next.jsの向いている人の箇所で TypeScriptをフロントエンドで活用したい人 と書かれてましたけど、ReactでもTypeScriptのスターターテンプレート用意されており、バリバリTypeScriptでかけますので、Next.jsの長所として推すほどのものでもないのかなと。

あと、Reactコンポーネントは現在ではClass Componentではほとんど書くことはないと思いますので、サンプルコードの書き方は間違ってはいませんが、推奨されているコードではありません。

王文雄王文雄

自分の基準はstaticなページを生成するときはNext.js、dynamicなものはReactですね。