はじめてのReact #19「開発環境を準備する」create-react-app編

ここまでご紹介してきたサンプルは学習やちょっとした検証には使えるのですが、実際に本番環境で動かすのには向いていません。というわけで今回は本番環境で動かすコードを作成するための開発環境を準備してみたいと思います。

Reactの開発環境

Node.jsのインストール

まず最初にNode.jsを入れる必要があるのですが、アップデートに対応しやすくするためバージョン切り替えが手軽に行えるツールをインストールした上でNode.jsの最新版を入れます。

MacやLinuxならnodebrew blog.katsubemakito.net

Windowsならnodist qiita.com

今回は以下のバージョンで構築を開始します。npmはNodejs用のパッケージマネージャーで、これを使って様々な便利ライブラリやツールをインストールすることができます。

$ node --version
v11.7.0
$ npm --version
6.5.0

create-react-appのインストール

Reactの開発環境をゼロから作ろうとすると中々に面倒なのですが、コマンド一発で必要な物を一式揃えてくれる便利ツールがfacebookより公式に提供されているので今回はこちらを利用してみます。 github.com

では先ほどインストールしたnpmコマンドを利用してこのcreate-react-appを入れます。npmを利用するとコマンド一発で入ります。

$ npm install -g create-react-app

今回は以下のバージョンが入りました。

$ create-react-app --version
2.1.3

開発サイクル

プロジェクトの作成

create-react-appに続きプロジェクト名を入力すると、プロジェクト名のフォルダが作成されその中に必要なファイルがガンガン生成されます。このコマンドの実行は数分かかりますので気長に待ちます。

$ create-react-app hello

実行が完了すると以下のようなファイルが生成されます。

隠しファイルになっているのでls -aコマンドなどを打たないと最初は気が付かないのですが、すでにGitのローカルリポジトリとなっており.gitignoreファイルも準備されています。気が利きますな!

$ ls -la hello
 total 1352
 drwxr-xr-x    10 katsube  staff     320  1 23 01:29 ./
 drwx------+   33 katsube  staff    1056  1 23 01:27 ../
 drwxr-xr-x    13 katsube  staff     416  1 23 01:29 .git/
 -rwxr-xr-x     1 katsube  staff     310 10 26  1985 .gitignore*
 -rwxr-xr-x     1 katsube  staff    2881 10 26  1985 README.md*
 drwxr-xr-x  1018 katsube  staff   32576  1 23 01:29 node_modules/
 -rw-r--r--     1 katsube  staff  676454  1 23 01:29 package-lock.json
 -rw-r--r--     1 katsube  staff     478  1 23 01:29 package.json
 drwxr-xr-x     5 katsube  staff     160  1 23 01:29 public/
 drwxr-xr-x     9 katsube  staff     288  1 23 01:29 src/

node_modulesディレクトリをのぞくと、ReactはもちろんBabelやESLintにWebpackなどが入ったことがわかります。 これでひとまず準備が概ね終わりました。あっという間でしたねw

それぞれのディレクトリやファイルの役割は以下の通り。

src/
開発で利用しているJavaScriptやCSSを置きます。基本的にこの中で開発を行っていきます。
public/
JavaScriptなどから直接利用しない画像やHTMLなどを置きます
node_modules/
インストールした外部のNode.js用のモジュールが入っています
package.json, package-lock.json
プロジェクトの設定ファイル
README.md
このプロジェクトの簡単な説明などを記述しておきます。
.gitignore
Gitに登録したくないファイルがあればここに記述します。
.git/
Gitのリポジトリを管理しているフォルダ。用がない限り触りません。

実行してみる

雛形が作成された際にも表示されているので気が付かれた方も多いと思いますが、現在のプロジェクトの実行はコマンド一発です。カレントディレクトリを移動し、npm startと打つだけです。

$ cd hello
$ npm start

するとビルドが開始され、ローカルで開発用HTTPサーバが起動、最終的にブラウザが起動しHTTPサーバへ自動的にアクセスされます。ビルドからサーバ起動にちょっとだけ時間がかかるので口笛でも吹きながら待ちます。

以下のような画面が表示されれば成功です。

ここで適当なテキストエディタでsrc/App.jsを開いてみましょう。これまで取り上げてきたコードと冒頭のimport部分が異なるだけであとはほぼ同じですね。

試しにLearn Reactの部分を適当な文字列に変更してみます。ここではLearnをEnjoyに変えました。

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Enjoy! React
          </a>
        </header>
      </div>
    );
  }
}

export default App;

src/App.jsを保存した瞬間に(実際には多少ラグはありますが)、ブラウザの表示が自動的に切り替わります。便利ですね!デュアルディスプレイにしておけば開発が捗るというものです。

注意点としては、Terminalにも表示されている通り、現時点では開発用にプレビューしているだけで、本番用のファイルはまだ出来上がっていません。

Note that the development build is not optimized. To create a production build, use npm run build.

開発用HTTPサーバはいったんCtrl+Cなどで停止しておきます。

テストコードを動かす

Facebook製のテストツールJestがデフォルトだと入っていますので、通常はこいつでユニットテストを行います。

TDDでの開発スタイルを前提として設定がされているらしく、常時バックエンドでJestが動き続けており、src配下のファイルを更新すると自動でユニットテストが動作するwatchモードで起動します。Jest用のTerminalウィンドウかタブを新たに開いてそこで動かすのが良さそうですね。自分のタイミングで行うこともできますのでご安心を。

