react vs vue vs svelte vs angular
モダンフロントエンドフレームワークの技術的比較
reactvuesvelteangular類似パッケージ:

モダンフロントエンドフレームワークの技術的比較

angularreactsveltevue はいずれも大規模なWebアプリケーションを構築するための主要なフロントエンドフレームワークまたはライブラリです。これらはコンポーネントベースのアーキテクチャを採用し、状態管理、UIレンダリング、開発者体験(DX)の面で独自のアプローチを持っています。angularはTypeScriptを基盤としたフルスタックフレームワークであり、reactは宣言的なUI構築に特化したライブラリ、svelteはコンパイル時に最適化を行うコンパイラ指向のフレームワーク、vueは柔軟性と漸進的な導入を重視したプログレッシブフレームワークです。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
react89,754,150243,876172 kB1,1591ヶ月前MIT
vue10,907,48653,1892.47 MB9851日前MIT
svelte3,822,53986,0992.81 MB98020時間前MIT
angular605,47558,9222.09 MB461-MIT

Angular vs React vs Svelte vs Vue: 実践的な技術比較

フロントエンド開発において、angularreactsveltevueはそれぞれ異なる哲学と技術的アプローチを持ち、プロジェクトの要件やチームのスキルセットに応じて最適な選択肢が変わります。この記事では、実際の開発シーンで直面する典型的な課題を中心に、各フレームワークの実装方法をコード付きで比較します。

🧩 コンポーネントの定義とデータバインディング

angular

angularはTypeScriptクラスとデコレータを使ってコンポーネントを定義します。プロパティバインディング(親→子)とイベントバインディング(子→親)を明示的に分離します。

// angular: hero.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-hero',
  template: `
    <div>{{hero.name}}</div>
    <button (click)="onSelect()">選択</button>
  `
})
export class HeroComponent {
  @Input() hero!: { name: string };
  @Output() selected = new EventEmitter<void>();

  onSelect() {
    this.selected.emit();
  }
}

react

reactは関数コンポーネントとPropsでデータを受け取り、コールバック関数でイベントを親に伝えます。JSX内で直接記述します。

// react: Hero.jsx
function Hero({ hero, onSelect }) {
  return (
    <div>
      {hero.name}
      <button onClick={onSelect}>選択</button>
    </div>
  );
}

svelte

svelte.svelteファイル内にHTML、CSS、JavaScriptを1ファイルで記述します。propsはexport letで定義し、イベントはcreateEventDispatcherを使います。

<!-- svelte: Hero.svelte -->
<script>
  import { createEventDispatcher } from 'svelte';
  export let hero;
  const dispatch = createEventDispatcher();

  function onSelect() {
    dispatch('selected');
  }
</script>

<div>{hero.name}</div>
<button on:click={onSelect}>選択</button>

vue

vueは単一ファイルコンポーネント(SFC)で、<template><script><style>を分離します。propsはdefinePropsで、イベントはdefineEmitsで宣言します。

<!-- vue: Hero.vue -->
<template>
  <div>{{ hero.name }}</div>
  <button @click="onSelect">選択</button>
</template>

<script setup>
const props = defineProps({
  hero: { type: Object, required: true }
});

const emit = defineEmits(['selected']);

function onSelect() {
  emit('selected');
}
</script>

🔄 状態管理:ローカル状態の扱い

angular

angularはクラスのプロパティとして状態を保持し、変更検知はZone.jsによって自動的に行われます。

// angular
@Component({
  template: `<p>カウント: {{ count }}</p>
             <button (click)="increment()">+</button>`
})
export class CounterComponent {
  count = 0;

  increment() {
    this.count++;
  }
}

react

reactuseState Hookでローカル状態を管理します。状態更新は非同期で、再レンダリングをトリガーします。

// react
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <p>カウント: {count}</p>
    <button onClick={() => setCount(count + 1)}>+</button>
  );
}

svelte

svelteは通常の変数として状態を宣言し、代入時に自動的に再レンダリングされます。リアクティブなステートメントには$:を使います。

<!-- svelte -->
<script>
  let count = 0;

  function increment() {
    count += 1;
  }
</script>

<p>カウント: {count}</p>
<button on:click={increment}>+</button>

vue

vuerefまたはreactiveでリアクティブな状態を作成します。テンプレート内では自動的にアンラップされます。

<!-- vue -->
<script setup>
import { ref } from 'vue';

const count = ref(0);

function increment() {
  count.value++;
}
</script>

<template>
  <p>カウント: {{ count }}</p>
  <button @click="increment">+</button>
</template>

🌐 ルーティングの実装

angular

angular@angular/routerを用いて、モジュールレベルでルート設定を定義します。

// angular: app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'user/:id', component: UserComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

react

reactは公式ルーターを持たないため、react-router-domが一般的です。JSX内で直接ルートを定義します。

// react: App.jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './Home';
import User from './User';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/user/:id" element={<User />} />
      </Routes>
    </BrowserRouter>
  );
}

svelte

svelteも公式ルーターを持たず、svelte-spa-routersvelte-navigatorなどのサードパーティ製が使われます。

<!-- svelte: App.svelte -->
<script>
  import { Router, Route } from 'svelte-spa-router';
  import Home from './Home.svelte';
  import User from './User.svelte';
</script>

<Router>
  <Route path="/" component={Home} />
  <Route path="/user/:id" component={User} />
