サーバーサイドプログラマーのためのReact.js 入門 2. 開発環境の構築の続き

これから作るアプリ

今回と次回で作るアプリですが Ruby on Railsのscaffoldジェネレータが生成する古き良き時代の単純なWebアプリケーションと同じ動きをする、React.js を使った Single page application (SPA)のフロントエンドを作っていきます。

バックエアンド(APIサーバー)は Ruby on Rails を使うことにします。

バックエンドの構築

Ruby on Railsのインストール等はネット上の情報を参考にしてください。 私の会社 EY-OfficeのWikiにもインストール方法を書いています (少し古いのでバージョンは最新のものを入れて下さい)

Railsがインストールできたら、以下のようにプロジェクトを作り scaffold ジェネレータを使い、Railsアプリを作ります。

$ rails new todo_app
$ cd todo_app
$ rails generate scaffold todo due:date task:string
$ rake db:migrate
$ rails server

http://localhost:3000/todosブラウザーからアクセスし、New Todo ページでデータを作成したり、アプリの動きを見てください。

f:id:yuum3:20160215151025p:plain

http://localhost:3000/todos.json をアクセスしてみて下さい。 scaffold ジェネレータが作ったコードはデフォルトでJSONを出力できます、これでバックエンドは完成です!

f:id:yuum3:20160215151031p:plain

rails server で起動したサーバーはReact.js でも使いますので、そのまま動かしておいて、以下の作業は別のターミナルで行ってください。

React開発環境の構築

前回は開発環境を構築する前準備でした、今回は具体的な開発環境を作り開発してみます。

Reactに行く前に

Railsの環境ではスタティックなコンテンツ等は public/ に置きます。

そこで JS が入るディレクトリーとJSを表示するための index.html を作成ておきます。

$ mkdir public/js
$ vi public/index.html
  • index.html
<!DOCTYPE html>
<html>
<head>
  <title>ReactTodo</title>
  <meta charset="utf-8">
</head>
<body>
  <div id="example"></div>
  <script type="text/javascript" src="js/app.js" charset="utf-8"></script>
</body>
</html>

React開発環境の構築

今回は Railsプロジェクトの中に frontend ディレクトリーを作りそこで開発することにします。npm init でいろいろとたずねれますが、気にせず return していっても良いです。

$ mkdir frontend
$ cd frontend
$ mkdir -p src/js src/css
$ nam init -y
  • React.js、babel、ESLint、webpack のインストール。 XXXX-loader はwebpack用のモジュールです。

本日ためしたところ eslint 2.0.0 をインストールすると babelが動作しませんでしたので @1.10 でバージョン 1.10.X をインストールしています。非互換な変更があったようです

$ npm install --save react react-dom
$ npm install --save babel-loader babel-preset-es2015 babel-preset-react
$ npm install --save eslint eslint-loader eslint-plugin-react babel
$ npm install --save css-loader style-loader
$ npm install -g webpack 
  • babel 設定ファイル .babelrc の作成。ES6(正式にはES2015)とJSX(React)の変換を行います
{
  "presets": ["es2015", "react"]
}
  • ESLint 設定ファイル .eslintlrc の作成、後で説明します。
{
    "env": {
        "browser": true,
        "node": true,
        "es6": true
    },
    "parserOptions": {
        "sourceType": "module",
        "ecmaFeatures": {
            "experimentalObjectRestSpread": true,
            "jsx": true
        }
    },
    "extends": ["eslint:recommended", "plugin:react/recommended"],
    "plugins": [
        "react"
        ],
    "rules": {
        "strict": [2, "function"],
        "no-undef": 2,
        "no-console": 0,
        "arrow-parens": [2, "always"]
    }
}
  • webpack の設定ファイル webpack.config.js の作成
    • entry: で生成物 app.js が src/js/index.js から作られることを定義
    • output: で生成物の出来る場所を定義、Rails の public/js/index.js に置かれます
    • PreLoaders: で生成前に ESLintの実行を指定
    • loaders: で生成(変換)作業を定義
      • .js, .jsx に対しては babelで変換
      • .css に対しては、styleタグ追加、css内のurl()等の解決を指定しています
    • resolve: は require/import での拡張子の省略を定義
    • eslint: eslintの設定ファイルを定義しています