コマンド一発で起動します。

$ npm test

Jestが起動すると以下のような選択を求めてきますので、いずれかのキーを押します。

キー 動作
a ファイルが更新される度にすべてのテストケースを実行
f "失敗"したテストケースのみを実行
t 指定したテストケースのみを実行
p 指定したテストファイルのみを実行
q watchモードを終了する
Enter watchモードではなく即時ユニットテストを実行する

今回は試しにaキーを押してみます。するとプロジェクト内のファイルからテスト用ファイルが検索され実行されます。今回はsrc/App.test.jsのみが該当しますので、このファイルのテストが実行されます。

すべてのテストが通れば以下のような表示になります。

ここでsrc/App.jsを更新すると自動的にテストが実行されます。上のTerminalでtouchコマンドを実行しファイルの更新日を現在の物にすると同時に、下のTerminalでJestが実行されているのがわかります。 https://youtu.be/2028egDCSe0

実際に実行するとわかるのですが、Jestは全部入りの重量級のツールなので起動が非常に遅く、毎回立ち上げるのはかなりストレスです。watchモードで裏側で起動しておくか、commit/pushと同時にJenkinsなどで自動的にテストするのがおすすめです。

本番用のファイルを作成する

では本番用のファイルをビルドしてみましょう。これもコマンド一発です。

$ npm run build

最終的に以下のようにCompiled successfully.とメッセージが表示されれば成功です。

Creating an optimized production build... Compiled successfully.

プロジェクト内に新たにbuildというフォルダが生成されているのでのぞいてみます。ここにあるファイルが本番用に最適化されたファイル郡になります。アプリが仕上がった段階でこいつをWebサーバなどにアップして公開することになります。

本番用のファイルをローカルで確認する

とはいえ、いきなり何の確認もなしにアップするのは恐ろしいので、まずは自分自身の環境で動作確認をしたいところなので、簡易的なWebサーバをインストールして動かしてみます。

Node.js製のserveコマンドをインストールします。今回は10.1.1が入りました。

$ npm install -g serve

$ serve --version
10.1.1

このserveコマンドに、先ほどbuildしたファイルがあるフォルダをオプションで渡してやります。

$ serve -s build

最後にTerminalで指定された通りlocalhost:5000にブラウザからアクセスすれば確認を行うことができます。

確認して問題なければ、Gitでコミットなどを行ったり、サーバにデプロイするなどすることになります。

Gitへpushする

GitHubなどのリモートリポジトリへpushしたい場合、最初の一回だけどこに送信するのかremoteの設定を行う必要があります。

今回はGitHubにhelloとう名前のリポジトリを作成しました。この下の方にあるコマンドを打ってやります。

言わずもがなですが2行目のgit pushした時点で実際にpushされます。

$ git remote add origin git@github.com:katsube/hello.git
$ git push -u origin master

念の為に以下のコマンドで登録状況を確認しておきます。

$ git remote -v
origin  git@github.com:katsube/hello.git (fetch)
origin  git@github.com:katsube/hello.git (push)

これ以降は普通にcommit/push/pullなどしてやることができます。

その他

build時に相対パスで出力したい

npm run buildすると通常は絶対パスでCSSやJavaScriptが呼び出されるHTMLが出力されます。これを相対パスに変更したい場合は、package.jsonhomepageという項目を追加してあげます。

package.jsonを適当なエディタで開きどこでも良いので追加します。ここでは一番下に記述しました。

{
  "name": "picbook",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-router-dom": "^5.0.0",
    "react-scripts": "2.1.8"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ],
 "homepage": "./"
}

これで、以下のように相対パスにすることができました。

<script src="./static/js/2.9aeef01b.chunk.js"></script>

もちろん./foo/などとディレクトリも指定すれば以下のようにパスも書き換わってくれます。

<script src="./foo/static/js/2.9aeef01b.chunk.js"></script>

TypeScriptで雛形を作成

プロジェクト名の後ろに--typescriptオプションをつけてあげればTypeScriptで雛形が作成されます。

$ create-react-app hellots --typescript

ご覧の通りです。

実行するコマンドはこれまでと同じです。

  • npm startでブラウザで確認、
  • npm testでユニットテスト、
  • npm run buildで本番用のファイルを作成

TypeScriptのオプションを付けない場合は、トランスパイラにBabelが利用されます。お好みのトランスパイラで開発が行えます。

裏側で動いているファイルを出現

create-react-appで作成した雛形には、必要最小限のファイルしか表には出てきません。初心者に優しくといった心遣いだと思うのですが、ある程度慣れてきたりcreate-react-appが死んで他のツールに移りたい場合など諸々カスタマイズがしたくなってくると思います。そんなときはコマンド一発で各種ファイルを出現させることができます。

$ npm run eject

途中で確認を求められたらYesと入力。

? Are you sure you want to eject? This action is permanent. Yes

すると新たにconfigディレクトリが作成され、その中に設定ファイルが生成されています。またscriptsディレクトリにはこれまでnpmコマンド経由で実行していたスクリプトも出現していますね。

$ ls
README.md*         config/            package-lock.json  public/            src/
build/             node_modules/      package.json       scripts/

$ ls config
env.js                      paths.js                    webpackDevServer.config.js
jest/                       webpack.config.js

Webpackなどの知識は必要になりますが、万が一の場合はこのコマンドを利用して脱出やカスタマイズを行うことになります。