</Router>

vue

vueは公式のvue-routerを提供しており、コンポーネントベースでルートを定義します。

// vue: router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue';

const routes = [
  { path: '/', component: Home },
  { path: '/user/:id', component: () => import('../views/User.vue') }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

⚙️ 開発ツールとCLI

  • angular: @angular/cliが提供するng generateng buildng serveなど、一貫したコマンド体系。AOTコンパイルと厳格なLintが標準。
  • react: 公式CLIはないが、create-react-app(非推奨)やVite、Next.jsなどが主流。設定の自由度が高いが、初期設定に時間がかかる場合も。
  • svelte: svelte-kitが公式推奨のメタフレームワークで、ルーティング、SSR、アセット処理を統合。シンプルな設定で高速な開発サーバーを提供。
  • vue: vue-cli(旧)とcreate-vue(新)があり、Viteベースのプロジェクトを簡単に生成。公式エディタ拡張(Volar)による優れたTypeScriptサポート。

📦 エコシステムと拡張性

  • angular: 公式が提供するHttpClientFormsAnimationsなど、多くの機能が標準で含まれる。RxJSとの統合が深く、複雑な非同期処理に強い。
  • react: エコシステムが最も広大で、状態管理(Redux、Zustand)、UIライブラリ(Material UI、Ant Design)など選択肢が豊富。ただし、選定と統合に判断力が求められる。
  • svelte: 標準ライブラリが小さく、必要に応じて軽量なサードパーティ製を使うスタイル。svelte/storeでシンプルな状態管理が可能。
  • vue: 公式がPinia(状態管理)、Vue RouterVue Test Utilsなどを提供。バランスの取れた公式エコシステムで、学習コストを抑えつつ生産性を高められる。

🧪 テスト戦略

  • angular: Jasmine + Karmaがデフォルト。CLIでテスト環境が自動生成され、依存性注入によるモックが容易。
  • react: Jest + React Testing Libraryが主流。コンポーネントの振る舞いを軽量にテスト可能。
  • svelte: VitestやJestと組み合わせ、@testing-library/svelteでUIテストを実施。コンパイル済みの出力がシンプルなため、テストが高速。
  • vue: Vitest + Vue Test Utilsが推奨。コンポーネントのマウントやPropsの操作が直感的。

💡 結論:プロジェクトに合った選択を

  • 大規模・長期保守・チーム開発angular(一貫性と堅牢性)
  • 柔軟性・エコシステム・人材確保react(自由度とコミュニティ)
  • パフォーマンス・シンプルさ・小規模svelte(ビルド最適化と軽量さ)
  • バランス・学習曲線・漸進的導入vue(柔軟性と公式サポートの両立)

どのフレームワークも成熟しており、正解は「プロジェクトの文脈」にあります。技術的負債を最小限に抑え、チームの生産性を最大化する選択をしましょう。

選び方: react vs vue vs svelte vs angular

  • react:

    reactは最大のエコシステムとコミュニティを持つライブラリで、柔軟性と再利用性を重視するチームに最適です。JSXによる直感的なUI記述、Hooksによる関数型コンポーネントの強化、そして豊富なサードパーティツールとの互換性が特徴です。ただし、状態管理やルーティングなどの機能は公式提供されていないため、プロジェクト要件に応じて追加のライブラリを選定・統合する必要があります。

  • vue:

    vueは、シンプルなAPI設計と柔軟なアーキテクチャにより、小規模プロジェクトから大規模アプリケーションまで幅広く対応できます。オプションAPIとコンポジションAPIの両方をサポートし、開発者の好みやプロジェクトの規模に応じて選択可能です。公式ツール(Vue Router、Piniaなど)が整備されており、バランスの取れたDXを提供しますが、超大規模チームでの採用事例はangularreactに比べて少ない傾向があります。

  • svelte:

    svelteは、ビルド時に仮想DOMを排除し、最小限のJavaScriptコードを生成することで高速な実行性能を実現します。テンプレート構文がHTMLに近く、学習障壁が低く、小〜中規模アプリケーションやパフォーマンスが重要な組み込みUIに適しています。ただし、エコシステムやツールチェーンの成熟度は他のフレームワークに比べてやや劣るため、複雑な要件や長期間の保守を見据えた大規模プロジェクトでは慎重な評価が必要です。

  • angular:

    angularは、大規模チームや長期保守が求められるエンタープライズ向けプロジェクトに適しています。TypeScriptとの深い統合、CLIによる一貫した開発環境、ルーティングやHTTPクライアントなど必要な機能が標準で提供される点が強みです。ただし、学習コストが高く、アーキテクチャへの柔軟性が制限される場合があるため、小規模プロジェクトや迅速なプロトタイピングには向かないことがあります。

react のREADME

react

React is a JavaScript library for creating user interfaces.

The react package contains only the functionality necessary to define React components. It is typically used together with a React renderer like react-dom for the web, or react-native for the native environments.

Note: by default, React will be in development mode. The development version includes extra warnings about common mistakes, whereas the production version includes extra performance optimizations and strips all error messages. Don't forget to use the production build when deploying your application.

Usage

import { useState } from 'react';
import { createRoot } from 'react-dom/client';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </>
  );
}

const root = createRoot(document.getElementById('root'));
root.render(<Counter />);

Documentation

See https://react.dev/

API

See https://react.dev/reference/react