react vs preact vs vue vs lit vs svelte vs backbone vs angular vs inferno
主要フロントエンド UI ライブラリのアーキテクチャと選択基準
reactpreactvuelitsveltebackboneangularinferno類似パッケージ:

主要フロントエンド UI ライブラリのアーキテクチャと選択基準

angularbackboneinfernolitpreactreactsveltevue は、すべてウェブユーザーインターフェースを構築するための JavaScript ライブラリまたはフレームワークです。これらはコンポーネントベースのアーキテクチャを採用しているものが多いですが、レンダリング方式(仮想 DOM、コンパイラ、Web コンポーネント)、状態管理のアプローチ、および学習曲線に大きな違いがあります。reactvue はエコシステムが広く、angular は包括的なフレームワークを提供します。svelte はコンパイル時に最適化を行い、lit は標準の Web コンポーネントに焦点を当てています。preactinfernoreact と互換性がありつつ軽量化を図っており、backbone はレガシーな MVC パターンを提供しますが、現在は新しいプロジェクトでの使用は推奨されません。

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

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
react51,855,099244,168172 kB1,1822ヶ月前MIT
preact6,744,05238,5031.55 MB14813日前MIT
vue4,942,92753,3012.47 MB99914日前MIT
lit2,268,46621,366106 kB6593ヶ月前BSD-3-Clause
svelte2,025,38086,1462.82 MB9686時間前MIT
backbone539,94328,100190 kB621年前MIT
angular058,8982.09 MB461-MIT
inferno016,412598 kB402ヶ月前MIT

主要フロントエンド UI ライブラリの比較:アーキテクチャ、パフォーマンス、開発体験

angularbackboneinfernolitpreactreactsveltevue は、それぞれ異なる哲学と技術的アプローチを持っており、プロジェクトの要件によって最適な選択は変わります。単に「どれが一番か」ではなく、それぞれの強みとトレードオフを理解することが重要です。ここでは、実際の開発現場で直面する技術的な違いを、コード例を交えて解説します。

🏗️ コンポーネントの定義方法:構文と構造

各ライブラリは、コンポーネントをどう定義するかという点で大きく異なります。これは開発者の日常的なコーディング体験に直結します。

angular は TypeScript を前提としたクラスベースの構造を採用しています。デコレーターを使ってメタデータを定義します。

// angular: Standalone Component
import { Component } from '@angular/core';

@Component({
  selector: 'app-counter',
  standalone: true,
  template: `<button (click)="count = count + 1">{{ count }}</button>`
})
export class CounterComponent {
  count = 0;
}

backbone は現代のようなコンポーネントシステムではなく、View と Model を分離する MVC パターンです。DOM 操作を手動で行う必要があります。

// backbone: View Definition
const CounterView = Backbone.View.extend({
  events: { 'click button': 'increment' },
  initialize: function() { this.count = 0; },
  increment: function() {
    this.count++;
    this.render();
  },
  render: function() {
    this.$el.html(`<button>${this.count}</button>`);
    return this;
  }
});

inferno は React と非常に似た JSX 構文を使用しますが、パフォーマンス最適化のための独自のコンパイルオプションを持つことがあります。

// inferno: Functional Component
import { createElement } from 'inferno';

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

lit は Web 標準のクラス構文を拡張し、テンプレートリテラルを使って HTML を記述します。

// lit: LitElement Class
import { LitElement, html } from 'lit';

class Counter extends LitElement {
  static properties = { count: { type: Number } };
  count = 0;

  render() {
    return html`<button @click=${() => this.count++}>${this.count}</button>`;
  }
}

preact は React とほぼ同じ API を提供するため、JSX を使って関数コンポーネントを定義します。

// preact: Functional Component
import { useState } from 'preact/hooks';

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

react も JSX を使用した関数コンポーネントが標準です。フックを使って状態を管理します。

// react: Functional Component
import { useState } from 'react';

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

svelte はフレームワーク固有の構文を持ち、HTML、CSS、JS を単一ファイルに記述します。コンパイラが反応性を処理します。

<!-- svelte: Single File Component -->
<script>
  let count = 0;
</script>

<button on:click={() => count++}>
  {count}
</button>

vue はテンプレート構文とスクリプトを組み合わせます。Vue 3 では <script setup> が推奨されます。

<!-- vue: Single File Component -->
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

🔄 状態管理と再レンダリング:どう更新されるか

状態が変化したときに UI がどう更新されるかは、パフォーマンスとデバッグのしやすさに影響します。

