Node.js 5.0へ

5.0!ほんの一年ぐらい前は0.10とか0.11とか名乗ってたのになあ。

www.publickey1.jp

運用モードでも全くないので、バシッと最新にしちゃいます。これまではnodejs.orgから落としてきたインストーラを使ったので「n」を入れて、そこからアップデートします。

$ sudo npm install -g n
$ n --latest
$ n latest

サクッと、結果は以下。

install : node-v5.0.0
mkdir : /usr/local/n/versions/node/5.0.0
fetch : https://nodejs.org/dist/v5.0.0/node-v5.0.0-darwin-x64.tar.gz
installed : v5.0.0

続いてnpmもアップデート。

$ sudo npm update -g npm
$ npm -v

結果は「3.3.12」ということです。

おいおい、babel周りがガラッと変わってるぞ

$ sudo npm update -g
$ npm update

何気なくGlobalもLocalも一切合切アップデートしちゃったんですよ。そうしたらもう、Babelifyが動かなくなってちょっとハマりました。ほんの数日前に書いたエントリが嘘八百。

babeljs.io

babel/babelify · GitHub に"> As of Babel 6.0.0 there are no plugins included by default. For babelify to be useful, you must also include some presets and/or plugins."って書かれてる通りBabelが変わって、Babelifyも当然変わる。プラグインのインストールとTranspileコマンドの書き換えを行います。

$ npm install --save-dev babel-preset-es2015 babel-preset-react
$ browserify App.jsx -o public/js/bundle.js -t [ babelify --presets [ es2015 react ] ]

