宣言的UIと命令的UI
前回の記事で一通りWebフロントエンドの歴史を整理したところで、宣言的UIと命令的UIについて整理していきたいと思います。
本記事では、フロントエンドの歴史において特に象徴的なjQueryからReactへの移行を中心に整理していきます。
命令的UIと宣言的UIの違いとその利点、欠点について整理しどのようにして現在のフロントエンド開発が進化してきたのかを探ります。
宣言的UIとは
宣言的UIは、UIの状態を宣言的に記述し、その状態に基づいてUIをレンダリングするアプローチです。開発者は、どのようにUIを構築するかを直接指示するのではなく、UIが最終的にどのように見えるべきかを宣言します。代表的なフレームワークにはReactやVue.jsがあります。
Reactのようなライブラリでは、コンポーネントベースの設計を採用しており、再利用性の高いUIコンポーネントを作成することができます。
宣言的UIの大きな利点は、コードの可読性と保守性が向上する点です。開発者は、UIの状態とその変化をシンプルに記述するだけで済み、状態が変わると自動的にUIが更新されます。jQueryのような直接DOMを更新するものと比較すると。仮想DOMの利用により、効率的な差分計算と更新が行われ、パフォーマンスも向上します。
また、リアクティブなデータバインディングの仕組みを持っているため、データの変更が自動的にUIに反映され、手動でDOMを操作しての更新作業が不要です。
命令的UIとは
命令的UIは、UIの具体的な変更手順を詳細に記述するアプローチです。開発者は、どの要素をどのように操作するかを直接指示します。代表的なライブラリにはjQueryがあります。jQueryを用いると、DOM要素の操作やイベントハンドリングが簡便になり、当時のWeb開発に大きな影響を与えました。また、jQueryはブラウザ間の互換性を確保するためのラッパー関数を提供し、開発者はブラウザ間の差異を気にせずに開発を行うことができました。
命令的UIの利点は、操作が直感的であり、小規模なプロジェクトや単純なタスクには適していることです。開発者は、DOM要素を直接操作するため、動作の確認やデバッグが比較的容易です。大規模なアプリケーションになると、命令的UIのアプローチはコードが散在しやすく、次第に管理が難しくなります。
命令的UIは、シンプルなWebサイトや古いブラウザのサポートが必要なプロジェクトには今でも利用されています。また、時代的な視点から、従来のMVCフレームワークのテンプレート機能を利用して書かれたコードに動的な振る舞いを追加しやすく、そういった構成のアプリケーションではいまだに使われています。
現代の複雑なWebアプリケーション開発においては、技術的な背景からも、フロントエンド組織とバックエンド組織を分割したいという組織的な要求からも、宣言的UIのアプローチが選択されることが多いです。
jQueryの時代
jQueryは2006年に登場し、ブラウザ間の互換性の確保とDOM操作の簡略化を軸に当時のWeb開発を大きく変えました。豊富なプラグインエコシステムもあり、多くのWebサイトで利用されました。しかし、jQueryの時代には以下のような課題がありました。
課題1: アプリケーションの構造
- 命令的なイベントハンドラ
- 大量のイベントハンドラが散らばり、処理も散らばる
- イベントハンドラ間に不明瞭な依存関係が生まれる
- DOMが巨大で暗黙的なグローバル変数になってしまう
課題2: 開発ワークフロー
- HTMLはマスタとなるリソースではない
多くの場合、Gitで管理されるのはHTMLテンプレートであり、実際にレンダリングされるHTMLはそのテンプレートから生成されます。 - JS側が必要とするHTMLを修正するには、テンプレートの修正が必要
テンプレートの修正が必要な場合、バックエンドとフロントエンドの開発者間でのコミュニケーションが煩雑になります。
Reactの登場による影響と当時の状況
2013年にFacebookがReactを公開したことは、フロントエンド開発に大きな変革をもたらしました。当時、jQueryやbackbone.jsなどの命令的なライブラリが主流であり、DOM操作やイベントハンドリングが中心でしたが、大規模なアプリケーションではコードの可読性や保守性に問題が生じていました。
Reactは、UIをコンポーネントという再利用可能な単位で構築する宣言的なアプローチを導入しました。この発明が画期的で、開発者はUIの状態を明示的に管理し、コードをわかりやすく書くことができるようになりました。また、直接DOM操作をせずに仮想DOMを通じて効率的に更新することが可能となりました。
Reactは一方向データフローを採用しており、データの流れを予測しやすくし、バグの発生を抑制する効果がありました。Vue.jsはReactの影響を受けて開発されていますが、双方向データバインディングをサポートしているため、Reactよりも状態管理が簡単です。ただ、一方向データフローの方がバグの発生を防ぎやすいとされています。
また、エコシステムの発展も迅速で、ReduxやReact Routerなどのライブラリが次々と登場し、開発効率が向上しました。これにより、Reactは短期間で広範な支持を集め、フロントエンド開発の標準的な選択肢となりました。宣言的UIの普及により、開発プロセスが劇的に改善され、現在もその影響は続いています。
宣言的UIの利点
- コンポーネントベースの設計: 再利用可能なコンポーネントを作成し、UIを構築します。これにより、コードの再利用性とメンテナンス性が向上します。
- 仮想DOM: 仮想DOMにより、効率的な更新が可能になり、パフォーマンスが向上します。
- 一方向データフロー: 状態管理がシンプルになり、バグの発生を防ぎやすくなります。
- エコシステムとツールチェーンの豊富さ: ReactやVue.jsは、豊富なライブラリやツールチェーンを持ち、開発効率を大幅に向上させます。
- リアクティブなデータバインディング: データの変更が自動的にUIに反映されるため、手動での更新が不要です。
宣言的UIの欠点
- 学習曲線: jQueryに比べて学習曲線が急であり、習得に時間がかかることがあります。
- 設定が複雑: プロジェクトのセットアップや構成が複雑になることがあります。
- 依存関係の管理: 多くのライブラリやツールに依存するため、依存関係の管理が難しくなることがあります。
jQueryとReactの比較
jQuery
$(document).ready(function(){
$('#submit').click(function(){
$('#form').hide();
});
});
React
import React, { useState } from 'react';
function App() {
const [visible, setVisible] = useState(true);
return (
<div>
<button onClick={() => setVisible(false)}>Hide Form</button>
{visible && <form id="form">...</form>}
</div>
);
}
jQueryでは、DOM要素を直接操作する命令的なスタイルで記述されます。小規模なプロジェクトや、古いブラウザへの対応が必要な場合には有用ですが、今新しく何かを作る場合にjQueryを選択することは基本的にはないでしょう。
Reactでは、状態にもとづいてUIをレンダリングする宣言的なスタイルで記述されています。例では、visibleという状態に基づいてフォームを表示・非表示するようになっています。Reactのコンポーネントは、状態を持ち、その状態に基づいてUIをレンダリングすることができます。2024年時点で新しいプロジェクトを作成する場合、基本的にはReactをベースとして技術選定することが多いです。jQueryと比較した場合のReactの欠点はHTML、CSS、JSといった基本知識以外にReact特有の知識を学ぶ必要があることです。また、古いブラウザへの対応が必要な場合、Reactの利用が難しいこともあります。
まとめ
- 宣言的UIと命令的UI
- 宣言的UI
- React, Vue.jsなどのフレームワークが主流
- データを変更すると、自動的にUIが変更される
- 命令的UI
- jQueryなどのライブラリが主流
- データを変更すると、UIを手動で変更する必要がある
- アプリケーション構造が複雑になると、コードが複雑になりやすい
- 宣言的UI
所感
命令的UIと宣言的UIは、アプローチの違いによってそれぞれ異なる利点と課題を持ちます。jQueryの時代には命令的なスタイルが主流でしたが、Reactの登場により宣言的なスタイルが主流となりました。2024年時点で新しいプロジェクトを作成する場合、基本的にはReactをベースとして技術選定することが多いでしょう。
特にバックエンドの構造化されたアプリケーションに馴染みのある場合は、Reactのような宣言的UIのアプローチが理解しやすいかもしれません。
日々進化しているフロントエンドの技術ですが、大きなパラダイムの変化としてjQueryからReactへの移行が象徴的な出来事であると言えるでしょう。。個人的にはシンプルなSPAを作成する際にはVue.js、比較的大規模だったり、長期的なプロジェクトにはReactを選択することが多いです。また、要件的にSSGが適している場合は簡単なものだとAstro、複雑なものだとNext.jsを選択することが多いです。
