React.js
Pocket

Reactを試すときいちいち環境作るの面倒なので、勉強ついでにスターターキット的なのを作ってみました。

中身はこんな感じです。

  • React
  • Babel
  • CSS Loader
  • Webpack
  • React Hot Loader

Hot Loaderがあれば変更時に自動でリロードしてくれるので楽です。また、Hot Loaderはただ単にブラウザ全リロードではなく、変更箇所のみ更新してくれるので、stateを保持したまま部分更新できます。

基本的に以下を参考にして、CSS Loaderほしいなーと思ったので追加しました。

React + Babel + Webpack + HMR な環境をつくるだけ

参考になりました。ありがとうございます。

作ったものはGitHubで公開してます。

React-starterkit

以下、一から作る場合の手順です。

ライブラリのインストールなどの準備

まずはプロジェクトフォルダでpackege.jsonを作ります。
npm initでエンター連打するぐらいなら、-yか-fをつけましょう。

npm init -y

babelで変換するとき、古いブラウザでもいい感じにしてくれる「babel-polyfill」とReact関連を入れます。

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

その他使うもの一式インストールします。

npm install --save-dev babel-core babel-loader babel-plugin-add-module-exports babel-preset-es2015 babel-preset-react babel-preset-stage-0 webpack style-loader css-loader react-hot-loader webpack-dev-server

.babelrc

プロジェクトフォルダ直下に「.babelrc」を作って以下を書きます。

{
  "presets": [
    "es2015",
    "stage-0",
    "react"
  ],
  "plugins": [
    "add-module-exports"
  ]
}

webpack.config.js

プロジェクトフォルダ直下に「webpack.config.js」を作って以下を書きます。

require('babel-polyfill');
var path = require('path');
var webpack = require('webpack');

var DEBUG = !process.argv.includes('--release');

var plugins = [
  new webpack.optimize.OccurenceOrderPlugin(),
  new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"' + (process.env.NODE_ENV || (DEBUG ? 'development' : 'production')) + '"' })
];

if(!DEBUG){
  plugins.push(
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({ compress: { screw_ie8: true, warnings: true } }),
    new webpack.optimize.AggressiveMergingPlugin()
  );
}

module.exports = {
  cache: DEBUG,

  debug: DEBUG,

  stats: {
    colors: true,
    timings: true,
    hash: true,
    version: true,
    chunks: true,
    chunkModules: true,
    cached: true,
    cachedAssets: true,
    reasons: DEBUG
  },

  entry: [
    './src/js/app.js'
  ],

  output: {
    path: path.join(__dirname, 'public', 'assets'),
    filename: 'app.js',
    publicPath: '/assets/'
  },

  target: 'web',

  devtool: DEBUG ? 'cheap-module-eval-source-map' : false,

  plugins: plugins,

  module: {
    loaders: [
      {
        test: /\.js?$/,
        include: [path.resolve(__dirname, 'src/js')],
        loaders: ['react-hot', 'babel']
      },
      {
        test: /\.css$/,
        include: [path.resolve(__dirname, 'src/js')],
        loaders: ['style', 'css?modules'],
      },
    ]
  }
};

はっきり言ってまだwebpackの書き方理解していません(笑)

server.js

React Hot Loaderを使うためserver.jsを作り以下を記述します。

var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config.js');

config.entry.push(
  'webpack-dev-server/client?http://localhost:3000',
  'webpack/hot/only-dev-server'
);

config.plugins.push(new webpack.HotModuleReplacementPlugin());

console.log(config);

new WebpackDevServer(webpack(config), {
  publicPath: config.output.publicPath,
  hot: true,
  contentBase: 'public/',
  historyApiFallback: true
}).listen(3000, 'localhost', function (err, result) {
  if (err) {
    return console.log(err);
  }

  console.log('Listening at http://localhost:3000/');
});

これも書き方よく理解してないので、勉強します(笑)

package.jsonの修正

package.jsonの「script」のところに追記します。

// 省略
"scripts": {
  "start": "node server.js",
  "release": "webpack --release",
  "debug": "webpack",
  "test": "echo \"Error: no test specified\" && exit 1"
},
// 省略

動かしてみる

大した例ではないですが、Reactで文字を表示させるまでやってみます。

まずは、「public」ディレクトリを作って、その中にindex.htmlを作り以下を記述します。

public/index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="root"></div>
  <script type="text/javascript" src="assets/app.js"></script>
</body>
</html>

次に、「src」ディレクトリを作って、jsディレクトリを作ります。

その中にapp.jsを作ります。

src/js/app.js

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

import { Main } from './components/main.js';

ReactDOM.render(
  <Main/>,
  document.getElementById('root')
);

そして、コンポーネント単位でディレクトリを切って、その中にjsファイルとそのコンポーネント専用のcssファイルを作っていきます。

src/js/components/main.js

import React from 'react';
import { Sub } from '../subcomponents/sub.js';

import style from './style.css';

export class Main extends React.Component{
  render(){
    return(
      <span>
        <h1 className={style.normal_ttl}>Title</h1>
        <Sub />
      </span>
    );
  }
}

src/js/components/style.js

.normal_ttl {
  border-bottom: 1px solid #ddd;
  color: #666;
}

src/js/subcomponents/sub.js

import React from 'react';

import style from './style.css';

export class Sub extends React.Component{
  render(){
    return(
      <h1 className={style.subtitle}>Sub title</h1>
    );
  }
}

src/js/subcomponents/style.js

.subtitle {
  color: #666;
}

以上が完了したら、コマンドで以下を打ちます。

npm start

そして以下にアクセスすると表示されます。

http://localhost:3000

jsやcssを修正して、保存すると自動でブラウザが更新されます。
快適ですねー。

また、以下コマンドでpublic/assets以下にデバッグ用ファイルが作られます。

npm run debug

このコマンドで作られたapp.jsはAtomで開くとほぼ確実にクラッシュします。

そして、以下コマンドで圧縮されたapp.jsが作られます。

npm run release

まだこの構成でいいのかも分からないですし、理解できてないとこもあるので、まだまだ変更していくかもしれませんが、今のところこんな感じで。

ここが変だよっていうのがあれば、プルリクくれるとありがたいです。

React-starterkit

Pocket