この半年で、node、ES6、React、Babel、Atomエディタ界隈に結構な変化があり、
JavaScriptではES6+とReact-JSXからES5へのトランスパイルが標準に / ATOMエディタで最速環境構築 厳選パッケージ 3 + 3 2015年夏バージョン
で紹介したAtomエディタの環境構築の方法で、いま自身の環境をアップデートするにやると普通にコケてしまう、いろいろ不具合が出るので更新。
ES、JSXトランスパイラのデファクトスタンダードであるBabel公式サイトの掲示板で、Babel開発者とやりとりした情報をベースに自分自身忘れないようにメモを兼ねて情報共有しておきます。
https://discuss.babeljs.io/t/error-parsing-jsx-with-global-installation-babel-preset-react/59
JavaScriptは本格的にECMASCript 6(ES6)へ移行した
実際使い込めば使い込むほどES6は強力。
2013年に、
調査: もっとも表現力に富んだ汎用プログラム言語は Clojure,CoffeeScript,Haskellというのがあった。
CoffeeScript (#6) は JavaScript (#51) よりもはるかに高い表現力を示している。事実上,すべての言語の中での最高値である。
一貫性においても CoffeeScript が変わらず No.1 であるが,4番目の Clojure と比較した IQR (interquartile range,,四分位範囲) の差異はわずか23LOC/コミットに過ぎない。
というように、CoffeeScriptの表現力はプログラム言語の中でも際立っており、素のJavaScriptは比較すると随分と劣っていた。
しかしそのJavaScriptもまさにそのCoffeeScriptが獲得していた表現力を吸収するようにES6となり、標準化は正義ということで、CoffeeScriptの役割は終わったように思う。
JavaScriptはES6になり、もっとも表現力の高い言語に進化したと言っても過言でないと思うし、実際コーディングしていて関数型プログラミングの特性が発揮するように表現力が高まった実感がある。
以下、
Trending repositories
https://github.com/trending?l=javascript&since=monthly
のトレンドも踏まえる。
Node.js
Node.jsの運営問題による開発の遅れから分裂していたio.jsはめでたく、Node.jsの体制を修正しながら本家に再統合。
Node v4.0.0となり、
矢継ぎ早に、Node v5.0.0のラインもリリースされた。
io.jsをマージ、ES6サポートを実現した「Node.js 4.0」リリース
https://nodejs.org/en/docs/es6/
ようやく、NodeでもECMASCript 6(ES6)が本格的にサポート開始。
つけくわえておくと、
https://github.com/Automattic/wp-calypso
というプロジェクトもトレンドにあるが、
Calypso is the new WordPress.com front-end
ということで、WordPressのコンテンツエンジンもPHPからNodeベースになるのか、なったのか詳しいことはまったく調べていないので、あまり良く知らない。
ReactはDOMと分離された
ReactはあいかわらずクライアントサイドのUIで確固たる位置を占めており勢力を拡大しているように見える。
Reactは、もはやHTML専用のUIエンジンではない、ということで、
React DOMは本体Reactから分離された。
http://facebook.github.io/react/blog/2015/10/07/react-v0.14.html
React has nothing to do with browsers or the DOM.
ReactはブラウザともDOMとも関係ない
Major changes
Two Packages: React and React DOM
As we look at packages like react-native, react-art, react-canvas, and react-three, it has become clear that the beauty and essence of React has nothing to do with browsers or the DOM.To make this more clear and to make it easier to build more environments that React can render to, we’re splitting the main react package into two: react and react-dom. This paves the way to writing components that can be shared between the web version of React and React Native. We don’t expect all the code in an app to be shared, but we want to be able to share the components that do behave the same across platforms.
つまり、2014-2015年に、一部、日本国内で、Reactとは仮想DOMのことである、というような喧伝がなされていたが、実は仮想DOMは本質ではなく、DOMが仮想化されている大元となる理由、コンポーネント指向、至高、つまりUIがオブジェクト指向ではなく関数型プログラミングを体現していることがより明確になった。
Functional Stateless Components in React 0.14
https://medium.com/@joshblack/stateless-components-in-react-0-14-f9798f8b992d#.nsecgw6kw
React Native
http://facebook.github.io/react/blog/2015/10/07/react-v0.14.html
This paves the way to writing components that can be shared between the web version of React
and React Native.
とあるように、背景にはやはりReact Nativeの存在が大きい。
https://github.com/facebook/react-native
ReactNativeは以前から存在していたが、iOSのみサポートしており、今や世界のスマホOSのマジョリティであるAndroidがサポートされていなかった。Reactバージョン0.14でDOMとの分離の方向性が打ち出されるとほぼ同時期に、Androidのサポートもリリースされて、今後スマホのUI開発でもReactのコンポーネント指向(関数型)も本格化すると思われる。
Reactで書かれたUIコードは、
Webブラウザでは、ReactDOM
スマホでは、ReactNative
に接続され、共用できる。
Babel
Nodeが、ES6を本格的にサポート開始したことにより、ES6+→ES5トランスパイラであるBabelのJavaScript世界における重要性は薄まったが、
1 JavaScript世界のUIデファクトであるReactの言語JSXを広範なブラウザで稼働するES5へのトランスパイラするにために、FacebookはBabelプロジェクトに依存する方針を明確にしており(前回記事参照)、Reactクライアントサイドをトランスパイルする為には、今後も末永くBabelは必須。
2 NodeのES6+対応はまだまだ発展途上。ES6で有用な仕様に開発途上オプションフラグを指定しなければいけないなど未熟。それに比べてBabelは現行、ES6+の対応度に勝る。
https://kangax.github.io/compat-table/es6/
1,2より、Babelは今後もデファクトのトランスパイラとして活躍し、JSコミュニティ(Facebook/React含む)から幅広い支持がありそうな状況。
ボトムラインとして、事実、これまでNodeはio.jsと分裂したり、大元のV8エンジンのES6対応が遅々として進んでないようだったり大きな問題があった。それに比較してBabelプロジェクトはフットワークが軽く対応が早く、この2015年に、JavaScriptコミュニティがES6への移行することを強く後押した功績も大きいと思う。
Babelとnpmのプロジェクトローカル指向
近頃、Nodeのパッケージマネージメントシステムであるnpmは3系に、Babelは6系にメジャーバージョンアップした。
npmも、Babelプロジェクトも、パッケージ依存は、Babelのようなツールも含めてプロジェクトローカルに分離独立させておくべきだ、という方針を強めている。
これはJavaScript、Node世界が、洗練された形で進化する過程で不可避に複雑化されて、必要なツールが増えてくると、各ツールとプロジェクトのバージョンの整合性が問題となってくる。
これまで多くの場合、ツールは、npm install -g
などとし、ツールはグローバルにインストール、各プロジェクトから共用する、という発想だったのが、もうその方向性では行き詰まるので、各プロジェクトローカルにそれぞれ専用のバージョンでインストールしよう、という方向性になっている。
もちろん各パッケージにいちいち巨大なツールを含有していたら、複数のnpmパッケージに依存するプロジェクト全体がとんでもないことになるのだが、npmにはdevDependenciesという仕組みで、パッケージ配布時には自動ではインストールされることがない開発モードの依存パッケージという秀逸な仕組みがあるので、それでうまく整理できる。
しかしこれまでいまいち意味がよくわからなかったのが、
Babelの公式サイトのドキュメントで、
http://babeljs.io/docs/setup/#babel_cli
Installation
$ npm install -g babel-cli
とあくまでグローバルインストールを公式に推奨しているように見えた。
しかし、Babel6系にアップデートした上で、
JavaScriptではES6+とReact-JSXからES5へのトランスパイルが標準に / ATOMエディタで最速環境構築 厳選パッケージ 3 + 3 2015年夏バージョン
のとおり、環境構築をしていくと、BabelのJSXのトランスパイルでエラーがでてコケる。
どうしようもないので、
Babel公式サイトの掲示板で質問してみたところ、
https://discuss.babeljs.io/t/error-parsing-jsx-with-global-installation-babel-preset-react/59
この理由は結局、そもそも公式ドキュメントのSetupにしたがってBabelをグローバルにインストールするのが間違いで、プロジェクトローカルに、
$ npm install --save-dev babel-cli
とdevDependenciesとしてインストールすべきである、Babelプロジェクト開発者はそういう方針である、ということがわかった。ドキュメントと方針に齟齬があるのは、今現在ドキュメントを大改定中であり、まだ追いついていないということ。
thejameskyle
I’ve been wanting to update the documentation to say otherwise. I just haven’t gotten to it (I’m busy writing the babel handbook right now which does teach people to install locally).
Again, I want to, but I also want to rewrite most of the documentation, a lot of which is in progress.
結局、よほどのことがない限り、原則、ツールも各プロジェクトローカルにdevDependenciesとしてインストールしてしまう
$ npm install --save-dev eslint babel-cli babel-preset-es2015 babel-preset-react webpack
などとし、結果、たとえば公開している自作npmパッケージtimeengine
https://www.npmjs.com/package/timeengine
https://github.com/kenokabe/timeengine
では、
https://github.com/kenokabe/timeengine/blob/master/package.json
{
"name": "timeengine",
"version": "4.6.0",
"description": "Time Engine is the True Functional Reactive Programming Library from the Point of View of Physics, our World and Time",
"main": "timeengine.js",
"scripts": {
"test": "babel timeengine.es -o timeengine.js; babel-node test.js"
},
"devDependencies": {
"babel-cli": "^6.3.15",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"eslint": "^1.10.3",
"immutable": "*"
},
"repository": {
"type": "git",
"url": "git+https://github.com/kenokabe/timeengine.git"
},
"keywords": [
"FRP",
"functional",
"reactive",
"time",
"physics",
"mathematics",
"stream",
"sequence",
"event"
],
"author": "Ken Okabe",
"license": "MIT",
"bugs": {
"url": "https://github.com/kenokabe/timeengine/issues"
},
"homepage": "https://github.com/kenokabe/timeengine#readme"
}
と、以下抜粋するように、devDependencies
として開発ツールをプロジェクトローカルにインストールしてしまうのが最終的な方針と解決策である。
"devDependencies": {
"babel-cli": "^6.3.15",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"eslint": "^1.10.3",
"immutable": "*"
},
この際、
babel
コマンドは、プロジェクトローカルの
./node_modules/.bin
にインストールされる。
グローバルでインストールしていたときのように、コマンド単体のパスは通っておらず、以上の相対パスをいちいち叩くのは骨が折れ現実的ではにないので、シェルの初期設定に、
.zshrc
export PATH=$PATH:./node_modules/.bin
などとしておけば良い。
その他
JavaScriptではES6+とReact-JSXからES5へのトランスパイルが標準に / ATOMエディタで最速環境構築 厳選パッケージ 3 + 3 2015年夏バージョン
で示した、
.eslintrcというESLint設定ファイルに以下の内容をコピペし、ホームディレクトリ直下に新規作成します。
{
"parser": "babel-eslint",
"env": {
"es6": true,
"node": true,
"browser": true
},
"rules": {
"semi": [2, "always"],
"strict": 1,
"no-undef" : 2
}
}
というのは、グローバルでなくプロジェクトローカルにまとめる方針になるので以下のように更新。
https://github.com/kenokabe/timeengine
のとおり、
.babelrc
.eslintrc
ともに、プロジェクトローカルのファイル郡に含めてしまう。
https://github.com/kenokabe/timeengine/blob/master/.babelrc
{
"presets": ["es2015","react"]
}
https://github.com/kenokabe/timeengine/blob/master/.eslintrc
{
"env": {
"es6": true,
"node": true,
"browser": true
},
"ecmaFeatures": {
"jsx": true
},
"rules": {
"semi": [1, "always"],
"strict": [2, "function"],
"no-undef" : 2
}
}
以上のような設定では、前回のように
babel-eslintをインストールすることは不要となった。
Atomエディタ
Atomのプラグインは、
JavaScriptではES6+とReact-JSXからES5へのトランスパイルが標準に / ATOMエディタで最速環境構築 厳選パッケージ 3 + 3 2015年夏バージョン
と同じ。
0 コメント:
コメントを投稿