この記事はグロービス Advent Calendar 2017の6日目です。

グロービスは麹町にある、社会人向けの経営大学院を運営している会社で、現在私はここの会員プラットフォームのフロントエンド開発をみさせてもらっています。なおグロービスでは、React 開発に参加してくれる方を絶賛募集中です。くわしくはこちら

プロローグ

本来「キモい」という主観の表明に正しいも間違っているもないので反論などは成り立たないとは思うのですが、DL数では他のフロントエンドフレームワークを圧倒し、もはや jQuery さえ凌駕する React に対して、食わず嫌いの正当化のための言説に用いられている感すらあるので、一度ちゃんと論じておきたいテーマでした。

なお想定する対象読者は React を本格的に使ったことのないエンジニアですので、バリバリ React を使っている人には当たり前すぎることしか書きません。読んだ後に「時間の無駄だった」と言われても困りますので、あらかじめご了承ください。

話を戻して、たとえば Google 検索で「JSX k...」と入力すると、

jsx_suggest.png

こんなふうに「気持ち悪い」がサジェストされますし、Twitter でエゴサーチすれば「JSX キモい」「JSX 気持ち悪い」でそれぞれ数十件ヒットします。

ただそういった書き込みを端から読んでいくと、「今ではキモいと思わなくなりました」とか「あれほど気持ち悪いと思ってたJSXも今では心地よく感じる」というような意見もチラホラ見つかります。
かく言う私も React をさわり出してようやく1年くらいで、それ以前はただ斜め読みしたサンプルコードの断片を見てなんかゴチャゴチャしてて書きにくそう/読みづらそうと思っていたので、「キモい」と言いたくなる気持ちも実はわからなくもありません。

ですので「JSX キモい」とは誰が言っているのか、はたまた彼らの「キモい」という感想の裏にどんなバックグラウンドがあるのかを考察していきたいと思います。

他のフロントエンドフレームワークとの比較

「React は View ライブラリであってフレームワークではない」というのは重々承知の上で、よく比較される Vue や Angular と比較してみましょう。

  • 1
  • 2
  • 3
  • 4

というリストを生成したい場合の3つのサンプルコードは以下のようになります。

(1) Vue テンプレート
<ul v-for="n in 4">
  <li>{{ n }}</li>
</ul>
(2) Angular テンプレート
<ul *ngFor="let n of _.range(1, 5)">
  <li>{{ n }}</li>
</ul>
(3) JSX
<ul>
{_.range(1, 5).map(n =>
  <li>{n}</li>
)}
</ul>

(※ 下2つのサンプルは Lodash を読み込んでいる部分のコードを省略)

一見したところのシンプルさは (1) > (2) > (3) といったところでしょうか。Vue テンプレートコードのシンプルさから見れば、JSX のコードは理解しづらいかもしれません。
ですが何が理解を難しくしているかというと、これら全てがテンプレート言語だという先入観です。(3)には(1)(2)のようには注釈に「〜テンプレート」とつけてません。

ありがちな誤解ですが JSX はテンプレート言語ではありません。その名前(JSX は「JavaScript eXtension」の略)が示す通り、JavaScript の記法拡張です。
JSX で書かれる HTML 記法、たとえば

<h1>Hellow, world!</h1>

は、

React.createElement('h1', 'Hellow, world');

と同義です。
React は単なる View ライブラリだと章の最初に書きましたが、React ではロジックとテンプレートといった区別は一切なく、全てを JavaScript で記述します。その際、HTML の部分はすべて createElement() を使って書いてもいいのですが、それだとさすがに不便なので JSX というシンタックスシュガーが用意されているというだけの話です。

(3) のコードを HTML ではなく JavaScript(ES2015) だと思って読んでみましょう。あら不思議、だんだんキモくなくなってきます。
さらに React 慣れしてくると、むしろ (1) の v-xxx や (2) の *ngXxx のほうがキモいと感じるようになってきます。なぜならこれらは、Vue や Angular が用意した、他では全く通用しない独自リテラルだからです。

JSX は Pure JavaScript に HTML に限りなく近い(というのは、JavaScript の予約語を避ける必要もろもろの事情で、100% HTML そのものではないため)拡張記法が付与されたものであり、JS が読み書きできる人なら新しく学ぶ必要のあることはさほど多くありません。

サーバサイドWAF との比較

2016年5月と多少古いですが「React.js界隈の人に聞きたい」という、React に対してかなり批判的な記事が界隈でバズりました。JS を落とす一方で Python や Ruby を持ち上げているので、投稿者はサーバサイド開発にどっぷり浸かっている人であることが推察されます。中身は割りとありがちな内容なのですが、その返信記事のほうが私は納得がいくところがあったので、ここに引用したいと思います。

この辺りの一連の発言を見るに、多分React以前の前提がいろいろ違っています。単にJSやNodeやNPMやSPAやWeb APIといったフロントエンドの世界観に対して、興味がないどころか漠然とした不信があり、サーバ側でヘビーにHTMLを作って吐くスタイルを守り続けたい人なのだ、という印象を受けます。
https://anond.hatelabo.jp/20160522120724

