フロントエンドのみなさん消耗してますか?

竹馬光太郎氏:よろしくお願いします。ご紹介にあった通り、こういうタイトルで発表させていただきます。自己紹介はあんまりやる気がないんですけど(笑)、いろいろとインターネットでお騒がせしております。@mizchiです。

(会場笑)

前職は今までゲームのクライアントを作ったり、教育のオーサリングツール作ったり、Qiitaのフロントエンドの部分の開発、あとKobito作ったりしていました。

去年の4月からフリーランスとして仕事を承っております。忙しくてあんまり仕事を受けられないんですけど(笑)、やっていることとしてはNode.jsやSPAをよく作っていて、今回は資料を作ってきました。自分が知っているものに偏りがちで、言及範囲が「あれがない」「これがない」「お前あれも知らねぇのか」みたいなこと言われるかもしれないんですけど、ちょっとそういうのは扱えないんですが、そのへんご了承くださいという感じですね。

ここから本題なんですが、フロントエンドのみなさん消耗してますか?

(会場笑)

いろいろな消耗が現場にあると思うんですよ。これは僕が最近消耗したものを適当に書いてきたんですけど(笑)、みなさんそんなに変わらないと思うんですよね。

jQueryとIE11がくそでかいテーマとして生き残っていて、SEOでサーバーサイドレンダリングする? 本当に? とか。

left-pad問題があったり、webpack.config.jpの量がすごくあったり、最近なかなか熱いのがBackbone.Routerとreact-router、このあたりは最高に盛り上がりますよね、書いていると(笑)。

僕が1番気に入っているフレーズが、The Elder Scrolls of Gulpfile (注:Bethesda のRPG, The Elder Scrolls シリーズ)というのがあるんですけど、これはあるゲームをやっている人にはわかりますね。見ると失明するスクロールというのがあって(笑)、そういう属人化してしまうニュアンスです。

腐る部分と腐らない部分の目利き

何が言いたいかと言うと、今回はみなさん今までいろいろフロントエンドを書いてきて、「あいつら何をやってるんだ?」と思われがちだったので、アーキテクチャの変遷を整理して、変化に強い設計とは何か、これから我々はどこに向かおうとしているのか、という部分を学んで、腐る部分、腐らない部分の目利きができるようになってほしいなと思っています。

僕ができているかもちょっと怪しいんですけど、それが少しでもできるようになろうということですね。やっていきましょう。

お題としては今までのフレームワークどんなのがあったかなというのと、ちょっと過去を振り返って、今何しているか、未来は何をしていそうか? そういう話をしたあとに、どうやったら今の手元の腐ったコードを未来に追従できるのかみたいな話をしようと思います。

フレームワークの振り返りという話なんですけど、こういう図を作ってきました。「俺のフレームワークこれがないぞ」「あれがないぞ」という話はちょっと今回は受け付けられないんですけれども(笑)。

超大昔、1990年代末くらいにJavaScriptみたいなものをブレンダン・アイクが作ってから、AJAXみたいなことを言われ出したのが2004、2005年くらいかな。

GmailやGoogleマップ、「JavaScriptは複雑なものが作れるようになったね」みたいな。「じゃあ作ってみようか」と言って、AJAXみたいな概念でガリガリとアプリケーションを我々は作り始めたような気がするんですけど、正確に言うと、僕は高校生だったのでぜんぜんやってはいないので、聞きかじりです。

昔jQuery MobileやjQueryUIがありましたよね。それとはちょっと違う系統でExt JS、Sencha、そのまえにYUIというのがあったと思うんですけど、Dojo ToolkitやMochiKitはちょっと省いてしまいましたが、そういうものがありました。

そのあと2010年くらいにHTML5みたいなことが騒がれ始めて、理由としてはAppleがFlash潰すみたいなことを言い始めて(笑)。「じゃあ俺たちはやっぱりJavaScriptで複雑なものを作らないといけない」となってからBackboneみたいなものでクライアントサイドMVCみたいな時代が始まった。

