113
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

React入門 - Part2: Browserify/Reactify/Gulpを使う

前回作成したhelloworldはブラウザでJSXTransformerを読み込みオンラインでjsにコンパイルしていました。実行時にChromeのデベロッパーツールに表示されるように、予めJSXはコンパイルすることが推奨されています。コンパイルの方法は、jsxコマンドを使う方法、 BrowserifyReactifyを使う方法、最後にGulpのタスクでまとめる方法を順番に試してみます。

Getting Startedの復習

作成したhelloworld.jsxを少し修正してコンポーネントを作り構成してみます。ディレクトリ構成は以下です。

$ cd ~/react_apps/helloworld/
$ mkdir src dist
$ mv helloworld.jsx src/
$ tree .
.
|-- dist
|-- index.html
`-- src
    `-- helloworld.jsx

Nameコンポーネントは作成時にプロパティを指定しています。nameプロパティは{this.props.name}として参照できます。

~/react_apps/helloworld/src/helloworld.jsx
var Name = React.createClass({
  render: function() {
    return (
      <span>{this.props.name}</span>
    );
  }
});
var HelloWorld = React.createClass({
  render: function() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <Name name="Masato" />
      </div>
    );
  }
});
React.render(
  <HelloWorld />,
  document.getElementById('example')
);

jsxファイルのパスも変更します。

~/react_apps/helloworld/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Hello World</title>
    <script src="http://fb.me/react-0.12.2.js"></script>
    <script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
    <script type="text/jsx" src="./src/helloworld.jsx"></script>
  </head>
  <body>
    <div id="example"></div>
  </body>
</html>

SimpleHTTPServerを起動します。

$ python -m SimpleHTTPServer 8080

Dockerコンテナで作業しているので、ngrokでトンネルします。

$ docker run -it --rm wizardapps/ngrok:latest ngrok 172.17.1.157:8080

ブラウザから確認します。ngrokのURLはランダムです。
http://684baaf0.ngrok.com

jsxコマンドを使う

Browserfyを使う前に、Getting Startedに書いてあるjsxコマンドを試してみます。react-toolsをnpmでインストールします。

$ npm install -g react-tools

jsxコマンドでsrcディレクトリにあるjsxファイルを、buildディレクトリにJavaScriptとしてコンパイルします。ファイルの拡張子をjsxにしているので、-xフラグの指定が必要です。

$ cd ~/react_apps/helloworld/
$ jsx -x jsx src/ dist/
built Module("helloworld")
["helloworld"]

jsファイルのロードをbodyに移動します。JSXTransformerも予めjsにコンパイルして不要になったので削除します。

~/react_apps/helloworld/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Hello World</title>
    <script src="http://fb.me/react-0.12.2.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <script src="./dist/helloworld.js"></script>
  </body>
</html>

ngrok経由でトンネルして、ブラウザで確認します。
http://684baaf0.ngrok.com/

BrowserifyとReactifyを使う

Browserifyブラウザ上でもNode.js用モジュールを使えるようにするライブラリです。ReactifyはJSX用のtransform moduleです。npmコマンドを使い、プロジェクトのディレクトリにBrowserify と Reactifyをインストールします。

$ cd ~/react_apps/helloworld
$ npm install react browserify reactify

jsxファイルでNode.jsと同じようにreactモジュールをrequireします。

/react_apps/helloworld/src/helloworld.jsx
var React = require('react');
var Name = React.createClass({
  render: function() {
    return (
      <span>{this.props.name}</span>
    );
  }
});
var HelloWorld = React.createClass({
  render: function() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <Name name="Masato" />
      </div>
    );
  }
});
React.render(
  <HelloWorld />,
  document.getElementById('example')
);

requireでモジュールを読み込んでいるので、index.htmlファイルからreact.jsのロードを削除します。

~/react_apps/helloworld/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Hello World</title>
  </head>
  <body>
    <div id="example"></div>
    <script src="./dist/helloworld.js"></script>
  </body>
</html>

browserifyコマンドに-tフラグでreactifyモジュールを指定し、jsxファイルをjsにコンパイルします。生成されたhelloworld.jsをscript要素でロードすると、ブラウザでもNode.jsのモジュールが使えるようになります。コンパイルされたjsファイルはrequireしたreactモジュールもまとめて1つのファイルになっています。

$ browserify -t reactify src/helloworld.jsx > dist/helloworld.js

ngrok経由でトンネルして、ブラウザで確認します。
http://684baaf0.ngrok.com/

Gulpを使う

Gulpは手続き型で設定ファイルを記述する、タスクランナー&ビルドツールです。Gulpを使うため、少しリファクタリングします。

$ cd ~/react_apps/helloworld-gulp
$ tree .
.
|-- dist
|-- gulpfile.js
|-- index.html
`-- src
    |-- main.js
    `-- view.jsx

