4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ブラックボックスにならないReact導入

Last updated at Posted at 2020-03-26

概要

React公式サイトのチュートリアルでは、React入門者に対してcreate-react-appコマンドによりReactのプロジェクトを作成することを勧めています。このコマンドを実行することで簡単にReactの実行環境が整います。しかし、このコマンドの裏では沢山の処理が動いており、Reactやフロントエンド初心者にとって、Reactの内部がブラックボックスになる原因になっていると思います。
そこで、この記事ではcreate-react-appコマンドを使わずにcreate-react-appを使うのと変わらないような開発環境を構築することを目指します。

事前準備

Node.JSのインストール

npmコマンドが使えるようにNode.JSをインストールして下さい。Node.JSのインストールは良い解説が他に沢山あるので、この記事では解説しません。

npmのプロジェクトの作成

これから作業を行うnpmのプロジェクトを作成します。
npm initコマンドを使うことで、カレントディレクトリをnpmのプロジェクトにすることができます。ディレクトリの名前は何でも構いません。
例ではmy-react-sampleという名前にしています。

コンソール
mkdir my-react-sample

cd my-react-sample

npm init

webpackの導入と動作確認

以下の手順ではwebpackの公式チュートリアルを参考にwebpackの導入を進めます。
webpackとはJavaScript言語用の依存関係解決ツールのようなものです。Javaでのgradle/groovyやC++でのCMakeに近いと思います。
基本的にReactはwebpackとセットで使われます。

webpackのインストール

webpackwebpack-cliをインストールします。

コンソール
npm install --save-dev webpack webpack-cli

ファイルの作成

webpackの動作確認のために以下のようにindex.htmlindex.jsとディレクトリを作成します。

  myReactSample
  |- package.json
+ |- /dist
+   |- index.html
+ |- /src
+   |- index.js

このような階層になるように作ります。

index.htmlの内容を作成

index.htmlを以下のようにしてください。

dist/index.html
<!doctype html>
<html>
  <head>
    <title>Getting Started</title>
  </head>
  <body>
    Hello!
  </body>
</html>

index.htmlファイルをブラウザで開くと、当然Hello!と表示されます。

index.jsの内容を作成

index.jsを以下のようにしてください。

src/index.js
function component() {
  const element = document.createElement('div');
  element.innerHTML = "Webpack!"
  return element;
}

document.body.appendChild(component());

body<div>Webpack!</div>を追加しているだけですね。

index.htmlからmain.jsを読み込む

main.jsを読み込むために、index.htmlに以下のように<script src="main.js"></script>を追加しています。

dist/index.html
<!doctype html>
<html>
  <head>
    <title>Getting Started</title>
  </head>
  <body>
    Hello!
    <script src="main.js"></script>
  </body>
</html>

webpackではデフォルトでsrc/index.jsを入力としてdist/main.jsに依存関係が解決されたJavaScriptファイルを出力します。これをwebpackによるビルドと言います。
dist/index.htmlからビルド成果物であるdist/main.jsを読み込むことでプログラムを動かすことが出来ます。
index.htmlmain.jsの両方ともdistディレクトリ内であるため、相対パスでmain.jsを指定して読み込めばよいです。

webpackでのビルド

以下のコマンドを打ち込むと、src/index.jsdist/main.jsにビルドされます。

コンソール
npx webpack
  myReactSample
 |- package.json
 |- /dist
   |- index.html
+  |- main.js
 |- /src
   |- index.js

このような階層になっているはずです。この状態でindex.htmlをブラウザで開くとHello!の下にWebpack!が表示されるはずです。

正しく表示されたなら、Webpackの導入は成功です。おめでとうございます!次にWebpack DevServerの導入を行います。

Webpack DevServerの導入と動作確認

Webpack DevServerとは、プロントエンド開発用に開発PC上で立ち上げる、ローカルのHTTPサーバーです。JavaScriptファイルを更新した際に自動でWebPackのビルドの実行とページの更新を行ってくれるので非常に便利です。ちなみに、create-react-appコマンドを使った際は自動で入ります。

Webpack DevServerのインストール

以下のコマンドでWebpack DevServerをインストールします。

コンソール
npm install --save-dev webpack-dev-server

プロジェクトのルートにwebpack.config.jsを作ります。

  myReactSample
 |- package.json
+|- webpack.config.js
 |- /dist
   |- index.html
   |- main.js
 |- /src
   |- index.js

webpack.config.jsを以下のように編集します。

webpack.config.js
var path = require('path');

module.exports = {
  mode: 'development',
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000
  }
};

これはwebpackの設定ファイルです。
まず、webpackのビルドをdevelopmentモードに指定しています。
また、devServer内でWebpack DevServerがホストするコンテンツのディレクトリの指定やportの指定などをしています。

Webpack DevServerの動作確認

コンソールでWebpack DevServerを起動します。

コンソール
npx webpack-dev-server

localホストでサーバーが起動します。9000番ポートを指定してブラウザで開いて下さい。
うまく行かない場合はwebpack.config.jsでコロンが足りないなどでエラーになっている事があります。

正しく設定が出来ると、index.jsを編集して更新した時に自動でリビルドとページの更新処理が行われます。

コンテンツ監視の設定

デフォルトの設定では、JavaScriptファイルを更新した時のみページの更新が行われます。HTMLファイルやCSSファイルの更新時にもページの更新が行われるようにするために、コンテンツ監視の設定をします。
以下のようにdevServer:の中にwatchContentBase: trueを追記してください。

