Table of Contents
Webアプリケーションの、主にフロントエンド周りに関連する歴史をまとめた。
静的サイト
まずは原初の話から。
1990年代前半、まだWebアプリケーションという言葉が無かった時代。 静的にHTMLファイルを配信するだけのWebサイト(静的サイト)だけがあった。 静的サイトでは、HTTPサーバーに複数のHTMLファイルを置いておいて、クライアントのHTTPリクエストのURLのパスによって配信するHTMLファイルを変える。
例えば、HTTPサーバーをhttpdで立てて、ドキュメントルートを/var/www/html
に設定して、以下のようにファイルを配置したとする。
/var/www/html/
|
+-- index.html
|
+-- sub/
|
+-- hoge.html
この場合、ブラウザでhttp://<HTTPサーバアドレス>/index.html
にアクセスすれば/var/www/html/index.html
が配信されてレンダリングされて表示される。
http://<HTTPサーバアドレス>/sub/hoge.html
にアクセスすれば/var/www/html/sub/hoge.html
が配信される。
古のWebサイトは、こんな感じにコンテンツごとにHTMLファイルを書いてサーバに置いておいて、その間にリンクを張って辿れるようにすることで構成されていた。
まあ今も大体そんな感じだけど。
動的HTML生成 (プログラムでHTMLを書き出す)
静的サイトだと表現できることが非常に限られるので、クライアントからのリクエストの内容をサーバが解釈し、DBの情報やなんかをもとにサーバ側でHTMLドキュメントを動的に生成し、クライアントに返す、ということをするようになった。
原始的(1990年代中盤から後半)には、プログラム中で一連のHTMLドキュメントを出力する方法がとられた。
public void doGet(
HttpServletRequest request, HttpServletResponse response
) throws IOException, ServletException {
response.setContentType("text/html;");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println(" <head>");
out.println(" <title>Hoge</title>");
out.println(" </head>");
out.println(" <body>");
out.println(new java.util.Date());
out.println(" </body>");
out.println("</html>");
}
使われた技術は、CGI (Perl)とか、Java Servletとか。 Jakarta ECSなんてのもあった。
動的HTML生成 (HTMLにプログラムを埋め込む)
プログラムでHTMLを書き出すことにより、かなり動的な感じにはなったが、書き出す処理を書くのがめんどくさすぎるし、読みにくい。 そのため、1990年代後半から2000年代初頭 にかけ、HTMLを主体にして、そのなかの動的な部分だけにプログラムを埋め込む技術がいくつも生まれた。
<%@ page contentType="text/html %>
<html>
<head>
<title>Hoge</title>
</head>
<body>
<%
out.println(new java.util.Date());
%>
</body>
</html>
HTMLドキュメントのひな型を作っておいて、その中にプログラムの処理結果を埋め込んでクライアントに返すため、テンプレートエンジンとか、テンプレートシステムとか呼ばれる。
該当する技術は、PHPとか、JSPとか、Velocityとか、eRubyとか。
DHTML
1990年代後半、クライアントサイドのJavaScriptでHTMLドキュメントをいじって、多少の動的感・インタラクティブ感をだす技術は既に一応あって、DHTMLと呼ばれていた。
DHTMLの肝はJavaScriptのDOM APIだ。 このAPIでは、HTML文書が各要素(タグなど)をノードとするツリー構造(DOMツリー)で表され、任意の要素を検索して取得したり、属性などを書き換えたり、要素の追加・削除ができる。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
</head>
<body>
<div id="hogehoge"></div>
<script type="text/javascript">
// idがhogehogeの要素の子要素として「<p>HOGEEEEEEE</p>」を追加。
document.getElementById("hogehoge").innerHTML = "<p>HOGEEEEEEE</p>"
</script>
</body>
</html>
しかし、このころのJavaScriptは、仕様・機能が貧弱だった上、ブラウザ間で挙動に差があったり、標準メソッドがブラウザ固有のメソッドで代替されていたりして開発体験が最悪だったためか、今日のようにWeb UIの中心的役割を果たすことはなく、補助的・装飾的機能の実装に使われることが多かったように思う。
アクセスした日付を表示したり、背景に雪を降らせたり、マウスカーソルを目玉に追いかけさせたり。
MVCアーキテクチャ
2000年初頭、Struts (Struts1)というJavaのWebアプリケーションフレームワークが流行り、Controller (Java Servlet)がクライアントからリクエストを受け取り、Model (JavaBeans)がそれを処理して、View (JSP)がHTMLをレンダリングしてクライアントに返す、という、MVCアーキテクチャが流行った。
Strutsに続いてSpring MVC、Ruby on Rails、CakePHPといったフレームワークが出てきて、MVCアーキテクチャによる開発効率や開発体験は洗練されていった。
Ajax
Strutsが全盛期の2005年ころ、JavaScriptで非同期にサーバからデータを取得し、それをもとにクライアントサイドでHTMLを動的に編集するような技術に、Ajaxという名前が付いた。
Ajaxは「Asynchronous JavaScript + XML」の略で、XMLHttpRequest (略してXHR)というJavaScriptのAPIで 、サーバにHTTPリクエストを送り、そのレスポンスを非同期に処理する技術。 レスポンスは、当時XMLが流行っていたので、その形式で送ることが想定されていたが、実際にはどんな形式でもいい。はず。 最近はJSONで送られることがほとんど。
JavaScriptはシングルスレッドで動くわけだけど、XMLHttpRequestはレスポンスを非同期に処理するため、リクエスト送信からレスポンス受信までの間、クライアントがスタックせずに済む。 また、通常のHTTPリクエストは、完全なHTMLドキュメントを受信して画面全体をレンダリングしなおす(i.e. 画面遷移する)のに対して、Ajaxは受信したデータをもとに画面の一部だけを更新するので、ネイティブアプリケーションに近めなユーザエクスペリエンスを実現できる。
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://httpbin.org/get', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
// DOMをいじる処理
// …
}
};
xhr.send(null);
Ajaxは、GoogleがGoogle Mapsで活用して一気に注目を集めた。 地図データをサーバから非同期に先読みするなどして、マウスのドラッグによって地図を滑らかにスクロールして見せるそのUIは当時画期的で、それまでの、画面遷移中心のUIからの飛躍を感じさせた。
PrototypeとjQuery
Ajaxの普及を後押ししたのが、PrototypeとjQueryというJavaScriptライブラリの登場だった。
PrototypeはRubyにインスパイアされて開発され、Ruby on Railsに採用されたことで2005年ころから普及したライブラリで、JavaScriptの標準グローバルオブジェクトであるArrayとかElementに便利メソッドを生やしたり、独自のグローバルユーティリティオブジェクトを追加したりして、Ajax処理をしやすくしたり、JavaScriptの機能を拡張してくれたりする。
特に、当時のプロトタイプベースで使いにくかったJavaScriptのオブジェクト指向を扱いやすくしてくれるClassや、配列の処理に便利なeachとかmapとかincludeとかのメソッドを追加するEnumerableなんかが熱かったように思う。
一方jQueryは、ファーストバージョンが2006年8月にリリースされ、ブラウザ間の非互換性をほとんど気にすることなく、簡潔なコードでDOM操作やAjax通信ができるAPIを提供した。 Prototypeと比べて、標準オブジェクトやグローバル名前空間を汚さない点がよかったのか、2007年 ころにはPrototypeを抜いて猛烈に普及した。
この頃からWebアプリケーションは、UIはクライアントサイドのJavaScriptでインタラクティブな感じに書いて、サーバサイドはXMLHttpRequestに対してJSONデータを返すAPIサーバとして働く、という感じのものが増えていったように思う。 またこの頃から、クライアントサイドの開発が量質ともに上がったために独立した仕事になり、サーバサイドと対比して、前者をフロントエンド、後者をバックエンドと呼ぶようになってきた。
因みに、PrototypeやjQueryと同様というかもう少し高機能なDojo Toolkitというライブラリが2004年ころからあったんだけど、あまり流行らなかった。 カスタムビルドという、モジュールを結合してminifyするwebpackみたいな機能を、Node.jsもない時代に実現していた先進的なライブラリだったんだけど、時代がついてこれなかったのかもしれない。
RIA (Flashとか)
WebアプリケーションにはAjaxと別の世界線もあった。
そこでは1997年ころにRIA (Rich Internet Application)という言葉が生まれた。 これは、クライアントサイドの技術を駆使した、表現力やユーザビリティが高いWebアプリケーションのこと。
(実際にはAjaxなアプリもこのくくりに入るが、ここでは非Web標準なクライアントサイド技術を使ったものの話を書く。)
RIA技術の代表格であるFlashは1996年に生まれた。 このころはShockwave FlashとかMacromedia Flashとか呼ばれたが、開発元が2005年にAdobeに買収されてAdobe Flashになり、そのあたりから2010年代前半辺りまで最先端のWeb UI技術として甚だしく流行った。
Flashは、Flexというフレームワーク(ツール?)のもと、ActionScriptというJavaScriptっぽいプログラミング言語と、MXMLというXMLなUI記述言語を駆使してWeb UIを開発できる技術。 WebブラウザにAdobe Flash PlayerとかAdobe AIRのプラグインを入れると表示できる。
Flashの人気に触発されたのか、Microsoftが2007年にSilverlightというのをリリースした。 これは、.NET Frameworkな言語(C#とかJScriptとか)と、XAMLというHTMLっぽいUI記述言語を駆使してWeb UIを開発できる技術。 WebブラウザにMicrosoft Silverlightプラグインを入れると表示できる。
また、Flashの誕生とほぼ同時期に、JavaでWebアプリケーションのUIを書くJava Appletというのも生まれていた。が、初期のバージョンでロードに時間がかかったり動作が重かったりする問題があり、嫌厭されてFlashほど流行らなかった。 WebブラウザにJavaプラグインを入れると表示できる。 なぜか最近になって、2017年 公開のマイナンバーのポータルサイトで採用されて話題になった。
こうした非Web標準技術を使ったRIAは、Ajaxに比べてリッチな表現ができたり、ブラウザ間の非互換性に悩まされないところに優位性があったが、以下のような問題があった。
- プロプライエタリな技術をベースにしていて、実装がブラックボックスだったり、仕様の方向性がベンダの都合に左右されたり、ベンダロックインされやすかったりする。
- ユーザがブラウザにプラグインをいれてないと表示されない。
- セキュリティ問題が見つかった場合、オープンな技術のものに比べて対策が遅い傾向があるし、ベンダによる実装しかないので替えが利かない。
- 他ベンダの技術や標準技術との親和性が無かったり、連携が弱かったりする。
- ブラウザ内で文字列検索ができなかったり、検索エンジンにまともにクローリングしてもらえない。
- 動作が重い。
このような問題のためか、Web標準周辺技術の発展に伴い、一時期は隆盛を誇ったFlashなども次第に廃れていった。
Flashは2020年に、Silverlightは2021年にサポート終了になり、Java Appletは2018年9月に出るJava 11で廃止されることが決まっている。
HTML 5とCSS 3とECMAScript 5
2000年代中盤 から非Web標準なRIAが流行ったのは、そもそもWeb標準技術であるHTML、CSS、JavaScript(というかその標準仕様を定めるECMAScript)が、アプリケーションのUIを作るという目的で設計されているわけではなく、それらを使ってWeb UIを作ることに限界があったのが一因だったと思う。
RIAの流行を受け、Web標準業界に危機感が募ったのか、2000年代後半 くらいからWeb標準技術にWeb UIを意識したバージョンアップの動きが始まった。
HTML 5の勧告 (2014年)
- それまでの標準であるHTML 4.01の勧告が1999年だったので、15年 ぶり。
- 文書構造を表すタグの追加:
<header>
とか<footer>
とか。 - 図を表現するためのタグの追加:
<svg>
と<canvas>
。 - inputタイプの追加:
date
、range
、email
とか。 - inputタグの属性の追加:
autocomplete
、pattern
、placeholder
、required
とか。 - マルチメディアのためのタグの追加:
<audio>
と<video>
。 - Webアプリケーション向けAPI追加: Drag and Drop、Local Storage、Web Workerとか。
- 冗長だったり見た目に関するタグ・属性の削除:
<center>
とか<font>
とかborder
とかcolor
とか。 data-*
属性のサポート。
CSS 3の勧告 (2011年)
- それまでの標準であるCSS 2の勧告が1998年だったので、13年 ぶり。
- 角丸、シャドウ、グラデーションのサポート。
- セレクタの機能追加: 属性値の部分マッチ、nth-childなど。
- メディアクエリ。
- Flexboxレイアウト、Gridレイアウト。
- Webフォント。
- トランジション、トランスフォーム、アニメーション。
ECMAScript 5の発行 (2009年)
- それまでの標準であるECMAScript 3の勧告が1999年だったので、10年 ぶり。
- strictモード。
- Arrayのメソッド追加: forEach、map、filterなど。
- Objectのメソッド追加: keys、freezeなど。
- グローバルオブジェクトにJSONが追加。
JavaScriptフロントエンドフレームワーク (第1世代)
Web標準技術が進化して表現力が上がり、ECMAScript 5やjQueryによってロジックを書きやすくなり、人々がWeb UIをバリバリ書けるようになり、RIAの影響もあってUIの複雑化が進んだ。
UIが複雑化すると、ユーザ入力の処理、Ajaxによるサーバとのデータ通信、UIの状態の取得、DOMの操作なんかを、何の秩序も構造化もレイヤー分けもなくナイーブにコーディングするのが辛くなってきた。
この辛みに対処すべく誕生してきたのが数多のJavaScriptフロントエンドフレームワーク。 2018年現在 まで続くフロントエンドフレームワーク戦国時代の幕開けである。
フロントエンドフレームワークは大抵以下のような機能を提供してくれる。
- UI(View)の記述を楽にする何か。テンプレートエンジンとか。
- Viewに表示しているデータとJavaScriptプログラムで保持しているデータを紐づける仕組み。(i.e. データバインディング)
- Ajaxユーティリティ。
- URLをViewやロジックと紐づける仕組み。(i.e. URLルーティング)
フロントエンドフレームワーク戦国時代初期に生まれた主要なフロントエンドフレームワークを列挙する。
(この記事では便宜上第1世代と呼ぶ。)
-
- 2010年 に誕生。
- MVVMアーキテクチャ。
- ModelがUIと独立してデータ(Ajaxでサーバから取ったものなど)を保持する。
- ViewModelがUIに紐づくデータとその操作を表現する。
- ViewはDOMツリー。ViewModelへの変更は自動でViewに反映されるし、その逆もしかり。
-
- 2010年 に誕生。
- 主にModelとViewからなるMVC的アーキテクチャ。
- Modelはデータとビジネスロジックを表現する。
- サーバから取ってきたデータを保持。
- ビジネスロジックによってデータが変わると、イベントを生成。
- ViewがModelをDOMに反映する。
- ModelからのイベントをlistenしてDOMに反映。
- ユーザからの入力を取得して、Modelに渡す。
- Modelはデータとビジネスロジックを表現する。
Ember.js v1
- 2011年 に誕生。
- MVVMアーキテクチャ。
- URLルーティングをコアとするコンセプトが特徴的。
-
- 2012年 に誕生。
- Google製。
- MVVMアーキテクチャ。
- DIやテストなどのサポートまであるフルスタックフレームワーク。
第1世代は、フロントエンドの世界にMVCアーキテクチャ(とその派生)をもたらした。
このMVCは、Struts時代のMVCとは違い、完全にクライアントサイドに閉じたアーキテクチャだ。 サーバ側はエントリーポイントとしてHTML(とCSSとJavaScript)をサーブするほかは、JSONを返すAPIサーバとしての役割に徹する。 このようなWebアプリケーションは、ページ遷移が発生せず、単一ページだけでUIが構成されるので、Single Page Application (SPA)と呼ばれる。
ModelとViewとの間でのデータの同期の仕方には以下のように2方向がある。
- M⇒V: Modelを更新すると対応するViewが自動で更新される。
- V⇒M: Viewがユーザ入力などによって変更されるとModelが自動で更新される。
前者だけをするのが1-wayバインディングで、両方するのが2-wayバインディング。 上に挙げた中では、Backbone.js以外が2-wayバインディング推しで、このころは2-wayバインディングが正義だったっぽい。
CommonJS、Node.js、パッケージマネージャ、モジュールバンドラ、AltJS、AltCSS、トランスパイラ、タスクランナー
第1世代のフロントエンドフレームワークが出始めたころ、JavaScriptの言語周りの環境にも大きな変化があった。 正直書くの辛くなってきたので、一気に片付ける。
CommonJS
クライアントサイドでJavaScriptが盛り上がっているのを見て、もっとJavaScriptいろんなところで活用できるんじゃね? となって、ブラウザの外でも普通のプログラミング言語としてJavaScriptを使うためには、どんな機能を追加すべきか、みたいな議論をするプロジェクトが2009年に立ち上がった。 CommonJSである。
CommonJSの最大の功績は多分、モジュールシステムを言語仕様でちゃんとサポートしよう、と言ったこと。 モジュールシステムは、Cでいうincludeとか、JavaやPythonのimportとか、そういう機能。 JavaScriptにはもともとそういうのが無くて、単にファイルを分割して個別にロードしていただけだったので、名前空間がコンフリクトしたりしなかったりしてた。
因みに、JavaScriptのモジュールシステムには、CommonJSのやつ以外にもAMDというのがあったけど、そっちは盛り上がらなかった。
Node.js
CommonJSの流れを汲んで、サーバサイドのJavaScriptランタイムとしてNode.jsが2009年にリリースされた。 これにより、ブラウザ外でJavaScriptを実行できるようになり、以降のJavaScript開発体験の劇的な改善につながった。
パッケージマネージャ
2010年 には、Node.jsにパッケージマネージャとしてnpmが同梱されるようになった。 これにより、モジュールを公開してシェアして再利用する文化が定着し、JavaScriptプログラムの開発効率や品質がかなり向上したはず。
パッケージマネージャとしてはもうひとつ、Bowerというのが2012年に出た。 npmはサーバサイドのパッケージ、Bowerはクライアントサイドのパッケージ、みたいな住みわけが当初はあったが、最近は全部npmになってBower使ってるプロジェクトは見なくなった。
2016年10月 には、FacebookがYarnというnpmを代替するツールを発表。 パッケージバージョンのロック、CDN (CloudFlare)・キャッシュ・並列処理によるパッケージダウンロードの高速化、パッケージ間のバージョンの不整合解消(フラットモード)、といった機能により、発表直後から急速にシェアを伸ばした。
モジュールバンドラ
サーバサイドでモジュールシステムができたのはよかったけど、その仕様がブラウザでサポートされることは終ぞなかった。 ので、モジュールバンドラというものが生まれた。 これは、ソース中のモジュールインポート(requireとかimport)をたどって、モジュール分割されたソースをブラウザが読めるように一つに結合してくれるツール。
モジュールバンドラのパイオニアが、2011年 にリリースされたBrowserify。 Browserifyは、モジュールの結合だけでなく、Node.js特有のAPIをある程度ブラウザでも動くようにしてくれるなど、魔法のようなツールだった。
2012年 にはwebpackというモジュールバンドラが出て、後述のトランスパイラと上手く連携したり、JavaScriptだけでなくCSSもHTMLもフォントも画像ファイルもなんでもバンドルできる高機能により、Browserifyを食った。
モジュールバンドルすると、ファイルサイズが大きくなって、ブラウザでロードするのに時間がかかって、初期画面の表示が遅くなる問題があった。 2015年、その問題を軽減すべく、Rollupというのが出てきた。 Rollupは、Tree-shakingという機能で、バンドル時に不要なコードを削除することでファイルサイズを小さくできることを売りにした。 が、webpackがバージョン2でTree-shakingをサポートしたため、使う理由がなくなった。
webpackは機能的には最高にクールだったが、設定が複雑で設定ファイルが肥大化するという問題があった。 この問題を解消すべく、2017年末 にParcelというモジュールバンドラがリリースされ、ゼロ設定で使えるということで人気を集めてきている。 今の時点でプロダクションレディなレベルなのかは疑問。
AltJS
上に書いた通り、2009年 にECMAScript 5が発行されて、JavaScriptは若干改善されたわけだけど、はっきり言ってまだまだ貧弱な言語だった。 そこにCoffeeScriptが登場。 2009年末 のことだった。
CoffeeScriptは、RubyやPythonみたいな簡潔で機能的な構文を備えた生産性の高い言語で、JavaScriptにコンパイルできる。 クラス構文とか、アロー関数とか、配列内包表記とか、インデントによるブロック構造とかを実現してて書き心地がかなりよかったのと、Ruby on Railsに採用されたというのもあって、2010年代中盤 くらいまで結構流行った。
CoffeeScriptのように、JavaScriptの代替として使い、JavaScriptに変換して実行するのを主なユースケースとする言語を、AltJS (Alternative JavaScript)と呼ぶ。 (なので、KotlinとかClojure(Script)とかHaxeなんかはJavaScriptにもコンパイルできるけど、ここではAltJSとして扱わない。) CoffeeScriptの最大の功績は、このAltJSという分野を切り開き、JavaScriptフロントエンドにコンパイルという概念を持ち込んだことだったと思う。
CoffeeScript自体はその後、2015年 に発行されたECMAScript 2015がその仕様を取り込んだことで役目を終えた。 2017年9月 にバージョン2をアナウンスして再起を図ったが、そのころすでに他に有力なAltJSが出てたし、ECMAScriptも結構成熟してきてたし、あまり注目されなかった。
AltJSには他に以下のようなものがあるが、ほぼTypeScriptしか使われてなさそう。
- TypeScript
- 2012年10月 初版リリース。
- Microsoft製。
- 静的型付けが最大の特徴で、他にもクラスやアロー関数やレキシカル変数などをサポート。
- PureScript
- 2014年4月 初版リリース。
- 強い静的型付けの関数型言語。
- Dart
- JSX
- DeNA製。
- 名前がReactのJSXと紛らわしい。
- 誰も使ってないし、2014年 くらいから開発止まってる。
- Flow
- 2014年11月 初版リリース。
- Facebook製。
- AltJSというべきものかは微妙。JavaScriptに静的な型情報を付加するためのもの。
- ReactなどのFacebookのプロジェクトやVue.jsで使われていてそれなりに存在感があるが、TypeScriptに押され気味。
AltCSS
CSSにもalternativesがある。 というかAltJSよりも歴史が古い。
- Sass
- 2006年 に誕生。
- SASS記法とSCSS記法がある。
- AltCSSでは1番人気っぽい。
- Less
- 2009年 に誕生。
- Sassに感銘を受けたけど、そのSASS記法がCSSと違いすぎてちょっと、と思った人がCSSに寄せて作った。けどSassもCSSに寄せたSCSS記法をサポートしたため食われた。
- Stylus
- 2010年 に誕生。
- PostCSS
- 2013年 に誕生。
- 正確にはAltCSSではなく、CSSを処理するツールをJavaScriptで開発できるフレームワーク。
- PostCSS Preset Envというプラグインとともに使うと、CSSのエッジな機能を使えるようになる。つまりどちらかといえば後述のトランスパイラに近い。
トランスパイラ
CoffeeScriptの流行などを受けて、ECMAScriptに再び改善の圧力がかかったのか、2011年後半 ころから次期ECMAScriptの議論が活発化した。 2015年 に満を持してECMAScript 6改めECMAScript 2015が発行された。
ECMAScript 2015は、クラス構文、アロー関数、レキシカル変数、定数、関数のデフォルト引数、ジェネレータ、テンプレート文字列、モジュールシステムなどをサポートし、一気にまともなプログラミング言語になった。
しかし、それらの新しい機能をアプリケーションに使うには、各社のブラウザのJavaScriptエンジンが実装して、さらにその実装したバージョンのブラウザがユーザに十分に行きわたるのを待たないといけない。 ECMAScriptの新機能は、正式に発行される前から仕様が公開され、ブラウザが先行して実装してはいくものの、プログラマは短気なのでそんなの待ってられない。
といった状況のなか、2014年10月 に6to5というツールがnpmで公開された。 ECMAScript 6で書かれたコードをECMAScript 5なコードに変換してくれる、トランスパイラというツールだった。
(実はトランスパイラとしては2013年3月に公開されたGoogle製のTraceurとか、2014年4月 に公開されたEmber.jsチーム製のesnextのほうが先駆けだったんだけど、6to5の開発スピードがとんでもなく早く、2015年1Q には機能面で両者を抜いてしまったらしい。)
6to5は2015年2月に名前をBabelに変えて、単に6to5という名前が示す機能だけでなく、JavaScript周りの様々なツールを開発・統合するためのプラットフォームとなった。
2018年現在、Babel無しでフロントエンド開発をすることはほぼ無さそうな感じになってる。
タスクランナー
モジュールバンドラやら、AltJSやら、AltCSSやらで、フロントエンドにコンパイルとかビルドとかいう作業が必要になって来たため、この業界にも必然的にタスクランナーが登場してきた。
タスクランナーというのは、他業界ではビルドツールなどとも呼ばれているもので、Cとかで使われるMakeとか、JavaのAntとかMavenとかGradleとか、GoogleのBazelとかと同様のもの。
まず、2012年1月 にGruntがリリースされて人気を博した。 が、当時のGruntの設定ファイルがJSONで書きにくいとか、処理がシーケンシャルで遅いとかいう不満が潜在的に溜まっていった。
で、それらの問題を払拭するgulpが2013年7月に出て、Gruntを食った。
けど結局、Gruntもgulpも、タスクの処理をどこかの馬の骨が作ったプラグインに頼っていて不安定で、またビルドツールというレイヤが増えたせいでビルドエラーのデバッグがし辛くなるという根本的な問題が顕在化し、npm-scriptsでいいじゃん、ってなった。
シンプルイズベスト。
JavaScriptフロントエンドフレームワーク (第2世代)
前章で書いたフロントエンド界の変容の後あたりに、当時の先端技術を取り入れて誕生したフロントエンドフレームワークを、この記事では第2世代と呼ぶ。
第2世代は第1世代から正統な進化を遂げた感じで、あいかわらずMVW (i.e. MV*)だった。 主要なのは以下。
-
- 2013年11月 に誕生。
- Googleのエンジニア達が作った。
- 最初は単なるPolyfillライブラリとして世に出て、徐々に機能を増やし、マテリアルデザインの標準実装となり、さらに膨らんできている。
- Web ComponentとかService WorkerといったエッジなWeb標準技術を取り入れた軽くて強力なフレームワーク。
- 2-wayバインディングもできる。
Vue.js v1
- 2013年12月 に誕生。
- Googleのエンジニア(個人)製。
- MVVMアーキテクチャ。
- 軽量AngularJSな感じらしい。
-
- 2014年6月 に誕生。
- AngularJSもReactも複雑すぎ。フロントエンド開発に必要十分なコンパクトな機能を提供するぜ、というフレームワーク。
- Aureliaよりかは使われていそう。
-
- 2015年11月 に誕生。
- AngularJSっぽいフルスタックフレームワークで、EcmaScript 2015+とかWeb Componentsとかの先端技術を取り入れていることが売り。
- 2-wayバインディング推しで、あまり流行らなかった。
-
- 2016年9月 に誕生。
- AngularJSの後継。AngularJSとの互換性をばっさり切り捨てる代わりに、アーキテクチャを刷新し、性能面と機能面の色々な問題を克服したらしい。
- が、Reactが画期的過ぎてAngularJSの栄光は取り戻せなかった。
- 最初2-wayバインディングまで切り捨てたが、あとで復活させた。
React (Virtual DOM)
第1世代から流行っていた2-wayバインディングがちょっと辛みを帯びてきた。 というか、2-wayバインディングしかできないAngularJSが辛くなってきたということだったのかもしれない。
2-wayバインディングには以下のような問題があった。
- 変更をwatchするオブジェクトが増えて、性能が悪くなる。
- ModelとViewとの間の依存やデータの流れが複雑になって、コーディングやデバッグが難しくなる。
これに異を唱えて登場してきたのがFacebookによるReact。 2013年3月 のことであった。
2-wayバインディングもMVCもテンプレートも要らんとして、代わりにReactが突きつけてきたVirtual DOMという解は、世界中の人々の魂を震えさせた。
Virtual DOMは、その名の通りDOMの仮想化であり、JavaScriptからReactのAPIを通してDOMのようなものを更新すると、Reactがいい感じに実DOMを更新してくれるというもの。 開発者は深く考えずに、イベントが発生するごとに、ページ全体を表すDOMツリーがどうなっているべきかをReactに教えるだけでいい。 あとはReactが、現在の実DOMとの差分を計算し、差分だけを性能よく更新してくれる。 これによって開発者は、DOMの状態やイベントの種類をみてアドホックに実DOMやModelの更新処理を書くという苦行から解放され、宣言的に富豪的にフロントエンドプログラミングができるようになった。
さらに2014年5月、ReactにベストマッチするアプリケーションアーキテクチャとしてFluxが発表された。 これは単方向のデータフローが特徴のアーキテクチャで、斬新でかっこよくて未来だった。
JavaScriptフロントエンドフレームワーク (第3世代)
React後、Virtual DOMの実装がいくつも出てきた。 virtual-domとかMaquetteとかPreactとかInfernoとか。
Fluxの実装も、Facebook自身によるFluxのほか、FluxxorとかReduxとかMobXとか沢山出た。
で、React+Reduxがいい感じってなって、世界の8割近くの人がReactで書くようになって、猫も杓子もVirtual DOMってなった辺りのフロントエンドフレームワークを第3世代と呼ぶことにする。
第3世代としては以下が挙げられる。
-
- 2015年8月 リリース。
- Glimmerというレンダリングエンジンを搭載。
- Glimmerは、テンプレートをGlimmer VM上で動くバイトコードにコンパイルして、実DOMを速くレンダリングしてくれるもの。
- Virtual DOMとは違う感じだけど、実DOMの更新を開発者の代わりにやってくれるあたり、目指しているものは同じ。
-
- 2016年10月 リリース。
- snabbdomベースのVirtual DOM実装を搭載。
- 2017年頭位からかなりの勢いで流行ってきている。
-
- 2016年11月 に誕生。
- Rich Harrisという個人が開発。
- フレームワークレスとか消えるフレームワークなどと呼ばれる一風変わったフレームワーク。
- Virtual DOMではない。
- コンパイルするとピュアなHTMLとCSSとJavaScriptが生成される。Webフロントエンド言語と呼んだほうがいいのかも。
- 海外ではぼちぼち使われている模様。
-
- 2018年5月 正式版リリース。
- Dojo Toolkitの後継。
- Virtual DomでTypeScriptでリアクティブでフルスタック。
終わりに
2018年8月現在 では、React vs Vue.js vs Angularといった感じで、激動の時代が過ぎてやや落ち着いて来ている感があるが、油断はできない。 実際、最近Elmという関数型AltJS兼Frontendフレームワークがじわじわ盛り上がってきている感じがあり、一波乱あるかもしれない。
いろいろ書いたけど、ElectronとかReact NativeとかNext.jsとかのSSRとかGatsby.jsとかGraphQLとかPWAとかWebAssemblyとかサーバーレスとかCSS設計手法とかCSSフレームワークとかいろいろ書き漏れた。
フロントエンドのユニットテストとかE2Eテストとかもいろいろあって面白い。 (E2Eテストは前に書いた。)
年表も気が向いたら追加したい。
しかしReact+Reduxに再入門したよ、っていう記事の前座として書くつもりだったのに、ずいぶん長編になってしまった…