フロントエンドを楽にするために Qiitaを支えたい技術 at 時雨祭 ## About - HN: mizchi - Qiitaの方からきました(入社半年たったらしい) - Reactオジサンはそろそろ飽きてきた - Angularに興味が無いのでこっちにきた ## 最近の業務 - Kobito for Windows - Closedβ中: もうちょい待ってろ - お前らウェブエンジニアはWindows使わないのでβユーザー集めにくいんじゃ ## 省力モード - 一昨日がClosedβリリースだったんで察してくれ!!! - ついさっきまでバグフィックス用のビルド作ってた ## Qiitaを支える技術? - 4ヶ月ほどほぼソロ作業 - 正直カウボーイぎみ - OSSでドキュメントガンガン書いてカバー(したい) ## 業務から派生したOSS - [mizchi/arda](https://github.com/mizchi/arda "mizchi/arda") - Flux フレームワーク - [mizchi/stone-skin](https://github.com/mizchi/stone-skin "mizchi/stone-skin") - IndexedDb ラッパー - [mizchi/md2react](https://github.com/mizchi/md2react "mizchi/md2react") - MarkdownをReactElementに変換して高速プレビュー ## なぜOSSにするか - 自分の知識を「会社だけのドメイン」にしないため - モジュールごとにInとOutを明確に定義することで説明コスト/学習コストを下げる ## 今日のテーマ - フロントエンドを考えなおそうとした - フロントエンドじゃない人にフロントエンドエンジニアが何を考えてるのが伝えたい ## 前提 - とはいえ、そもそも自分(mizchi)はフロントエンドなのか? - JSは書けるといっていいと思う - Ruby/Python/Scala/C#あたりを書ける - CSSは最低限しか書けない - スキルがSPAの大規模設計に特化 - 偏った立場です 第一部: フロントエンドとは一体何だったのか ================================ ## フロントエンドとは主に何か - HTML - CSS - JavaScript ## フロントエンドエンジニアとは何か - 以上のものを使ってウェブサイトを構築する人 ## フロントエンドエンジニアとは何か:現実 - サーバーサイドエンジニアの片手間 - デザイナの片手間 - 他のエンジニアの職種より給与が一回り低い(100万円ほど)(個人の観測範囲です) - 正直、平均的なエンジニアリング能力はそう高くない ## フロントエンドスペシャリストとは何か - 一昔前はセキュリティスペシャリストと同義 - Web標準化コミュニティ - ASTレベルメタプログラマ - アプリケーションエンジニアと同じようなアーキテクト 注意: 綺麗に分類できるわけではない ## フロントエンドの業務 - コンポーネントの提供 - SPAのトータルデザイン ## VS サーバーサイド - 「取得系/更新系のAPIを決めよう」 - QiitaはJSONSchemaがあるのでTypeScriptの型定義を自動生成した - node.jsの場合は自分自身 ## VS マークアップ - 狭義のフロントエンドはこれを専門でやる人 - このボタン押したらこのclassをtoggleしてくれ ## VS デザイナ - 「この動きを実装してくれ」 - アニメーションは直接JS書いたほうが早い - Canvas/SVG ## 最近の「実践的な」フロントエンドに求められる技術は何か - node.jsでツールチェインを扱う能力 - 外部モジュールの管理 - npm/bower - browserify/webpack - アセットパイプライン構築 - gulp/grunt - sass/less - altjs - 各種アセットのminify - 中規模以上のコントロールフローの設計 ## 「最近のJSは学習コストが」 - 一定以上の規模がある場合、一人はアセットパイプライン担当がいないと厳しい - ファサードを用意する `gulp build:css` とか `gulp build:js` - gulp/grunt は秘伝のタレ化しやすいので気をつける # 第二部: Modern JavaScript ## ES6 - 最新仕様 - もうちょっとで仕様が固まる ## ES6の機能 - class - letによるレキシカルスコープ - yield generator - Promiseによる非同期 - 分割代入 要は普通の言語になろうとしている ## 影響を受けた言語 - Scheme(初期) - Python(ES3~mozilla期) - Ruby(ES5/NodeJSのエコシステム) - C#(ES6) ※mizchiの肌感覚です ## ES6使える? - ブラウザ側の実装はまだほとんど有効化されてない(もうちょい) - アセットパイプラインを構築すれば使える ## 現在の勢力図 - Babel: ES6準拠+α - TypeScript: ES6風+型+独自モジュール。最近GoogleのAtScriptが合流した - CoffeeScript: 主な機能がES6の仕様に吸い込まれて積極的に選ぶ理由は減った。Railsデフォルトなのが強い - Flowtype: 言語というより型アノテーションの静的Linter。夢はあるが現在制約が厳しすぎて使いづらい。 僕はオフサイドルールのある言語が好きなのでcoffee好きです ## Babel - 元6to5 - @sebmck が気合で作ってる - サブセットとしてJSX/flowtypeを実装 - ES7 async/awaitを先行実装 ## 一部のJavaScript書きがASTレベルプログラミングに走るわけ - 需要に対して進化が遅い言語制約に起因 - (変な歴史的負債はあるが)言語のコア機能はシンプル - 様々な言語をバックエンドに持つ人が集まるコミュニティ - Ruby/Python -> CoffeeScript - 静的型の需要 -> TypeScript / Flowtype - 関数型言語界隈のオモチャにされてきた ## ポリフィル文化 - ブラウザの差異をコミュニティが勝手に埋める - 言語表現に抵触しない限りはPolyfillで先行実装 - jQueryの歴史的役割は、主に0年代後半のブラウザ抽象化 ※言語制約によって実装できないものもある。DirectProxyなど。 ## 例: Babelのasync/await実装 - 式変形でCPS変換 - bable/polyfillという専用ポリフィルを通して実行 ## いろんな言語のWAFに言いたいこと - クライアントツールチェインがnode.js周辺でかなり充実している - そのせいで独自のアセット管理機構が邪魔になりつつある - とくにRailsのアセットパイプラインは危ないと感じている ## なにを選べばいいの - アセットパイプラインを組めるならbabelとかtypescript使えばいい - 組めないなら、最低限、新仕様とコンフリクトしないような技術スタックやポリフィルを選択する - 互換のポリフィル > 妙にショートカットされたシンタックスシュガー -------------------------------------------- # 第三部: アプリケーション設計について ## 最初にいいたいこと - SPAを片手間でやるのは無理です諦めろ ## 共通する枕詞 IN: 「JSONを渡すから」 OUT: 「ユーザーにかっこよく見せて」 or 「ユーザーの入力をリクエストで返して」 ## 昔(古典的AJAX) 入力(JSON) -> jQueryでDOMグチャッ -> 出力(XHR/Show) ## 今(SPA) 入力(JSON) -> 何かしら巨大なスタック -> 出力(XHR/Show) -> 入力(UI) -> やはり巨大なスタック -> ... ## 主な違い - ビューが生成されて捨てられるまでのライフサイクル - モダンブラウザのJSの速さ/レンダリングの速さ - 分厚い中間層の存在 - 通信頻度 ## jQueryはスクレイピング的API - 簡単なものを手早く作れる - 構造化が苦手 ## 結局UXのワーストケースとは何か - 共通化された画面の中で、似たような画面への遷移を繰り返すこと ## 「分厚い中間層」とは - コントローラ的なモノ? ## MVC概念の導入 - 基本的にはBackbone.js以降 - Component指向はAngularを経てWebComponentへ ## クライアントサイドにおけるMVCの需要 - そもそも完全にMVCをクライアントサイドに適用するのは無理 - (正確にはMVC2と言わないとJxckさんに怒られる) - Controller/UIがPubSubするのに適した方向へ - MVW(hatever) と呼んだりしていた ## Flux - React以降 - クライアント開発アプローチの富豪化(by @naoya) ## 富豪化? - 開発アプローチの富豪化であって実際の処理が富豪化してるわけではない - VirtualDOMは、ピュアなJSの速度にものを言わせて、実際にボトルネックになるDOMの状態遷移の手順を差分検出でスキップする - ボトルネックはDOM操作 ## モダンなJSのフレームワークの傾向 - 「JSの」速度向上に任せた富豪的プログラミング - 構造化のための手続きを内包 ## 現実 ## 覚えることがry - そもそもJSでやれることが増え、やらされることが増えて肥大化してる - 増えたぶんは覚えろ: 以上 ## フロントエンドエンジニアの目指すところ - サーバー/クライアントの境界面を設計する - 設計によって見通しをよくし、学習コストを抑える - 古いJSの悪習を引き継がない(DDDでいうSmartUI) ## 今までの経験 - KPIダッシュボードを作ってくれ - GoogleMapみたいなの作ってくれ - Excelみたいなの作ってくれ - リアルタイムで共有できるおえかきボード作ってくれ - Markdownエディタ作ってくれ ## 疎結合にする - 「このコンテナの中は自分が担当する」みたいな感じ - 入力/出力の規約を明文化する ## ライブラリにして渡す - READMEにこの関数だけ叩けば動くよ - ハコを指定されれば組み込むよ ## SPAで完全分業 - サーバーはREST APIだけくれ - クライアントの制御フローは任せろ - 漲ったJSerにとっては、ある程度以上の動きがあるならば**SPAのほうが実装コストが低い** - とはいえ、まだ漲ったJSerという人種が少ない ## SPAの懸念点 - Googleのページランクアルゴリズムが不明瞭 - window.onloadまで読んでる? - ちょっとまだ怖いですね # 第五部: Isomorphic ## 概要 - クライアントでもサーバーでも同じコードで動いたら楽ではという発想 ## Isomorphicを支える技術 - React(VirtualDOM)によるDOM抽象化 - browserifyによるnodeモジュールの抽象化 ## 一般Isomorphic - node.jsでクラサバのコードを共通化 - javascriptでサーバーとクライアントをすべて書く(Meteor等) - node.jsエンジニアに恩恵 ## 特殊Isomorphic - clojure/clojurescript - scala/scala.js - ocaml/js_of_ocaml - haskell/ghcjs これらを用いて 一番筋がいいのはclojureだと思っている ## サーバーサイドによるVirtualDOM - たとえば react/react-rails - ReactElementをサーバーサイドレンダリング - クライアントサイドで、RedrawをスキップしてReactElementへのハンドラの注入を引き継ぐ ## サーバーサイドによる抽象化の為に - テンプレートエンジンを共通化する必要 - JSから渡されるハンドラ名をテンプレートエンジンに書くようになる - サーバーサイドが内包したV8エンジンでユニットテストできるようになる ## 今から使える? - パラダイム変わりすぎ - まだ時間とライブラリが足りない - みんな頼む # これが一番楽だと思います 将来的にはな!