webpack.config.js
var path = require('path');

module.exports = {
  mode: 'development',
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000,
    watchContentBase: true
  }
};

追記した後、コンソールでWebpack DevServerを再起動します。Ctrl + cしてから、以下のコマンドを実行して起動します。

コンソール
npx webpack-dev-server

すると、jsファイルだけでなく、htmlファイルを更新した際も自動でページの更新が行われるようになります。

ここまで上手く行けばWebpack DevServerの導入は成功です!次にbabelの導入を行います。

babelの導入

babelのインストール

ReactではJSXという特殊なJavaScript拡張構文を使います。JSXを使えるようにするためにJSトランスパイラであるbabelを導入します。

コンソール
npm install --save-dev @babel/core babel-loader @babel/polyfill @babel/preset-env @babel/preset-react 

webpack.configの変更

babelの利用をwebpack.configファイルのrules内で指定します。

webpack.config.js

var path = require('path');

module.exports = {
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: "babel-loader",
            options: {
              presets: [
                "@babel/preset-env",
                "@babel/react"
              ]
            }
          }
        ]
      }
    ]
  },
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000,
    watchContentBase: true
  }
};

この状態でnpx webpackコマンドを使ってビルドすることが出来れば、babelの導入は成功です!

Reactの導入

いよいよReactを導入します!ReactはJavaScriptのライブラリとして提供されています。まずはインストールします。

Reactのインストール

Reactはdevelopment環境だけでなくproduction環境でも必要であるため、--save-devオプションではなく--saveオプションを適用します。

コンソール
npm install --save react react-dom

Reactを使う!

Reactは指定したidを持つDOM要素とその子要素を支配するという形で動作します。今回はrootというid名を指定することにします。
index.htmlに<div id="root"></div>を追加します。

dist/index.html
<!doctype html>
<html>
  <head>
    <title>Getting Started</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="main.js"></script>
  </body>
</html>

index.jsでも同じidを指定します。ファイルの最後の方にある、ReactDOM.render内で指定しています。

dist/index.js
import React from 'react'
import ReactDOM from 'react-dom'

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    )
  }
}

function App() {
  return (
    <div>
      <Clock />
      <Clock />
      <Clock />
    </div>
  )
}

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

このコードはReactの公式チュートリアルのstateとライフサイクルで紹介されているものです。時刻が更新され続ける文字が表示されたらReactの導入は成功です!お疲れ様でした!

TypeScriptの導入

静的言語で開発したくなる時があるのでTypeScriptでReactを使えるようにします。

TypeScriptのインストール

コンソール
npm install --save-dev typescript ts-loader

tsconfigの作成

TypeScriptの設定ファイルであるtsconfig.jsonファイルを作成します。

  myReactSample
 |- package.json
 |- webpack.config.js
+|- tsconfig.json
 |- /dist
   |- index.html
   |- main.js
 |- /src
   |- index.js

以下のように編集します。

tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es5",
    "module": "es2015",
    "jsx":"react"
  }
}

webpack.configの編集

TypeScriptトランスパイラの利用などをwebpack.configファイルで指定します。

webpack.config.js
var path = require('path');

module.exports = {
  mode: 'development',
  entry: "./src/index.tsx",
  module: {
    rules: [
      {
        test: /\.tsx$/,
        use: "ts-loader"
      }
    ]
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js"]
  },
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000,
    watchContentBase: true
  }
};

index.jsのリネーム

拡張子を".tsx"とすることで、TypeScriptのトランスパイラがJSX構文を扱うことが出来るようになります。

  myReactSample
 |- package.json
 |- webpack.config.js
 |- tsconfig.json
 |- /dist
   |- index.html
   |- main.jsx
 |- /src
+  |- index.tsx
-  |- index.js

型定義ファイルのインストール

reactとreact-domをTypeScriptから使うために、それぞれの型定義ファイルをインストールします。

コンソール
npm install --save-dev @types/react @types/react-dom

JavaScriptファイルをTypeScriptファイルに書き換える

  • import文の書き換え
  • Props, Stateインターフェースの定義
  • Clockクラスが継承するクラスをReact.ComponentからReact.Component<Props, State>へ変更

などを行っています。

index.jsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';

interface Props {
}

interface State {
  date: Date
}

class Clock extends React.Component<Props, State> {
  timerID: any
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    )
  }
}

function App() {
  return (
    <div>
      <Clock />
      <Clock />
      <Clock />
    </div>
  )
}

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

webpackビルド

コンソール
npx webpack

ビルドでエラーが出る場合はエラーメッセージを元に修正して下さい。

Webpack DevServerでのホスト

ビルドエラーが出なくなったらWebpack Devserverを起動します。

コンソール
npx webpack-dev-server

TypeScript導入前と同じように、時刻が更新され続ける文字が表示されたらTypeScriptの導入は成功です!お疲れ様でした!

導入完了!

以上でReact、Webpack、Webpack DevServer、Typescriptの導入が完了しました!モダンなWeb開発はブラックボックスになりがちですが、一つずつ順番に導入することで裏側で何が動いているのか少しは明らかに出来たのではないかと思います!

Reactの初心者の方は、この後Reactの公式チュートリアルを進めてReactに慣れると良い思います。

既にある程度Reactに詳しい人は、WebpackやTypescriptのconfigファイルの設定一覧を見てみると良いと思います。今回の記事ではシンプルな設定にしましたが、設定できる便利な機能が沢山あります。

4
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?