設定ファイルの詳細は webpackのドキュメント や各ローダーのドキュメントを見てください。日本語の記事もいくつかありますので、両方を見ながら覚えて行って下さい。 (いずれ記事を書きたいですが、私もまだまだ苦労しています・・・)

module.exports = {
  entry: {
    app: "./src/js/index.js"
  },
  output: {
    path: '../public/js',
    filename: "[name].js"
  },
  module: {
    preLoaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: "eslint-loader"
    }],
    loaders: [{
      test: /\.css$/,
      loader: "style!css"
    }, {
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
     }]
  },
  resolve: {
    extensions: ['', '.js', '.jsx', '.css']
  },
  eslint: {
    configFile: './.eslintrc'
  }
};

試してみよう!

やっと環境ができました、さっそく試してみましょう。 まずは、 Reactの Getting Started のコードを試してみましょう

  • src/js/index.js
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('example')
);

ターミナルで webpack -d -w を入力し、少し待つと以下のように表示されます

  • app.js とマップファイルが生成されました。
  • また、index.js では React が定義されているが使われてないというエラーが出ています。
$ pwd
/Users/XXXXXX/todo_app/frontend
$ webpack -d -w                                 
Hash: cf1445dbfe9ce6c676f1
Version: webpack 1.12.13
Time: 2268ms
     Asset    Size  Chunks             Chunk Names
    app.js  764 kB       0  [emitted]  app
app.js.map  846 kB       0  [emitted]  app
    + 180 hidden modules

ERROR in ./src/js/index.js

/Users/yy/tmp/todo_app/frontend/src/js/index.js
  1:8  error  "React" is defined but never used  no-unused-vars

✖ 1 problem (1 error, 0 warnings)

ここでは、ESLintの出したエラーは一旦無視(他のエラーはちゃんと追求して下さいね)してブラウザーhttp://localhost:3000 をアクセスすると 画面に Hello、wold! が表示されます。

f:id:yuum3:20160215151043p:plain

上手くいかない場合はブラウザーのコンソール(開発ツール、インスペクター)を見てください。エラーや警告が出ているかもしれません。

上で書いたJSは ES5 ですが ES6 に変えてみましょう。同じエラーは発生しますが Hello, world! が表示されるはずです

import React from 'react'
import ReactDOM from 'react-dom'

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.getElementById('example')
)

Next Steps のコードも試してみてください。

ESLint

JavaScriptは動的な言語です、従って実行してみるまでエラーが発見できません。 テストを書いてこまめに開発していていれば良いのですが、ブラウザーを操作してやっと開発中のページを実行した途端に、つまらない文法エラー発生! などということになりがちです。

そこで大きな助けになるのが ESLint です。文法エラー、未定義エラー、定義されているが未使用などを実行前にチェックしてくれるので開発がはかどります!! 特に Reactでは JS の中に HTML が書かれる JSX は、なれるまで間違いが発生しやすのでお勧めです。

ただし、JSは動的な言語なのでチェックは完璧にはできません。上の Hello,world! 出ていたエラーは Reac変数がプログラムの中で使われていないので発生しました。しかし、この行を消してしまうと React.js が読み込まれないので実行できません。

このような場合は、ソースコードか設定ファイルに指定することで回避できます。ここでは .eslintlrc に React は使われてなくても良いというrule を設定を追加してみましょう。 詳しくは Configuring ESLint をみてください。

{
    ... ここまでは同じ...
    "rules": {
        "strict": [2, "function"],
        "no-undef": 2,
        "no-console": 0,
        "arrow-parens": [2, "always"],
        no-unused-vars: [2, {"varsIgnorePattern": "^React$"}]
    }
}

次回は、いよいよ React.js ^^)/