Rails に代表される MVC アーキテクチャの考え方は、まずロジック的に必要な処理をいったん全部終わらせて、しかる後にそれを HTML に落とし込むというものです。最終出力はあくまで静的な HTML であるため、HTML をベースにそれに分岐やループのような機能を付加するための独自リテラルを追加されたテンプレートエンジンがフレームワークには用意されています。

いっぽう、React を理解するための最も重要なキーワードは「Virtual DOM」でも「Flux アーキテクチャ」でもなく、「コンポーネント指向」です。React では全てのアプリケーションはコンポーネントを組み合わせることによって作られます。
コンポーネントとは、構造見た目振る舞いがセットになった要素であり、コンポーネントの理想は個々がアプリケーションから切り離されても独立して動く、自己完結的なものです。

React のアプリケーションでは個々のコンポーネントが並列に処理され、準備が終わったコンポーネントから順次描画されていきます。MVC アーキテクチャとは対照的で、サーバサイド開発が長かった人が理解するためには、それまでのどっぷり浸かっていた思想から頭を切り替える必要があります。

また React のターゲットは今や Web アプリケーションだけではありません。React Native を使えば、iOS や Android、Windows アプリまでが作れてしまいます。React が考えるのは、あくまでコンポーネントをいかに生成するかです。React にとって HTML は Web アプリケーションをターゲットにした際の「コンポーネントを作成するための DSL」でしかありません。

サーバサイド WAF の最終生成物は静的な HTML であり、いかに綺麗な HTML が出力されるかが目的のテンプレートエンジンに慣れてしまっていると、これらを読み違います。その拒否反応の最たるものが「JSX キモい」であって、それゆえ彼らは React ではなく見た目がサーバサイド WAF 付属のテンプレートエンジンによく似た Vue などに流れていきがちなのでしょう。でも Vue ですら今はコンポーネント指向を採り入れているので、その理解レベルで Vue を使ってもうまく使えないのではないかと思います。

「ロジックとデザインの分離」 vs 「コンポーネント指向」

ここまでの説明を受け入れられた人でも、まだ現実の問題として業務に React(と JSX)を使うのは難しいと言われるかもしれません。その現実の問題とは「そうは言ってもデザイナーさんに JSX 書けんの? 書けないでしょ」ということです。

これまでのサーバサイドWAF が HTML テンプレートエンジンを採用していたのは、MVC アーキテクチャによる関心の分離という面もありますが、より現実的なソリューションとして「ロジックとデザインの分離」により View の部分を Web デザイナーに分業してもらえるということがあったと思います。

ERB や Haml といったテンプレート言語は、エンジニアでなくてもさほど習得が難しくないので、デザイナーに勉強してもらって、View ファイルを作ってもらっていたという現場が多かったと思います。しかし、JSX ではそうはいきません。「コンポーネントとは、構造と見た目と振る舞いがセットになった要素」と言いましたが、つまりコンポーネント指向ではロジックとデザインはむしろ混在するもので、分離は根源的に難しいのです。じゃあどうするか。

結論から言うと、デザイナーが HTML や CSS を書く時代は終わりました。それらはすでにフロントエンドエンジニアの領分です。私が知る限り、React を採用した SPA 開発の現場ではたいていそうなっていました。デザイナーさんたちはまずプロトタイピングツールでデザインプロトタイプを作り、その後に細かなマージンや正確な色を指定した Photoshop ファイルなどを渡し、渡されたフロントエンドエンジニアがそれに従って HTML や CSS を書くというフローです。

私も従来の分担に慣れていたので最初は戸惑いましたが、コンポーネント指向を推し進めると、自然とこのやり方に行き着くのでしょう。私のようにサーバサイド開発からフロントエンド開発に移ってきた人は苦労するでしょうが、がんばって勉強してくださいとしか言えません。最近のクラウド型デザインツール、ZeplinFigma では HTML や CSS のエクスポート機能があるので、それらを使っていればさほど大変ではないかと思います。

また近年の Web アプリケーションの複雑化に伴い、CSS のコード量も膨大なものになって、クラス等の名前をバッティングさせないために BEM や SMACS といった手法による管理の試みがなされてきましたが、コンポーネント指向の開発に則ればそんな煩わしい悩みからも開放されます。
CSS Modulesstyled-components といったライブラリを利用すれば、クラス名にランダムなハッシュをつけるなどして名前空間を自動的に閉じてくれるので便利です。

まとめ

  • テンプレート言語じゃないのにテンプレート言語と比べるな
  • コンポーネント指向の React を理解するには、MVC なサーバサイド WAF にどっぷり浸かった頭から切り替える必要がある
  • デザイナーさんには本来のデザインの業務に戻ってもらおう。マークアップはフロントエンドエンジニアの仕事

「JSX キモい」という意見に対して、React 歴1年足らずのエンジニアが反論してみました。JSX キモくない!

p.s.
それにつけても Qiita Markdown の Syntax Highlight は、いつになったら JSX 記法に対応するの? 当然ながら GitHub はとっくの昔に対応してる。