始まったあとに、KnockoutやAngularのv1でデータバインディングみたいなことをし始めて、Vue、React、Reduxがきて、これを便宜的に3つに分割していて、下に書いてあるんですけど、テンプレーティングの時代。これは僕が作った用語なので大雑把な分類なんですけど、テンプレートを書くようになった時代、データバインディングをするようになった時代、あとFluxやObservableの時代と分類しています。

かつてフロントエンドは何をしていたか

太古、我々フロントエンドは何をしていたかと言うと、木があって、bodyがあって、DOMツリー、headerがあって、contentがあって、itemList、何のリストかわかりませんが、ここにappendChildとか書いていました。

jQueryのselect.appendでもいいんですけど、こんなことをしてたはずです。

手で木を書き換えていた時代があって、正直「時代」と言っても、フロントエンド専業以外ではこれがまだ標準です。なぜならIE6というのが支配的な時代を作っていて、2004年くらいからいまだになかなか死んでないからだと思います。

これがすごく不安定なDOM API、IEに限らずFirefoxもそんなに標準化されていたかというとちょっと怪しくて、そのへんの不安定なAPIをjQueryが吸収していたという時代がありましたね。

そもそも複雑なことはしないはずっていう前提もあって、こういう時代が長く続いた結果、これが支配的な価値観になったまま今に至っているみたいなところがあります。

このあとにテンプレートを書く時代がやってきたと思っています。

今までcontentの下にitemListがあってa、bを生成する。このa、bの木を自分で手で書いてた時代から、「itemList以下は一括でテンプレート書いて生成すればいいじゃん」というのでテンプレートを別途宣言してcontent以下にはめ込む。

innerHTMLみたいなかたちで生成したものをドーンとはめる。そのあとイベントハンドラをデリゲートするみたいなことをやっていたはずです。Backboneが出てきたときにこういうことをやり始めて、コンポーネントみたいな概念がここで生まれていった気がしますね。

HTMLの初期生成がクライアント側に移動してきた。最初はサーバーで生成したセレクタ規約みたいなものに対してjQuery UIやセレクタ規約に従ったものをガッチャンと動かしてたんですけど、それをクライアント側でアトミックに生成するのでメンテナンス性が良くなった反面、クライアントとサーバーで同じものを生成したり、SEOの問題が発生したりしてきました。

当時使ってたものとしてmustache、handlebars、underscore.templateを使っていたと。あと幻のjQuery Templateというのがあったんですけど、標準化されずに葬られました。

データバインディングの時代へ

それより先の時代、データバインディングの時代と呼んでいるんですけど、書くものはテンプレートで一緒です。このときになるとコンポーネントみたいな意識になるんですよね。

擬似コードなのでちゃんとしたコードじゃないんですけど、コンポーネントをcontentに対してrenderするとappインスタンスが入って、app.updateすると、ここのバリューがa,bだったのがc,dに書き換わるみたいなことをやり始めたと。これは何かと言うとKnockoutやAngularJS、Vue.js、僕の記憶が正しければbackbone.stickitというBackboneのヘルパーがあって、そういうものでやっていたと思うんですけれども。

この時期になると、もともとテンプレートはサーバーサイドの文字列の抽象のコピーだったから文字列を展開しただけのものだったはずが、今は状態を持つ木構造を展開している。さらにその構造をフレームワークが密に知っているという状態になります。

これになると完全にサーバーサイドで同じ抽象を表現できなくなります。部分的な書き換えやリスト展開を効率的に行うときのパフォーマンス上の理由ですね。僕の記憶が正しければ、AngularJSが最初に出現したときってAngularのテンプレートのデータバインディングの部分だけ抜き出して小さくてかっこいいみたいな感じで出てきたと思います。AngularJSの0.x系? 大昔に自分が書いた記事にそう書いてあったのでそうなんだと思いますけど(笑)。

