COLUMN
2022年09月05日
なぜフロントエンドフレームワークを用いるのか
カテゴリー:システム開発, テクノロジー
タグ:React, Vue.js, WebComponents, フロントエンド
これらのフロントエンドフレームワークが何をもたらし、私たちの開発生産性を上げてくれるのかを紹介します。
結論
- DOM操作をなくす
- コンポーネント化による分担作業
- 充実したエコシステムの利用
DOM操作をなくす
おそらくフロントエンドフレームワークで最も重視されているのはJavaScriptからHTMLのDOM操作をなくすことにあるのではないでしょうか。Reactで登場した仮想DOMと言う概念は、JavaScriptでデータを操作すると、UIに反映される仕組みになります。
それまでのフロントエンドではjQueryやVanilla JS(素のJavaScript)を使って、DOM操作を行っていました。例えば #hello
のテキストを書き換える場合は次のようなコードになります。
document.querySelector('#hello').innerHTML = 'こんにちは、世界!';
そして、認証状態などを画面に反映していた場合、JavaScriptを使って状態を都度確認することもあったでしょう。
<div class="login" data-status="true">ログイン状態</div>
<script>
if ($('.login').data('status') === 'true') {
// 認証している
} else {
// 認証していない
}
</script>
こうした操作はとても面倒です。HTMLはグローバルなので、どのJavaScriptファイルからでも操作できます。その結果、あるファイル(a.js)で修正した内容を別なファイル(b.js)で検知するのが面倒だったり、思いもしなかった変更がいつの間にか行われている可能性があります。
仮想DOMでは、こうした煩雑な管理から私たちを解放してくれました。JavaScriptのデータを編集するだけで、UIへの反映はお任せになります。なお、Svelteは仮想DOMを使いません。
以下は簡単な例ですが、ログイン判定を行っています(コード自体はなんちゃってReactです。動作保証はありません)。 isLoggedIn
変数は setIsLoggedIn
関数を通してのみ、値を変更できます。
// デフォルトは false (未ログイン)
const [isLoggedIn, setIsLoggedIn] = useState(false);
// ログイン判定
if (loggedIn()) {
// ログインしていればtrueに変更
setIsLoggedIn(true);
}
後はUI側で isLoggedIn
変数の値に応じて表示を変更するよう指定しておくだけです。DOMでどう描画するかは気にする必要がありません。
// ログイン状態 isLoggedIn の値によってコンポーネントを出し分け
return (
{ isLoggedIn ? <UserInfo /> : <LoginForm />}
);
このDOM操作をなくすことで、JavaScript側の実装をシンプルなものにし、開発効率を向上させられるのは間違いないでしょう。ただ、意図しない再レンダリング発生による弊害もあり、上手に使いこなすのには慣れが必要です。
コンポーネントの責任を明確にする
多くのフロントエンドフレームワークはWeb Componentsの思想を取り入れています。Web ComponentsはHTML/JavaScript/CSSを一つのコンポーネントとし、各コンポーネントを連携させることでWebアプリケーションを構築します。その際に大事になるのは、各コンポーネントの独立性と連携です。
例えばカレンダーコンポーネント HTMLElements/smart-calendar – webcomponents.org を想定します。このカレンダーコンポーネントは <smart-calendar />
というHTMLタグだけでカレンダー表示できるとします。一般的にカレンダーを描画したり、操作するのは複雑ですが、コンポーネントとしてまとまっていることで、開発者はとても簡単に導入、利用できます。
もちろん、ただタグを記述するだけでなく色や言語を変えるなど、カスタマイズができると良いでしょう。そうしたオプションを受け付けられるコンポーネントは多数ありますし、自作する場合も追加できます。
<smart-calendar
theme="blue"
locale="ja"
/>
日付を選択した場合には、親コンポーネント(呼び出し元)にコールバックが欲しいでしょう。これもまたコンポーネントの設計次第で可能です。
const calendar = document.querySelector('smart-calendar');
calendar.addEventListener('change', event => {
// 選択した日付を取得する
const detail = event.detail,
value = detail.value;
})
ReactやVue風に書くと、次のようになるでしょう。
<smart-calendar
theme="blue"
locale="ja"
@change={change}
/>
この辺りはコンポーネントの設計に依存しますが、何ができて、どういった機能を提供するかはコンポーネント側で決められます。そうやってコンポーネントの責任範囲を明確にし、連携しやすくします。
再利用性を高める
コンポーネントは再利用も容易です。別な画面でカレンダーコンポーネントを使う場合、同じように <calenar />
を記述すれば良いだけです。ある場面では青いカレンダー、別な場面では黒いカレンダーと言った使い分けもできるでしょう。
こうしたコンポーネントは別ファイルに分離されているのもポイントです。多くのコンポーネントが組み合わさった画面であっても、各コンポーネントが別ファイルや分離していることで、管理しやすくなります。責任範囲が明確になっていれば、どこで何をしているかが明確になり、処理の見通しも良くなります。これは複数人で開発を進めている場合に特に大事になるでしょう。
エコシステムの拡充
最近のUIフレームワークは大抵ReactやVueなどに対応しています。また、npmで提供されるパッケージも数多く存在します。それらを利用する上でもフロントエンドフレームワークを利用する価値があるでしょう。Vanilla JSのプロジェクトでもWebpackなどを導入できますが、Next.jsやVue CLIを使った方が早いでしょう。
かつては開発環境の構築が大変というイメージがありましたが、最近ではパッケージング化も進み、プロジェクト開始までの敷居はずいぶん下がっています。特にCLIツールを使うことでプロジェクトのベースを生成してくれたり、プラグインのインストールなども行ってくれます。
主な選択肢
フロントエンドフレームワークとして有名なところを以下に挙げます。
どのフロントエンドフレームワークを導入すべきか
先述の通り、グローバルで見るとReact/Next.jsが人気になっています。もし開発チームに海外メンバーがいるなら、Reactが選択肢に挙がるでしょう。日本国内であればVueの人気が高いように見えます。これはコミュニティの活発さなどを見ても感じられるところです。
- v-tokyo – connpass
- React.js meetup – connpass
- Angular Japan User Group – connpass
- Svelte Japan User Group – connpass
- Preact
後は、メンバーの得意とするフレームワークが選択肢になるでしょう。
Reactはバージョンアップが激しいイメージがありましたが、バージョン18(2022年03月29日リリース)になってからは落ち着いてきたようです。Vueはバージョン3がリリースされていますが、UIフレームワークなどのエコシステムがまだ追従し切れていないイメージがあります(例えば有名なVuetifyはVue3版を開発中です)。Vue2は2023年09月にLTSが終わるので、選択するのは難しいでしょう。
フロントエンドフレームワーク導入で考慮する点
Reactなどでよく言われることですが、Vanilla JSと比べればパフォーマンスが落ちるのは否めないでしょう。特に仮想DOMに起因するところが大きく、再描画する範囲をどこまで絞り込めるかが鍵になります。そのため、多くのフロントエンドフレームワークではパフォーマンスの高さを売りにしています。
フロントエンドフレームワークではベストプラクティスが年々変化しています。組み合わせるミドルウェアであったり、関数コンポーネントとクラスコンポーネントのどちらが良いかなど、よく変化が起きます。その結果として、インターネット上にある知見が陳腐化してしまったり、自分たちのケースでは役立たないこともあります。
そうした変化の速さに追従し、プロジェクトをアップデートしていく必要があります。
まとめ
モダンなフロントエンド開発においては、フレームワークを導入することで開発効率が向上します。中途半端に導入するのは難しいため、入れるのであればコマンドラインツールなど、ベースから利用すべきでしょう。
HexabaseではVueによる管理画面デモやTodoアプリデモ、Angularによるガントチャートデモ、Nuxt.jsによるログインデモやチャットデモなどを公開しています。各種フロントエンドフレームワークを利用したデモとして、ぜひご覧ください。