ブラウザで実行するjsの開発環境構築(主にReact.js)


# はじめに
React.jsってよく聞く！やってみたい！
って思ったそこのあなた！！（僕です）

bower?
gulp?
grunt?
Angular.js?
React.js?
Riot.js?
Vue.js?
ES2015?
CommonJS?

わからない単語が多すぎる・・・！

となったことかと思います。これらについて、入りが大変だったので、セットアップと、用語説明メインで書こうと思います。

フロントエンドエンジニアではないので、何かあれば、気軽にコメントで指摘ください。

※Mac環境

# homebrewのインストール
色々なツールの管理に便利な、Macのデファクトスタンダード

大抵の人は入れていると思いますが、今回も使うので入れておいてください

昔はMacPortsかhomebrewか、とか言ってたけど最近はhomebrew一択な気がする

参考：[MacにHomebrewをインストールする](http://qiita.com/_daisuke/items/d3b2477d15ed2611a058)

# node.jsのインストール

パッケージ管理に、node.jsを使うのですが、そのnode.jsのバージョンアップがけっこうあるので、node.js自体のバージョン管理をしたいです。

そこで、nvmとか、nodebrewとか、nodenvとかあります。そのまま入れてもとりあえずは問題ないですが、どれかを使ってバージョン管理をしたほうが吉です。

### nodenvの場合
anyenvを使っている人は、

```bash
anyenv install ndenv
```

そうじゃない人は、

```bash
brew install nodenv
```

として、nodenvをインストール

その後、以下のページに従って環境設定

参考：[nodenvを使ってMacにNode.jsの環境を構築する](http://qiita.com/1000ch/items/41ea7caffe8c42c5211c)

### nodebrewの場合

参考：[node.jsのversionを管理するためにnodebrewを利用する](http://qiita.com/sinmetal/items/154e81823f386279b33c)

```bash
brew install nodebrew
```

`~/.bash_profile`(zshなら`~/.zshrc`)に以下を追加

```
export PATH=$HOME/.nodebrew/current/bin:$PATH
```

そして、

```bash
source ~/.bash_profile
nodebrew setup
```

でリロード（ターミナルを再起動してもOK）

nodeの設定

```bash
nodebrew install-binary latest
nodebrew ls
nodebrew use v6.2.0
```

もちろん、`nodebrew ls`で出てきたバージョンの内、一番新しいものをuseの後ろのセットします。

## 設定後

`node -v`でバージョンを確認できます。

自動的に、npmというパッケージ管理システムもインストールされています。
こちらも、`npm -v`でバージョン確認できます。(node.jsのバージョンとは異なります)

２つとも正常にできていれば、完了です！

## Atomのセットアップ

もし[Atom](https://atom.io/)で開発している場合は、jsxファイル（Reactで使う、拡張jsファイル）のハイライトには追加パッケージが必要なので、インストール

```bash
apm install react
```

また、上のタブの[Edit]>[React (JSX)]>[Reformat JSX]でフォーマットできるので定期的に（linter使うより手軽）

参考：[tanaka's Programming Memo: AtomでReactのコードを書く](http://am1tanaka.hatenablog.com/entry/2015/06/28/111614)

# gulpのインストール

[gulp](http://gulpjs.com/)というタスクランナーを使うので、これをnpmでグローバルインストールしておきます。
今は[grunt](http://gruntjs.com/)よりも[gulp](http://gulpjs.com/)の方が一般的ぽい？

makeみたいなもので、毎回実行するタスクを記述しておくことができます。npm scriptでも実現可能ですが、

```bash
sudo npm install -g gulp
```

`ERR!`がでなければ、`npm WARN deprecated`は出てもOK

※昔pythonのバージョンを3.xにしているとエラーになったが、今はいけるっぽい？

## React.jsプロジェクトの実行確認
参考：[React.js + Babel + Browserify + gulp の環境を作ってみた](http://qiita.com/hkusu/items/e068bba0ae036b447754)

サンプルを実行してみよう

```bash
git clone https://github.com/ha1fha1f/react-gulp-es2015
cd react-gulp-es2015
npm install
gulp
```

>(node:12443) fs: re-evaluating native module sources is not supported. If you are using the graceful-fs module, please update it to a more recent version.
[16:59:51] Using gulpfile ~/git/js/ha1fha1f.github.io/gulpfile.js
[16:59:51] Starting 'browserify'...
[16:59:51] Finished 'browserify' after 23 ms
[16:59:51] Starting 'watch'...
[16:59:51] Finished 'watch' after 18 ms
[16:59:51] Starting 'webserver'...
[16:59:51] Webserver started at http://127.0.0.1:8000
[16:59:51] Finished 'webserver' after 19 ms
[16:59:51] Starting 'default'...
[16:59:51] Finished 'default' after 2.92 μs

これが出てきたら

ブラウザから、[http://127.0.0.1:8000](http://127.0.0.1:8000)にアクセス！

見られれば、正常にReact.jsで開発環境完成しています

実際に、最終の表示に使っているファイルは、index.htmlとstyle.css、bundle.jsのみです。
その他のファイルが、gulpのタスクの中で変換されて、bundle.jsになっています。以降、このプロジェクトを書き換えていくだけで開発することが出来ます（それが楽だと思います）

# gulpの使い方
gulpfile.jsに従って、タスクを実行する。makeのような感じ。

`gulp.task('taskname', function(){});`
もしくは
`gulp.task('taskname', ['task1']);`
という形で、taskを定義します

`gulp.task('default', ['task1', 'task2']);`
引数無しでgulpコマンドを実行した時には、defaultに登録したtaskが実行されます。
ので、defaultという名前のタスクとしてすべて登録しておく。

上のサンプルで登録していた３つのタスクは、

- babelでトランスパイル、browserifyでrequire関係を解消してまとめる(bundle())。それをvinylオブジェクトに変換(source())して、そして、`js/bundle.js`として、書き出す(browserify, babelifyモジュール)
- js/*.jsxの更新を監視して、browserifyというタスクを自動的に実行する
- カレントディレクトリをルートとしてローカルサーバーを立てる(webserverモジュール)

という３つです


# npmの使い方

通常は、`package.js`というファイルに従って、

```bash
npm install
```

とするだけで依存ライブラリが（カレントディレクトリ/node_modulesに）インストールされます。

```bash
npm install packagename --save--dev
```

とすると、モジュールが（カレントディレクトリ/node_modulesに）インストールされた上で、package.jsonに、開発の時のみ使うモジュール(devDependencies)として追加されます。

productionの時も必要なモジュールの場合は、`--dev`を外しますが、今回などはbundleにまとめてしまうので、ブラウザ開発ではあまり必要ではないかと思います。

```bash
npm update packagename
```

とすると、パッケージをアップデートできます。

npmの設定は、package.jsonで確認できます。逆に、package.jsonを直接書き換えてもOKです。
書き換え後、`npm install`すれば、node_modulesも更新されます。
ただし、JSONなので、コメント等入れることはできません。

"scripts"の要素にも、シェルコマンドを記述すればnpm scriptsとして利用することができます。(これを使ってgulpを使わない人もいる)

npmは基本的にはnode.js用のパッケージマネージャで、ブラウザ用にはbowerとかもあったみたいですが、インポートの面倒さなどから、結局ブラウザでもnpmのほうが一般的ぽいです。

## browserifyとは
ブラウザのスクリプトでも、requireを使うことができるようになります。

つまり、requireの依存関係を解消して、一ファイルにまとめてくれます。（それぞれを`<script>`で設定する必要もない）

参考：[Browserify: それはrequire()を使うための魔法の杖](http://qiita.com/cognitom/items/4c63969b5085c90639d4)

# babelとは
トランスパイラ
ES2015（ES6）はブラウザでの実行にはまだ対応してないので、従来コード（ES5）に変換する必要がある

React.jsでのJSXも、そのままではブラウザで実行できないので、ES5への変換が必要。

どれを変換するかをpresetで指定している。今回はこの２つ。

```JavaScript
.transform(babelify, {presets: ["es2015", "react"]})
.bundle()
```

# watchとは

watchコマンドみたいなやつ。

```JavaScript
gulp.task('watch', function() {
    gulp.watch('./js/*.jsx', ['browserify'])
});
```

ファイルの更新を監視して、更新された時に実行するタスクを登録しておく。


# vinyl-source-streamとは

gulpはvinylオブジェクトをどんどん繋いで処理を行う。
が、babelifyの`.bundle()`の結果はvinylオブジェクトではないので、変換する必要がある。
そこで`source()`関数を使う。そのために、これのrequireが必要。

`.pipe(gulp.dest('./js/'))`は、vinylオブジェクトを受け取って、ファイルに出力する。

```JavaScript
.pipe(source('bundle.js'))
```

# フレームワークとは
上の例では、React.jsというフレームワークを用いました。他にも、いろいろなフレームワークがあります。

それぞれ考え方があって、実装が異なります。

どれも似たような感じで、トランスパイルして実行します。

# ECMAScriptとは
ほぼJavaScriptのことです。

ECMAScriptは仕様で、それに基づいた言語の一つとしてJavaScriptがある感じ。

参考：[ECMAScript 2015(ES6)の概要と次世代JavaScriptの新たな機能](https://html5experts.jp/1000ch/16984/)

ES6とかES2015とか言われてるのが、バージョンの話で、ES2015とES6は同じです。横の数字がバージョンに関する情報。
今後は一年ごとに出るらしく、ES2015という呼び名のほうが一般的になるらしい。

class、ブロックスコープなど、色々拡張されている

参考：[もうはじめよう、ES6~ECMAScript6の基本構文まとめ(JavaScript)~](http://qiita.com/takeharu/items/cbbe017bbdd120015ca0)

まだ大抵のブラウザは対応してないので、読み込みより前に、babelなどで変換が必要だが、けっこう書くときには一般的ぽいので、今回も利用した。

かなり書きやすくなっている。`var`とか、`(function(){})()`の滅びを感じる。

# React.jsのコーディング
上のサンプルでは、app.jsxが、メインのファイルです。gulpfileで指定しています。（これを起点として、どんどんrequireを解消していく）

0.14でReactDOMがReactから分離されましたので、renderには、ReactDOMを使用しています。

```JavaScript
ReactDOM.render(
    <App />,
    document.getElementById('content')
);
```

でレンダリングしています。残りは、どんどんコンポーネントの木構造が読まれて、描画されていきます。

React.jsの詳しい説明はこのへんで！

[入門React.js](http://amzn.to/2c4PciS)

# おわりに
設定と用語説明に重きを置きました。
実際の開発は別の記事とか本とかを読んでください！

＆気軽にコメントください