2016年にJavaScriptを学ぶとこんな感じ
このストーリーは、Circle CIに投稿された”It’s the future”というストーリーにインスパイアされたものです。オリジナルはこちら。ここに書いたことは一つの意見というだけで、他のJavaScriptフレームワークもそうですが、過剰に真に受けないでください。このストーリーを執筆中に新たなJavaScriptフレームワークは作成されていません。
やあ、今新しいプロジェクトをやっているんだけど、実はここ数年ウェブのコード書いていなくてさ、しかも以前とは少し変わったとも聞いているよ。それで君が一番この辺でウェブ開発に詳しいって聞いたんだけど?
-フロントエンドエンジニア、といったほうが正しいが…まあ、俺なら間違いない。俺のは2016年のウェブだからな。ビジュアライゼーション、ミュージックプレイヤー、サッカーをするドローン等々。JsConfとReactConfから帰ってきたばかりだからウェブ開発の最新テクノロジーも知っている。
いいね。今ユーザの最新のアクティビティを表示するページを作ろうとしていて、それでRESTエンドポイントからデータを取得してフィルタ可能なテーブル内に表示させて、サーバ側で何か変更があったら更新させる、みたいなことがやりたいんだ。それでデータの取得にjQueryを使ってデータをページ上に表示させようかと考えていたんだけど。
-オーマイゴッド、だめだ、jQueryなんてもう誰も使っていない。Reactを試したほうがいい。2016年だからな。
ああ、なるほど。Reactって何だい?
-Facebookの中の連中によって作られた超クールなライブラリだ。ビューの変更の制御が簡単になったことでアプリケーションのコントロールとパフォーマンスが飛躍的に上がるんだ。
いいね。サーバから取得したデータを表示するためにReactを使うことはできる?
-ああ、でもまずはReactとReact DOMのライブラリをウェブページに追加する必要がある。
待って、なぜ2つのライブラリなんだい?
-ひとつは実際のライブラリ、もうひとつはDOMを操作するためのもので、それによってJSXで記述することができるようになる。
JSX?JSXって?
-JSXはJavaScriptの構文拡張で、XMLとほとんど同じだ。DOMを記述するための別の方法のようなものだ、HTMLをもっと良くしたものと考えればいい。
HTMLじゃいけないのかい?
-2016年だからな。誰もHTMLを直接コーディングするやつなんていない。
なるほど。とにかくこの2つのライブラリを導入すればReactが使えるようになるわけだね?
-ちょっと違うな。Babelを追加する必要があって、その後使えるようになるんだ。
別のライブラリ?Babelって何?
-Babelはトランスパイラのことだ。これを使えばどんなバージョンのJavaScriptコードを書いたとしても特定のバージョンにコンパイルすることができる。つまり、君がまだES5を使ってるのならReactJSを使うのにBabelを使う必要があるってことだ。そして現実を見ようぜ、ほかのクールキッズ達はES2016+を使ってる。
ES5? ES2016+?今のでよくわからなくなったよ。 ES5とES2016+って何?
-ES5はECMAScript 5の略だ。現在のほとんどのブラウザに実装されてからほとんどのエンジニアがターゲットにしているエディションだ。
ECMAScript?
-そうだ。つまりJavaScriptは1995年に最初にリリースされたときはLivescriptという名称で、Netscape Navigator上でしか動作しなかった。そして1999年にスタンダードなJavaScriptが確立されたわけだが、当時はとっ散らかった状態だった。それが今はありがたいことに7つのエディションにまとまっているんだ。
7つのエディション…なるほど。で、ES5とES2016 +というのは?
-それぞれ5番目と7番目のエディションのことだ。
6番目はどうしたの?
-ES6のことか?ああつまり、それぞれのエディションはその前のエディションのスーパーセットなのさ。だからもし君がES2016+を使っているなら、それ以前のバージョンの全ての機能を使っていることになる。
なるほど。で何故ES6じゃなくてその上のES2016+を使うの?
-まあ、ES6を使うこともできる、でもasyncやawaitみたいなクールな機能を使うためにはES2016+を使う必要がある。それか適切な制御フローのための非同期呼び出しをブロックするためにES6とコルーチンを使うかだ。
今君が言った意味が全くわからないよ…いろんな名前が出てきて混乱している。いいかい僕のやりたいことはサーバからデータをロードするということで、CDNからjQueryをインクルードしてAJAXでデータを取ってくれば前はできたんだ。何でこのやり方じゃだめなの?
-2016年だからな。誰もjQueryなんて使わないんだ、とんでもないスパゲッティコードの束ができるだけだからな。みんなそれを知ってるのさ。
なるほど…じゃあ新しいやり方では3つのライブラリをロードすると。そうすればサーバからデータを取り出してHTMLテーブルに表示させることができる。
-まあ、3つのライブラリをインクルードするんだが、モジュールマネージャで1つのファイルに纏めてからロードさせるんだ。
はあ。モジュールマネージャとは?
-その定義は環境によって異なるな、でもウェブ界隈ではAMDまたはCommonJSモジュールをサポートするもの全てを指す。
な、なるほど。でAMDとCommonJSとは…?
-定義さ。複数のJavaScriptライブラリとクラスをインタラクトさせる記述方法とも言う。exportやrequireは知っているよな?AMDまたはCommonJS APIに則って複数のJavaScriptファイルを書いて、Browserify等でそれらをバンドルするわけだ。
ああ、それは理にかなっている、と思うよ。。Browserifyって?
-CommonJSで記述された依存関係をブラウザ上で動作するファイルにバンドルすることができるツールさ。みんながnpmレジストリにこれらの依存関係を公開することから生まれたツールだ。
npmレジストリ?
-スマートな連中がコードや依存関係をモジュールとして配置した巨大なパブリックレジストリのことだ。
CDNみたいなもの?
-少し違うな。誰でもライブラリをパブリッシュしたりダウンロードしたりできる中央集権化されたデータベースと言った方が正しいな。開発のためにローカルでそのライブラリを使って、それを今度はCDNにアップロードすることもできる。
ああBowerみたいなものだね!
-ああ、でも今は2016年だからな。誰もBowerなんて使わない。
なるほど…つまりライブラリをnpmからダウンロードする必要があると。それでその後は?
-そうだな。例えばReactを使いたいなら、Reactモジュールをダウンロードしてコードにインポートする。ポピュラーなJavaScriptライブラリは大体こんな感じだ。
Angularと同じだね!
-Angularはかなり2015年だが、まあそうだな。Angularでもいいが俺が言ってるのはVueJSとかRxJSとかその他のクールな2016年ライブラリのことだ。知りたいか?
まずはReactにしよう…今大量のことを学んでるから。となるとこのnpmからReactを持ってきてBrowserifyというのを使えば良いと?
-ああ。
沢山の依存関係を結びつけてバンドルするにはかなり複雑過ぎない?
-ああ、Browserifyを自動化するためにGruntやGulpやBroccoliを使う理由はそこにある。Mimosaでも良い。
Grunt?Gulp?Broccoli?Mimosa?一体何を話しているんだい?
-タスクマネージャだ。まあもうあまり人気はないがな。俺も2015年とかにはよく使っていた。そのあとMakefilesで、今はWebpackを使っている。
Makefile?CとかC++のプロジェクトで使われるものだとばかり思っていたよ。
-ああ、でもウェブ界隈の連中は物事を複雑化して結局基本に立ち返るのが好きなんだ。こういうことを毎年繰り返してて、多分待っていれば、1,2年後には俺達はウェブでアセンブリを使うようになるだろう。
はあ…さっきのWebpackと言うものは?
-ブラウザ用のもう一つのモジュールマネージャだ、タスクランナーのようなものでもある。Browserifyをベターにしたバージョンみたいなものだ。
ああそう…何故ベターなの?
-まあ、ベターではないかもしれないが、依存関係がどのように結びつくべきかという点でさらに自己主張ができる。WebpackならCommonJSのやつだけじゃなくて、例えばそうだなネイティブES6がサポートされたモジュールみたいな異なるモジュールマネージャを使うことができる。
このCommonJSとかES6とかいうのでものすごい混乱してきたよ。
-みんなそうさ、でも君はもうSystemJSについては気にしなくていい。
ジーザス、今度は別のjsが出てきた。オーケーじゃあこのSystemJSというのは何だい?
-そうだな、BrowserifyやWebpack 1.xが一つの巨大なファイルを作るのと違って、SystemJSは複数のファイルに記述された複数のモジュールを紐付ける動的モジュールローダーなのさ。
待って、でも僕らがやりたいのはライブラリをビルドして一つの大きなファイルを作ってそれをロードすることだろ!?
- ああ、でもHTTP/2がもうすぐ来るからそうなると複数のHTTPリクエストの方が好ましいのさ。
ということはReactのオリジナルの3つのライブラリを追加すればいいんじゃない?
-そうでもない。というのは、それらをCDNを使って外部からロードすることもできるが、そうした場合でもBabelはインクルードする必要があるだろう。
はあ…でそれはあんまり良くないんでしょ?
-ああ、Babel全体のコアをインクルードすることになるだろうが、本番環境でそれは効率が良くない。本番環境はゆで卵のレシピのように簡単にサタンを召喚するための儀式がいつでもできるようにプロジェクトを準備して動かしておく必要がある。アセットは少なくして、難読化して、その上でcssをインラインして、スクリプトを引き伸ばして…
わかった、もうわかったよ。じゃあCDNに直接ライブラリを配置できないなら、どうやってやればいいの?
-Webpack + SystemJS + BabelのコンボでTypescriptからトランスパイルするのさ。
Typescript?JavaScriptでコーディングするのかと思ってたよ!
-TypescriptはJavaScriptだ、JavaScriptのスーパーセット、もっと厳密にはバージョンES6のJavaScriptだ。さっき話した6番目のバージョンのことは憶えているか?
ES2016+がES6のスーパーセットなんじゃないの!?なんでTypescriptが必要なの?
-まあ、それを使えば俺達はJavaScriptを静的型付け言語として使えるようになり、ランタイムエラーを減らせるのさ。2016年だからな、いくつかの型をJavaScriptに入れておいたほうがいい。
Typescriptがまさにそれだと。
-Flowもそうだ、Typescriptがコンパイルされる必要があるJavaScriptのスーパーセットである一方で、Flowはタイピングしかチェックしないんだけどな。
はあ…それでFlowとは?
-Facebookのエンジニアが作った静的タイプチェッカーだ。彼らはそれをOCamlの中にコードしたんだ、関数型プログラミングは最高だからな。
OCaml?関数型プログラミング?
-現代のクールキッズが使うやつだ、わかるだろ、2016年だからな。関数型プログラミングとか高次機能とかカリー化とかピュアファンクションとかだ。
全くわけがわからない。
-みんな最初はそうさ。いいか、関数型プログラミングはOOPよりも優れていてそれこそが俺らが2016年に使うべきものだ。
待って、僕は大学でOOPを学んだよ。OOPって良いんじゃなかったっけ?
-JavaがOracleに買収されるまではな。つまり、OOPは当時は良かったし、今でも使われている、でも今や状態を変更することは赤ちゃんを蹴ることと等しいということは周知の事実で、だからみんなイミュータブルオブジェクトと関数型プログラミングに移行しているのさ。Haskellのやつらは何年もそれを提唱していて、俺はElmの連中と一緒にやろうとは思わなかった。でもラッキーなことにウェブでは今Ramdaみたいなライブラリができたおかげで俺たちはプレーンのJavaScriptで関数型プログラミングを書くことができるのさ。
君もしかしてわざと次々と新しい名前だしてないよね?一体Ramndaって何だい?
-違うRamdaだ。Lambdaみたいに。デイビッド・チェンバースのライブラリさ?
デイビッド誰?
-デイビッド・チェンバース。クールな奴さ。彼は意地の悪いクーデターゲームをプレイする。 Ramdaのコントリビューターの1人でもある。関数型プログラミングをマジで学びたいならエリック・メイヤーもチェックしておいたほうがいい。
それでエリック・メイヤーというのは...?
-関数型プログラミングを作った1人だ。最高の男だよ。趣味の悪いカラーシャツを着ながらアジャイルをボロクソに言う彼のプレゼン動画が沢山あるから見てみるといい。あとチェックしておくべきなのはTj、ジャシュ・ケナス、シンドラ・ソーラス、ポール・アイリッシュ、アディ・オスマニ…
オーケー、その辺で十分だよ。でもサーバからデータをフェッチして(取り出して)表示するには今まで教えてもらったことは複雑だし不必要じゃない?とにかく動的データでテーブルを作成するのにさっきの人々について学ぶ必要が無いのは間違いないよ。Reactに戻ろう。Reactを使ってサーバからデータをフェッチするにはどうすれば良いの?
-そうだな、実際はReactを使ってフェッチはしない。Reactを使ってやるのはデータの表示だけだ。
もうだめだ。。じゃあデータをフェッチするには何を使うの?
-Fetchを使うのさ。
何だって?データをフェッチするのにFetchを使う?誰だいそんな名前にしたのは。
-だよな?Fetchはサーバに対してXMLHttpRequestsを実行するためのネイティブ実装のことだ。
はあ、つまりAJAXだね。
-AJAXはXMLHttpRequestsを使用した一例に過ぎない。Fetchを使うことでpromiseオブジェクトを基本としたAJAXを使えるようになり、コールバック地獄を避けることができるのさ。
コールバック地獄?
-ああ。例えばサーバに対して非同期リクエストをする度に、サーバからの応答を待たなければならない、そしてそのために関数の中に関数を入れることになって、俺達はこれを地獄からのコールバックピラミッド読んでいる。
な、なるほど。それでpromiseオブジェクトがそれを解決すると?
-そのとおりだ。promiseオブジェクトを通してコールバックを操作することにより、コードの記述、モック、テストが簡単になる。さらに一度に複数のリクエストを送信して全てがロードされるまで待つことも簡単だ。
そしてそれがFetchでできると?
-ああ、でもこれはユーザが人気の無いブラウザを利用している場合に限るがな。それ以外に対応するためにはfetch-polyfill、Request、Bluebird、またはAxiosのいずれかをインクルードする必要がある。
一体どれくらいのライブラリを知る必要があるんだい?全部でいくつあるの?
-JavaScriptだからな。何千というライブラリが存在して、その全てが同じ目的のために使用される。俺達はライブラリを知っていて、そしてその中のベストなライブラリを持っている。俺たちのライブラリは超巨大で、時々その中にガイ・フィエリの写真を入れて使っている。
今ガイ・フィエリって言わなかった?もうそろそろ終わりにしよう。そのBluebirdとかRequestとかAxiosというライブラリは何をするものなの?
-これらはXMLHttpRequestsを実行してpromiseオブジェクトを返すためのライブラリさ。
jQueryを使ったAJAXも同じようにpromiseオブジェクトを返さなかった?
-俺たちはもう「J」という言葉は使わないんだ。2016年だからな。Fetchを使って、ブラウザ上にそれがなかったらpolyfillか、またはBlubird、Request、Axiosを代わりに使うのさ。そして非同期関数内でawaitを使ってpromiseオブジェクトを制御すれば、それだけで適切な制御フローの出来上がりさ。
君がawaitって言葉を使ったのは3回目だけど僕はそれが何であるか全くわかっていないよ。
-Awaitを使えば非同期処理をブロックすることができる、それによってデータをフェッチしている最中にも制御することができ、また全体的にコードの可読性も向上させることができる。最高なのは、君が気にすればよいことがBabelのstage-3プリセットを追加すること、またはsyntax-async-functionとtransform-async-to-generator プラグインを使うことだけだということだ。
狂気としか言いようがない。
-いいや、awaitを使うためにTypescriptのコードをプリコンパイルしてそれをBabelでトランスパイルする必要があるという事実のほうが狂気さ。
え?これってTypescriptに含まれていないの?
-次のバージョンでは含まれる予定だが、現時点のバージョン1.7はES6しかターゲットにしていない。だからもしブラウザでawaitを使いたいなら、まずTypescriptのコードをES6をターゲットにしてコンパイルして、次にBabelしてES5をターゲットにするのさ。
もう何と言えば良いのかわからない。
-いいか、簡単さ。全てをTypescriptでコードするんだ。次にFetchを使う全てのモジュールをES6にコンパイルして、stage-3プリセットのBabelでトランスパイルして、SystemJSと一緒にロードする。Fetchを持っていないのであれば、polyfillする。またはBluebirdかRequestかAxiosを使う。そしてawaitをつかって全てのpromiseオブジェクトを制御する。
僕たちの「簡単」の定義は全く別物のようだね。それでそれらを使って最終的にReactで表示することができるんだね?
-君のアプリケーションは状態の変更は制御するのか?
うーん、やらないと思う。やりたいのはデータを表示することだからね。
- 助かった。そうでなければ俺は君にFluxと、FlummoxやAltやFluxibleのような実装を説明しなきゃならなかった。どちらにしろReduxは使うべきだろう。
もう沢山だ。何度も言っているけど僕がやりたいのはデータを表示する、それだけなんだ。
-データを表示したいだけならReactは必要無いだろう。テンプレートエンジンで十分だ。
からかってるの?そんなに面白い?友人や家族にもこんな風に振る舞うの?
-俺はただ君に使えそうなものを教えているだけだよ。
やめてくれ。もうたくさんだ。
-つまり、もしテンプレートエンジンだけを使う場合でも、俺だったらTypescript + SystemJS + Bebelコンボは使うだろうな。
僕がやりたいのは一つのページにデータを表示するということだけで、初代モータルコンバットのサブ・ゼロの究極神拳を実行したいわけじゃない。もうどのテンプレートエンジンを使用すればよいのかだけ教えてよ、それを使ってやってみるから。
-沢山あるよ。どのテンプレートエンジンなら使ったことがある?
うーん、名前は覚えてないよ。かなり前の話だもの。
-jTemplates? jQote?PURE?
うーん、違うなあ。他には?
-Transparency? JSRender? MarkupJS? それともKnockoutJS?2ウェイ・バインディングの。
他には?
-PlatesJS? jQuery-tmpl?それともHandlebars?これはまだ使っているやつもいる。
そんな感じだったと思う。その最後のに似ているの他にない?
-Mustache、underscore?正直lodashは今でも使われていると思うが、これらは何というか2014年だ。
うーん、、多分当時は新しい方だったんだけどね。
-Jade? DustJS?
いいや。
-DotJS? EJS?
いいや。
-Nunjucks? ECT?
いいや。
-CoffeeScriptの構文を好きなやつなんていないから、違うな。Jadeは?
いいや、Jadeはさっき出てきたよ。
-つまりPugだ。Jadeなんだけど。Jadeは今はPugだ。
はあ。いいや。思い出せない。君ならどれにするの?
-恐らくES6ネイティブのテンプレート文字列だな。
僕に当てさせて。それはES6が必要で、
-そう。
そしてそれは使っているブラウザによってはBabelが必要で、
-そう。
そして、もしコアライブラリ全体を追加せずにインクルードしたい場合は、npmから一つのモジュールとしてそれをロードする必要があって、
-そう。
そして、Browserify、またはWepback、またはその他殆どの場合はSystemJSが必要で、
-そう。
そして、Webpackでない場合は、理想的にはタスクランナーで管理されるべきで、
-そう。
でも、関数型プログラミングと静的型付け言語を使用するべきだから、まずTypescriptまたはFlow等を加える必要があって、
-そう。
そしてもしawaitを使いたいならそれをBabelに送ると。
-そう。
そうするとFetchやpromiseオブジェクトや制御フローなどいろんなことを使えて、
-Safariとかはサポートされていないから、その場合はFetchをpolyfillするのを忘れるなよ。
いいかい。もううんざりだ。うんざり。ウェブもJavaScriptもうんざり。
-いいさ。どうせ数年後には俺達はみんなElmかWeAssemblyを使っているだろうからな。
バックエンドに戻ることにするよ。こんなに多くの変更やバージョンやエディションやコンパイラやトランスパイラを僕には扱えないよ。こんなのにずっとついていくなんて考えられないよ、JavaScriptのコミュニティは狂ってる。
-わかった。じゃあPythonのコミュニティを試してみるといい。
どうして?
-Python 3のこと聞いたことある?