angular は変更検知(Change Detection)を使用します。ゾーンの内外でイベントが発生すると、ツリー全体をチェックして更新が必要な箇所を探します。

// angular: Change Detection Trigger
// Template binding automatically triggers check
// Manual trigger if needed:
constructor(private cdr: ChangeDetectorRef) {}
update() {
  this.value = 10;
  this.cdr.detectChanges();
}

backbone は手動レンダリングが基本です。モデルの変更をリッスンして、明示的に render を呼び出す必要があります。

// backbone: Manual Render on Change
initialize: function() {
  this.model.on('change', this.render, this);
}

inferno は仮想 DOM を使用しますが、React よりも細かく最適化された差分アルゴリズムを持っています。フラグを使用して更新タイプを高速判定します。

// inferno: Optimized VDOM
// Internally uses flags to skip unnecessary checks
// Developer writes standard JSX, compiler optimizes

lit はプロパティの変更を検知し、非同期にバッチ処理して DOM を更新します。Shadow DOM を使用するのが一般的です。

// lit: Reactive Properties
static properties = { count: { type: Number } };
// Setting this.count triggers update() automatically

preact は仮想 DOM を使用しますが、サイズを小さくするために一部の最適化(例えば、一部のライフサイクルイベント)を省略しています。

// preact: VDOM Diffing
// Similar to React but lighter weight diffing
setState({ count: 1 }); // Triggers re-render

react は仮想 DOM を使用し、状態更新時にコンポーネントツリーの差分を計算して最小限の DOM 操作を行います。

// react: State Update
setCount(1); // Schedules re-render, batches updates

svelte は仮想 DOM を使いません。コンパイル時に状態の変更箇所を特定し、変更があったときだけ直接 DOM を更新するコードを生成します。

<!-- svelte: Compiled Reactivity -->
<!-- Compiler injects code like: $$invalidate('count', count = 1) -->
<script> let count = 0; </script>

vue はプロキシオブジェクトを使用して状態の変更を追跡し、依存関係に基づいてコンポーネントを更新します。

// vue: Reactivity System
const count = ref(0);
count.value++; // Triggers dependent effects

📦 エコシステムと拡張性:ライブラリとツール

プロジェクトが大きくなると、ライブラリ単体以外のサポートが重要になります。

angular は CLI、ルーティング、フォーム処理、HTTP クライアントなどが公式に含まれています。サードパーティに依存しない完結した環境です。

// angular: Built-in HTTP Client
import { HttpClient } from '@angular/common/http';
constructor(private http: HttpClient) {}

backbone は最小限の機能しか提供しないため、ルーティングやテンプレートには別のライブラリ(Marionette など)が必要でした。現在はエコシステムが縮小しています。

// backbone: External Router Required
const Router = Backbone.Router.extend({ ... });

inferno は React のエコシステムの一部を利用できますが、すべてのライブラリが完全に compatible ではない場合があります。

// inferno: Compatibility Layer
import { compat } from 'inferno-compat';

lit は Web 標準に準拠しているため、どのフレームワークでも使用可能です。専用エコシステムは小さいですが、安定しています。

// lit: Framework Agnostic
customElements.define('my-counter', Counter);

preact は React 用のライブラリの多くをエイリアス経由で使用できます。preact/compat がこれを可能にします。

// preact: Using React Libraries
import { render } from 'preact/compat';

react は世界最大級のサードパーティエコシステムを持ち、あらゆる要件に対応するライブラリが存在します。

// react: Vast Ecosystem
import { motion } from 'framer-motion';

svelte はエコシステムが急速に成長していますが、React に比べるとライブラリの数は少ないです。しかし、統合が簡単なことが多いです。

<!-- svelte: Store Integration -->
<script> import { writable } from 'svelte/store'; </script>

vue は公式のルーティングや状態管理(Pinia/Vuex)が整備されており、React よりも統合がスムーズです。

// vue: Official Router
import { createRouter } from 'vue-router';

⚠️ レガシーとメンテナンス:Backbone の位置づけ

backbone は 2010 年代初頭に人気を博しましたが、現在はメンテナンスモードに入っています。新しいプロジェクトで採用するべきではありません。

  • 非推奨の理由: 現代のコンポーネント思考、双方向バインディング、仮想 DOM などの機能が欠けています。
  • 代替案: 軽量さを求めるなら preactlit、包括的な機能を求めるなら vueangular が適しています。
// backbone: Legacy Pattern
// Avoid for new projects
var MyView = Backbone.View.extend({ ... });

🤝 共通点:現代のフロントエンド開発