-tスイッチの引数はスペースもちゃんと入れないと、[babelifyなんて知らん!と怒られます。パラメータのトークナイズがちょっと足りてないみたい。これで10/30に書いたのと同じことが再び出来るようになってます。babel-nodeもダメなんで、そちらはpackage.jsonの中にBabel設定を書きました。

// package.jsonの一部
{
  "devDependencies": {
    "babelify": "^7.2.0",
    "babel-preset-es2015": "^6.0.15",
    "babel-preset-react": "^6.0.15"
  },
  "babel": {
    "presets": [ "es2015" ]
  },
  "scripts": {
    "start_es6": "babel-node server.es6",
    "build_server": "babel server.es6 -o server.js",
    "bundle_client": "browserify App.jsx -o public/js/bundle.js -t [ babelify --presets [ es2015 react ] ]"
  }
}

WebStorm 11も製品版リリースしてた

リリースラッシュです。WebStrom も11.0になってました。EA版じゃなくなったし、そろそろ課金すっかな。

今はbabel-nodeで動かす

ECMAScript6で、node.js/express.jsのサーバ側を書く段になるとes6的メリットを享受できていません。Reactの方はclassを用いて書くといい感じなんですけどね。

// server.es6
import express from 'express';
const server = express();
server.get('/', async (req, res, next) => {
    res.status(200).send("Hello World!");
});
server.listen(8080);

$ node server.es6

で、こんなHello Worldでもそのままでは動かない。node.jsの今のバージョンであるv4.1.1だとModulesがデフォで対応していないのでimportでランタイムに文法エラーが出てきちゃう。そのうち対応するでしょうけど今は残念ながら--harmonyオプションでもダメなので、babel-nodeの出番です。babelをインストールしたら、/usr/local/binにいます。

$ babel-node server.es6

はい。動きました。しかし今使ってるv11プレビュー版のWebStormであるバージョンWS-143.380.11のデバッグ機構ではbabel-nodeを設定して一度目の実行はちゃんと動くけど、二度目以降はツールの中でポートを掴んでる何かにアプリケーションをちゃんとアタッチできないのか、WebStormが出す独自の404画面になっちゃう。これは多分WebStormのバグだな。babel-nodeでの実行をやめ、Transpileしてからnodeでの実行に戻しても同じ現象だし。コンソールでの起動ならば何の問題もない。

f:id:masataka_k:20151031095730p:plain

ちなみにこれはWebStormのデバッグ機構にbabel-nodeを設定するところ。一度目はちゃんとデバッグできるんだけどなー。

importの解決でBrowserifyからのBabelify

ECMAScript6でクライアント側を書いてますが、極小のHello Worldレベルから一歩進むだけで壁が。JavaScriptの発展の歴史の中で大きなアプリケーションを作るためのパッケージ参照機構が様々用意されてたみたいですが、そこにまた大きな曲がり角が出てきちゃってた。

  • 原始時代より長らくHTML上でscriptタグのsrc属性にファイル名を指定することで読み込むという参照方法のみだった。
  • サーバ側でもJavaScript使おうよとNetscapeを始め何度か繰り返されては散り、しばらく忘れ去られていた太古の試みは、Node.jsの登場でルネッサンス
  • Node.jsがプラットフォームとして実装したrequireでnpm管理されたパッケージ構成を参照させたのを模して、独自にライブラリレベルでrequireをクライアント側へ導入する文化が花開く
  • 産業革命。ES6でimport/exportの言語表記が標準化される。Node.jsもio.jsとの分離と再統合を経てES6に対応。しかし環境として世に数多あるブラウザがES6対応版に置き換わってくるのはこれから

今はimport書いてもそのままでは動かない。Babelではimportをrequireに書き換えるからrequireをbabel/registerなどでライブラリとして手当しないといけない。そんな中、そもそもファイルが分割されているから参照機構が必要なんじゃないかと動乱の中でちゃぶ台ひっくり返したのがBrowserifyでした(この前知ったばかりなのに適当な説明しちゃったな)。

http://browserify.org/

Transpilerとしてrequireが書いてあるコードの参照を辿ってライブラリを探し、見つけたもの皆を一つのファイルに合体させちゃうという。イイね!さらにTranspile時にBabelしちゃいましょうというのがBrowserifyのプラグインであるBabelify。合わせ技でimport/exportを解決。

github.com

Githubサイトの説明に書いてある通り、ターミナルでコマンド一発です。

$ browserify App.jsx -o public/js/bundle.js -t babelify

あとはHTMLのsrcで参照するタイプのscriptタグを全部削って、生成物を参照するscriptタグだけに変える。その前にライブラリはできる限りnpm管理でnode_module配下にしとくこと。

<script src="js/bundle.js"></script>

こうなってくると、WebStormのファイル監視にBabelを設定して自動Transpileしていたのを外して、動作確認が必要な時にBrowserifyを叩くってことになりますね。複数ページになって複数のブロック構造になってくるとまたどうしたもんかねとかあるけど、この辺は愚直にやっても数はブロック数に限定されてるので手間じゃなくいいんだと思う。

ECMAScript6を楽に

少々触った程度ですが、もうWebStormからSublimeやBracketsといったテキストエディタ+へは戻れません。だいたい最近の流行をつかんだところで、もっと中身の方に移ろうと思います。

babeljs.io

JSX書くのに、BabelがいるってんならECMAScript6もいいよねってことで。まずWebStormにBabelを設定しました。色々見て回る途中にBabelは入れてたので、設定もドキュメントに従ってすぐに終わります。

f:id:masataka_k:20151023045932p:plain

自動で平たいJavaScriptコンパイル(最近はトランスパイル/Transpileともいうらしい。トランスレートとコンパイルからの造語かな?)されるようになりました。実際の生成物は同じフォルダに出力されますが、WebStormのプロジェクト構造ビューでは元のファイルの添付のようにフォルダ表示されるようになります。全部自動だからイイね。生成ファイルはデフォルトだと「-compiled」接尾辞のついた名前。HTMLから参照するときには生成ファイルの方になるので、設定変えてもっと短くしたり出力フォルダを変えたりしたほうがいいかも。

ということで、ES6を書いた後が楽になりました。書くところはまだES6以前にJavaScript的な一切がほぼこれからなので楽じゃないんですけど。

var Hello = React.createClass({
  render: function() {
    return (
      return <h1>Hello, {this.props.name}!</h1>
    );
  }
});

ES5のこれより

class Hello extends React.Component {
    render() {
        return <h1>Hello, {this.props.name}!</h1>
    }
}

ES6のこっちの方が見通し良い。

Reactのバージョンあがってた

Reactのバージョンがv0.14.0に上がってました。構成もいろいろ変わってる。。。3秒見るだけで変わってて、独立したJSXTransformerが無くなりJSXの逐次変換ではBabelが使われるようになり、グローバル変数としての"React"を"ReactDom"に代えて利用ケース毎に適切な呼び出しコンテクストを設定の上でReact本体を隠蔽しています。さらにはGetting Startの確認すぐに冒頭でnpm利用を推奨しています。

We recommend using React with a CommonJS module system like browserify or webpack. Use the react and react-dom npm packages. https://facebook.github.io/react/docs/getting-started.html

そっかー。そうなると言語もES6で書くかだな。モジュール依存関係を明示する次世代JSな世界はIDEにも優しい。その後に試用を始めたWebStrom 11もバリバリES6なボイラープレート吐いてた。

f:id:masataka_k:20151022025938p:plain

importだわclassだわ、馴染む雰囲気ではあるけどこれからゼロスタート。スクショのコードにはJavaアノテーションみたいなのも見えるねー。

WebStorm 11はJSXをちゃんとハイライティングしてるし、どうやら.eslintrcをプロジェクトに含めるとそれでlintingしてくれる!

{
  "extends": "airbnb",
  "globals": {
    "__DEV__": true
  },
  "rules": {
    "react/jsx-quotes": 0,
    "jsx-quotes": [2, "prefer-double"]
  }
}

生成されたボイラープレートに入ってた.eslintrcは、Air B'nB由来なんですね。ちょっと可笑しい。

React向けにLinterを設定する

JavaScriptを書き、Reactに触れるにあたって、エディタをどうしようかと一回りしました。元々Javaな人なんでEclipseなどの統合開発環境でがっちりサポートされてきた身としてはテキストエディタだけでっていうのは不安です。不安なんで一年前には速攻でJetBrainsのWebStorm 7を買いましたね。改めて調べるとJetBrainsにおけるメジャーバージョンというのは相当軽い意味のようで、バージョン11が出ようかというところでした。 一方で、先月MDLを書いてた時には横にいた新井さんから教わったAdobe Bracketsを試してました。Bracketsは無料なので気楽ですし、HTML&CSS書くのにはいいですねー。ボタンポチッと押すだけでエディタと連携したデバッグChromeブラウザを立ち上げるのが便利。コードをちょっと書き換えるだけでビュー更新が即時されるのが素敵。ただ、Reactはどうかというと以下の問題が生じます。JavaScriptも書きやすいとは言えないかな。

  • JSLintが見当違いの文法ワーニングを大量に吐く
  • JSXがちゃんとハイライトされない

WebStorm11を試す前に、まずは苦労してみようかとBracketsで環境試し作りしてみました。調査の結果JSLintの問題は、後継のESLintに差し替えるとオッケーです。ESLintはすでにOSSでReact対応が提供されてます。その手順は。。。いろいろ読んでやっとできたよ。。。以下は本日の正解。足が速いので時間がちょっと経つだけで正解じゃなくなりそう。

前提

Node.jsがインストールされていて、npmが使えること。BrewだMacPortだといろいろ方法はありますが、まあ細かなバージョンが云々というような高尚なレベルじゃないので、潔く手を抜いて本家からMacインストーラ付きバイナリパッケージ落としてくればいい。さらにはgitも必要です。

ESLint を設定してReact文法をLintingする

eslintをインストール

www.npmjs.com

Lintingのエンジンです。これが無いと始まらない。Globalにインストールしておいたほうがどっからでも叩けて潰しが効きそうです。

sudo npm install -g eslint

eslint-plugin-reactをインストール

www.npmjs.com

これはESLintのReact文法のプラグインとしてお目当てのもの。

sudo npm install -g eslint-plugin-react

~/.eslintrcを編集する

細々と状況毎に設定を切り替えるということを求めないならば、RCファイルを一つ作れば動きます。切り替えを求める場合はフォルダ切ってJSONファイルを切り替え環境毎に作ることになるという。下記envではECMAScript6を無効にしています。ES6は早いかなー、でもReactの場合はES6で書いてもプリプロセスとしてコンパイラかけとけばいいですから意外に早すぎることもないかな?

{
  "env": {
    "node": true,
    "es6": false
  },
  "ecmaFeatures": {
    "jsx": true
  },
  "plugins": [
    "react"
  ],
  "rules": {
    "react/display-name": 0,
    "react/forbid-prop-types": 1,
    "react/jsx-boolean-value": 1,
    "react/jsx-closing-bracket-location": 1,
    "react/jsx-curly-spacing": 1,
    "react/jsx-indent-props": 1,
    "react/jsx-max-props-per-line": 0,
    "react/jsx-no-duplicate-props": 1,
    "react/jsx-no-literals": 0,
    "react/jsx-no-undef": 1,
    "react/jsx-quotes": 1,
    "react/jsx-sort-prop-types": 0,
    "react/jsx-sort-props": 0,
    "react/jsx-uses-react": 1,
    "react/jsx-uses-vars": 1,
    "react/no-danger": 1,
    "react/no-did-mount-set-state": 1,
    "react/no-did-update-set-state": 1,
    "react/no-direct-mutation-state": 1,
    "react/no-multi-comp": 1,
    "react/no-set-state": 0,
    "react/no-unknown-property": 1,
    "react/prefer-es6-class": 0,
    "react/prop-types": 1,
    "react/react-in-jsx-scope": 0,
    "react/require-extension": 1,
    "react/self-closing-comp": 1,
    "react/sort-comp": 0,
    "react/wrap-multilines": 1
  }
}

たくさんある「react/...」はLintingの挙動を決める設定で、値0が無視/値1が警告/値2がエラー。ちょこちょこその後の動作を見て書き換えていけばいいでしょう。全部1にするとうざいぐらいに警告が出ますが、JSLintの時と違ってその警告が見当違いということはありません。まさにこのRCファイルにそう設定しているからこそ出る警告となってます。

BracketsでESLintを動かす

brackets-npm-registryをインストール

github.com

Bracketsにプラグインをインストールする前段階として、標準のものとは違うパッケージ管理ツールを入れます。

sudo npm install -g gulp-cli
cd ~/Library/Application\ Support/Brackets/extensions/user/
git clone https://github.com/zaggino/brackets-npm-registry.git brackets-npm-registry
cd brackets-npm-registry
npm install

brackets-eslintをインストール

github.com

これはUIからインストールする。クリック一発。インストールが終わるとリフレッシュが走って後、めでたくEsLintでLintingされるようになります。

JSlintの無効化

最後の仕上げとして、brackets.jsonの編集をします。このファイルはBracketsの環境設定メニューで開かれるJSONファイルです。明示的にESLintを登録して、「linting.usePreferredOnly」は登録してるものだけを有効にするという設定。JSLintが暗黙に登録されているのでその抑制のために必要とのこと。

{
省略...
    "language": {
        "javascript": {
            "linting.prefer": [
                "ESLint"
            ],
            "linting.usePreferredOnly": true
        }
    }
}

ハイライトはダメ

ところで、BracketsのJSXハイライトはバグってます。春先から課題スレッド上がってるけど解決してない。

github.com

Sublime Text 3へ設定してみる

普段のテキスト書きではSublime Text 2を愛用していました。Sublimeもコードを書くテキストエディタとしてプラグイン盛り盛りでパワーアップできます。ただしESLintを盛るには永遠のベータ版であるSublime Text 3にする必要がありました。

Sublime Text 3をインストール

Sublime Text - Download

SublimeLinterをインストール

ST3のCommand + Shift + pのメニューで、"install"と入力するとPackage Control: Install Packageが選べる。クリック。"Linter"で探すとSublimeLinterが出てくる。選んでクリックするとインストール

SublimeLinter-eslintをインストール

上記と同様にして、Package Control: Install PackageからSublimeLinter-eslintを選ぶ。クリックするとインストール。

なんということでしょう!Sublime Text 3はJSXもちゃんとハイライティングします。Lintingも動き、軽い使い方ならこれがファイナルアンサーで良さそう。

しかーし。WebStorm 11を試してからの結論としよう。

入門 React

入門 React ―コンポーネントベースのWebフロントエンド開発

入門 React ―コンポーネントベースのWebフロントエンド開発

遅ればせ?ながらReact.jsを触ってます。春に日本に出張で戻った時には適用を具体的に考えてもいなかったけど、なぜか何となくReact.jsがキーワードとして頭にあったために、本屋で新刊だった「入門 React」を見つけてすぐジャケ買いしてました。その後に新会社設立からの体制固めで時間が経過しましたが、やっと最近は手が空いてきており、むしろ作る方に回れって感じになってきましたのでチームの手が付いていなかったコーポレートWEBサイト周りをやることとしています。よって最近のWEB開発技法をもう一度さらっておこうという。 React.jsの前に、そもそもサイトのコンテンツ流し込むテンプレを作らないといけないということで、先月はMaterial Design Lite(MDL)をやってました。モバイルファーストかつAndroid風な見かけをやってみたかったのでBootstrapではなく、参加したGoogle I/O 2015で見ていたMDLにチャレンジです。意外にそれらしい見かけやレスポンシブの動きが手軽に実現出来たところで、次には動かすところ。そこでやっとReact.js。サーバサイドはチームがAPIをGo言語でゴリゴリやってますのでそれを最終的には利用しますが、プロトタイプは去年の夏頃に時間を費やしていたNode.js+Express.jsで軽めにやってみようかと思います。

www.getmdl.io

そして「入門 React」。この本はどう考えても入門という言葉が暗示するような、まず1冊目として読んでみましょう!というホスピタリティを提供しません。むしろReact.jsの本家WEBサイトのコンテンツから漏れたような注釈的内容が書かれた本だと思います。しかしレシピ本の構成でもないという。この本を一冊目に読むと全く何が言いたいのかさっぱりわからない状態になりそうです。まず本家WEBサイトを一通り読んで理解してください。その上でこの本を読むと、ああなるほど筆者は親切な人なんだなぁ、この本は良書だったんだなぁと思えるようになります。 React.jsを今から試そうかという人は(他にはReact関連タイトルって見当たらないし)十分にこの良書を買っていいと思います。ただし買うだけでしばらくは積んでおいて、読むのは最低限本家WEBサイトのチュートリアルを写経してからにしてください。入門と冠ついたタイトルは単なるオライリーの施策であって、彼らは売るためにタイトルを偽造していました。こいつの原書のタイトルである「Developing a React Edge」や概要には全く101風な単語がありません。

facebook.github.io