あいつの日誌β

働きながら旅しています。

React Tutorial (1)

追記(2017-02-08)

webpack.config.js がエラーが出るので訂正しました。js 界隈は変化が早いのでチュートリアルを試される方はお早めにお願いします。 あと React.js の tutorial というよりも redux の tutorial ではないかという意見を頂戴しましたがよくよく考えればそうですね。

あらすじ

React, redux を使った開発をしたのですが、後続の部隊がきちんとメンテできるかどうか心配だったのでドキュメントを作成しました。

目次

  • 開発環境を準備 <= ココ
  • React の基本的な Life Cycle に触れる
  • redux に触れる
  • redux-saga に触れる
  • react router に触れる
  • npm で公開されている components を導入して echo system を体感する
  • redux-form に触れる
  • react-select に触れる

開発環境を準備

browsersync + webpack の設定を行います。 react hot replace の設定をしておく作業が早くなる気がするので組み込みます。

今回の作業で必要なファイル、ディレクトリを作成します。

mkdir practice-react && cd $_
mkdir src www
touch .babelrc webpack.config.js devServer.js src/index.js src/Root.js www/index.html
npm init -y

開発でのみ使用する module は devDependencies にインストールします。

npm install --save-dev browser-sync webpack webpack-dev-middleware webpack-hot-middleware
npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-stage-0 babel-preset-react babel-plugin-react-hot
npm install --save-dev style-loader file-loader css-loader url-loader react-hot-loader

bundle.js に組み込まれる module は dependencies にインストールします。

npm install --save babel-polyfill
npm install --save jquery bootstrap
npm install --save react react-dom

各種ファイル作成

create .babelrc

{
  "presets": ["es2015", "stage-0", "react"]
}

create webpack.config.js

const path = require('path')
const webpack = require('webpack')

module.exports = {
  devtool: 'inline-source-map',
  entry: [
    'webpack/hot/dev-server',
    'webpack-hot-middleware/client',
    './src/index.js'
  ],
  output: {
    publicPath: "/",
    path: path.resolve('www'),
    filename: "bundle.js",
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.ProvidePlugin({
      jQuery: 'jquery',
      $: "jquery"
    })
  ],
  resolve: {
    extensions: ['.js'],
  },
  module: {
    loaders:[
      { test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel-loader'] },
      { test: /\.css$/, loader: "style-loader!css-loader" },
      { test: /\.svg$/, loader: 'url-loader?mimetype=image/svg+xml' },
      { test: /\.woff$/, loader: 'url-loader?mimetype=application/font-woff' },
      { test: /\.woff2$/, loader: 'url-loader?mimetype=application/font-woff' },
      { test: /\.eot$/, loader: 'url-loader?mimetype=application/font-woff' },
      { test: /\.ttf$/, loader: 'url-loader?mimetype=application/font-woff' }
    ]
  }
}

create devServer.js

const webpack = require('webpack')
const browserSync = require('browser-sync')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')
const historyApiFallback = require('connect-history-api-fallback')

const config = require('./webpack.config')
const bundler = webpack(config)

browserSync({
  open: false,
  server: {
    baseDir: config.output.path,
    index: "index.html",
    middleware: [
      webpackDevMiddleware(bundler, {
        publicPath: config.output.publicPath,
        stats: { colors: true }
      }),
      webpackHotMiddleware(bundler),
      historyApiFallback()
    ]
  },
  files: [
    'www/*.html'
  ]
})

create src/index.js

import React from 'react'
import { render } from 'react-dom'
import Root from './Root'

render(
  <Root />, 
  document.getElementById('root')
)

if (module.hot) {
  module.hot.accept('./Root', function() {
    const NextApp = require('./Root').default
    render(<NextApp/>, document.getElementById('root'))
  })  
}

create src/Root.js

import 'babel-polyfill'
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.css'
import React from 'react'

export default (props) => (
  <div className="container">
    <h1>React boilerplate</h1>
    <p>test</p>
  </div>
)

create www/index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://opensource.keycdn.com/fontawesome/4.7.0/font-awesome.min.css" integrity="sha384-dNpIIXE8U05kAbPhy3G1cz+yZmTzA6CY8Vg/u2L9xRnHjJiAK76m2BIEaSEV+/aU" crossorigin="anonymous">
  </head>
  <body>
    <div id="root"></div>
    <script src="/bundle.js"></script>
  </body>
</html>

以下を実行

% node devServer.js

まとめ

今回は開発環境の構築方法についての説明を行いました。 Browsersync で通信速度を 3G に設定して動作確認するとシャレオツな感じで良いと思います。 次回は基本的な Life cycle と記述方法について説明します。