現代、我々は何をしているんだと言うと、我々って言うとちょっと主語がでかいですね。さっきから。

(会場笑)

この場にフロントエンドの人しかないと思ってしゃべっているので、主語がでかくなっちゃうんです。

現在は何の時代なのか?

現在、Client Side MVCという言葉が2010年ごろ流行っていたと思います。これは死にました。なぜか? Client Side MVC、つまり……もっと言ってしまうとBackboneの実装のことをClient Side MVCと言うことが多かったんです。

これをやり始めたJeremy Ashkenas、CoffeeScriptやBackbone、underscoreの作者はRailsエンジニア的な世界観が強くて、Railsの抽象をクライアントに持って来ようとしていて、BackboneモデルというのはRailsのモデルとほぼ1対1に対応させようとしていて、厳密に対応はしないんだけどデータをプロキシする程度としては対応しているし、クライアントルーターやその他諸々の概念もそうなんだけど、クライアントとサーバーで必要な画面の抽象もそうしていたんだけど、結果としてはやっぱ別物だったという話になりました。

あとそもそもサーバーサイドのMVC、RailsやCakePHPと言われているものはMVC2と言われているちょっと奇形なMVCなんですけど、「本来のMVCにもっと立ち返ろう」とかそもそもここまで来ると、もはやGUIに近い抽象なのでGUIのほうから知見を持ってこようというので、これらの概念が再構築されていった。

今は僕はFluxとObservableの時代だと思っていて、Event、State、Viewみたいな構造に分割されて、EventSource、Eventをパブリッシュしてくるなにか塊と、それをsubscribeするものが分割されています。これらの知見ってFRP、Functional reactive programmingみたいな方法から由来していて、有名なのはElmですね。ElmってReduxのパクリ元になっているというのが有名だと思うんですけど、Haskellっぽいreactive programming環境なんですが、あと他にRxやMS系の知見などとかある言語でした。

今回注意しないといけないんですけど、Angularって僕はObservableのフレームワークだと思っていて。あれデータバインディングのように見えるんですけど、裏側はObservableを購読するというかたちになっています。

Rxの世界観

Rxの世界観はどうなっているかですね。

ObservableのABCというのがあったら、そもそもObservableは何かと言うと、クリックイベントをパブリッシュしてくるdispatcherみたいなもの、キーボードイベント、ティッカーイベント、それを別のObservableがRxオペレーターを使ってガチャガチャしていきます。それが梱包したデータをViewXみたいなのがsubscribeしてデータを受け取って、そのObservableのスナップショットがバインドされるます。

ViewYは直接購読してるんですけど、そいういうもあるよねみたいな感じです。Reduxはどうなのかと言うと、Observable A,B,Cが全部、MiddlewaerとReducerって書いてるところがいわゆるStoreと言われているところなんですけど。まあ、Fluxですね。

Middlewaerに一旦すべてのイベントがガーって通ってしまって、Reducerがすべてのアクションを1個ずつ解釈してReducer0、Reducer1がちょっとずつ更新される。今どういうスナップショットかというのをViewXYにmapStateToPropsみたいな関数でさらに切り出して配っていくというのがReduxです。

なんでこういう考え方になるかと言うと、Componentの裏側に隠れたStateは基本的に存在しちゃいけない、表に見えるEventからのみいろいろカリキュレートして状態を作る。そうすると状態というものが存在しないはず。

前の状態というのはあるんですけど、Reducerって前の状態とアクションを1個取って次の一歩に進むというものなので、状態というものは基本的に排除されていく。スナップショットだけを扱う。そのある時点でのスナップショットをViewは表現しているというかたちですね。

これはちょっとおまけなんですけど、ReduxというのはRxの概念的なサブセットだと思っていて、これわかる人にはわかるんですけど、すべてのアクション、ObservableをRx.Observable.mergeしてRx.Observable.scanしたら、それは基本的にReduxです。