これら 8 つのパッケージには、いくつかの共通する目標とアプローチがあります。

1. コンポーネントベースの思考(Backbone を除く)

  • ほとんどのライブラリは UI を独立した部品に分割することを推奨します。
  • 再利用性と保守性を高めます。
// Common Concept: Component Reuse
<Header /> <Main /> <Footer />

2. 宣言的 UI

  • 状態が変われば UI が自動的に更新されることを目指しています(Backbone は命令的)。
  • 開発者は「どう更新するか」より「どうあるべきか」を記述します。
// Common Concept: Declarative State
// UI = f(state)

3. JavaScript エコシステムとの統合

  • npm、webpack、vite などのモダンなツールチェーンと連携します。
  • TypeScript のサポートも主流です。
// Common Concept: TypeScript Support
interface Props { count: number; }

📊 比較サマリー

特徴angularreactvuesveltelitpreactinfernobackbone
レンダリング変更検知仮想 DOM仮想 DOMコンパイラWeb Comp仮想 DOM仮想 DOM手動
言語TypeScriptJSXTemplateHTML/JSJS ClassJSXJSXJS
学習曲線高い低い低い低い
サイズ極小
現状aktifaktifaktifaktifaktifaktifニッチレガシー

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

angular は、大規模で長期にわたるプロジェクトにおいて、厳格な構造と包括的な機能を提供します。チームの統一性を保つのに役立ちます。

react は、柔軟性とエコシステムの豊かさを求める場合に最適です。あらゆる課題に対して解決策が見つかりやすいです。

vue は、使いやすさと機能性のバランスが取れています。段階的な導入が可能で、チームの習熟度に合わせられます。

svelte は、パフォーマンスと開発体験の両方を重視する場合に素晴らしい選択肢です。コンパイラによる最適化が特徴です。

lit は、フレームワークに依存しないコンポーネントを作成したい場合に最適です。将来の標準技術に近いです。

preactinferno は、React の知識を活かしながら、より軽量な実行環境を必要とする場合に検討してください。

backbone は、過去の資産を維持する場合を除き、新しい選択としては考慮から外すべきです。

最終的には、チームのスキルセット、プロジェクトの規模、そして長期的なメンテナンス計画を考慮して決定することが重要です。技術的な違いを理解していれば、どのツールを選んでも価値のあるアプリケーションを構築できるでしょう。

選び方: react vs preact vs vue vs lit vs svelte vs backbone vs angular vs inferno

  • react:

    豊富なサードパーティライブラリ、求人情報の多さ、そして柔軟なアーキテクチャを重視する場合に react が業界標準の選択肢となります。サーバーコンポーネントや新しいレンダリング機能へのアクセスも可能です。

  • preact:

    React のエコシステム(フックや JSX)を維持したいが、バンドルサイズを削減してパフォーマンスを向上させたい場合に preact を選択してください。React との互換性レイヤーを提供しており、移行コストが低いです。

  • vue:

    柔軟な導入方法(ライブラリとしてもフレームワークとしても利用可能)と、直感的なテンプレート構文を求めている場合に vue が適しています。Options API と Composition API の両方をサポートしており、チームの習熟度に合わせられます。

  • lit:

    ブラウザ標準の Web コンポーネントとしてライブラリを配布したい場合や、フレームワークに依存しない軽量なコンポーネントを作成したい場合に lit が最適です。バンドルサイズを小さく保ちつつ、テンプレートリテラルによる直感的な記述が可能です。

  • svelte:

    ビルドステップでの最適化によりランタイムを軽くしたい場合や、ボイラープレートコードを減らして生産性を高めたい場合に svelte を選択してください。コンパイラがコードを最適化するため、実行時のオーバーヘッドが最小限です。

  • backbone:

    既存のレガシーシステムのメンテナンスを行う場合を除き、新しいプロジェクトで backbone を選択すべきではありません。現代のコンポーネントベースの開発要件を満たさないため、代わりに vuereact などの現代的なライブラリを検討してください。

  • angular:

    大規模な企業向けアプリケーションを開発しており、型安全性、包括的なツールセット、そして長期的なサポートを必要とする場合に angular を選択してください。依存性注入や RxJS などの強力な機能が最初から含まれているため、アーキテクチャの統一性を保ちやすいです。

  • inferno:

    既存の React エコシステムを活用しつつ、特定の高性能要件(例えば、頻繁な更新が必要なダッシュボード)を満たす必要がある場合に inferno を検討してください。React との互換性がありますが、ライフサイクル管理に独自の注意点があります。

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