npmコマンドでGulpをグローバルにインストールします。

$ npm install -g gulp

npmコマンドでモジュールをローカルにインストールします。gulpはローカルのプロジェクトにインストールされたモジュールを使います。

$ npm install gulp react browserify reactify vinyl-source-stream

gulpfile.jsを作成します。reactifyでtransformしたjsファイルは、./dist/app.jsに出力されます。

~/react_apps/helloworld-gulp/gulpfile.js
var gulp = require('gulp');
var browserify = require('browserify');
var source = require("vinyl-source-stream");
var reactify = require('reactify');

gulp.task('browserify', function(){
  var b = browserify({
    entries: ['./src/main.js'],
    transform: [reactify]
  });
  return b.bundle()
    .pipe(source('app.js'))
    .pipe(gulp.dest('./dist'));
});

helloworld.jsxファイルをリファクタリングして、main.jsとview.jsxファイルに分割します。

~/react_apps/helloworld-gulp/src/main.js
var React = require('react');

var view = require('./view.jsx');
React.renderComponent(
  view(),
  document.getElementById('content')
);

view.jsxは、HelloWorldコンポーネントをmodule.exportsに代入して公開して、main.jsから参照できるようにします。

~/react_apps/helloworld-gulp/src/view.jsx
var React = require('react');
var Name = React.createClass({
  render: function() {
    return (
      <span>{this.props.name}</span>
    );
  }
});
var HelloWorld = React.createClass({
  render: function() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <Name name="Masato" />
      </div>
    );
  }
});
module.exports = HelloWorld;

index.htmlでは、gulp browserifyタスクで1つにコンパイルした./dist/app.jsファイルをロードします。

~/react_apps/helloworld-gulp/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Hello World</title>
  </head>
  <body>
    <div id="content"></div>
    <script src="./dist/app.js"></script>
  </body>
</html>

gulp browserifyタスクを実行してJSXのコンパイルとrequireしたモジュールなどをまとめます。

$ gulp browserify
[13:47:57] Using gulpfile ~/react_apps/helloworld-gulp/gulpfile.js
[13:47:57] Starting 'browserify'...
[13:47:59] Finished 'browserify' after 2.03 s

ngrok経由でトンネルして、ブラウザで確認します。
http://684baaf0.ngrok.com/

package.jsonを作成する

新しい環境でも同じモジュールがインストールできるように、package.jsonを作成してプロジェクトの情報を記述しておきます。最初にマニュアルでインストールしたnode_modulesを削除します。

$ cd ~/react_apps/helloworld-gulp
$ rm -fr node_modules/

npm initコマンドを実行して、対話的にpackage.jsonを作成します。GitHubのリポジトリも自動で入れてくるので、入力した値はauthorだけでpackage.jsonファイルを作成できました。

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (helloworld-gulp)
version: (1.0.0)
description:
entry point:
test command:
git repository: (https://github.com/masato/helloworld-gulp.git)
keywords:
author: Masato Shimizu
license: (ISC)
About to write to /home/docker/react_apps/helloworld-gulp/package.json:

{
  "name": "helloworld-gulp",
  "version": "1.0.0",
  "description": "",
  "main": "",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/masato/helloworld-gulp.git"
  },
  "author": "Masato Shimizu",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/masato/helloworld-gulp/issues"
  },
  "homepage": "https://github.com/masato/helloworld-gulp"
}


Is this ok? (yes) yes

前回は--save-devフラグを付けませんでしたが、package.jsonのdevDependenciesに設定が書かれるように、npm installするときは--save-devを忘れずつけます。

$ npm install --save-dev gulp react browserify reactify vinyl-source-stream

package.jsonを確認すると、devDependenciesが追加されました。

~/react_apps/helloworld-gulp/package.json
...
  "devDependencies": {
    "browserify": "^8.0.2",
    "gulp": "^3.8.10",
    "react": "^0.12.2",
    "reactify": "^0.17.1",
    "vinyl-source-stream": "^1.0.0"
  }
}

package.jsonをリポジトリに追加して、GitHubにpushしておきます。

git cloneし直す

GitHubにpushしたリポジトリを別のディレクトリにcloneして動作確認をします。

$ cd ~/react_apps
$ git clone https://github.com/masato/helloworld-gulp.git gulp-test

プロジェクトのディレクトリに移動して、npm installを実行してローカルにモジュールをインストールします。gulp browserifyタスクを実行してJSXファイルをコンパイルします。

$ cd gulp-test
$ npm install
$ gulp browserify

ローカルでSimpleHTTPServerを起動します。

$ python -m SimpleHTTPServer 8080

ブラウザから動作確認します。
http://684baaf0.ngrok.com/

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
113
Help us understand the problem. What are the problem?