i-Vinci TechBlog
株式会社i-Vinciの技術ブログ

React入門 第1回 Webpackを使ってみよう

React入門 第1回 Webpackを使ってみよう

こんにちは!元自衛官エンジニアの藤田です!
リモートワークの成果がおなか周りのお肉に積み上げられてきています!
そういうわけで最近のマイブームは、セ〇ン〇レブ〇の炭酸水(レモン味)です。ネットスーパーで箱で買って飲んでいます。さっぱりしていて飲みやすいところが好きですね!

さて皆さん、Reactを触ったことありますか?
私は最近、ちょっと触ってみようかなという感じでReactのお勉強を始めました。そのお勉強の成果をまとめる形でReactの入門シリーズを書いていこうと思っています。想定する読者層としては、HTML, JavaScript, CSSをちょこっとお勉強で触ったことはあるけど、フロントエンドの開発でReactは触ったことはない人です。

  1. Webpackを使ってみよう
  2. State, Propって何ですか?
  3. Hooks APIって何なんですか?いったい!
  4. Class Component vs. Functional Component 両方の書き方を試してみよう
  5. コンポーネントのライフサイクルって、ちょっと何ですか?え、なに?
  6. Material UIって?ちょっと何がしたいの?
  7. TypeScriptで書いてみよう
  8. Styled Componentで書いてみよう
  9. Redux, Redux-Saga、って何ですか?イヤイヤ、こわっ!
  10. ちょっとアプリを作ってみよう(3~4回程度に回を分けるかもです)

のような感じで回を重ねようかなと考えていますが、しれっと内容は変わるかもです。(私の気分で!)

私はJavaをちょこっと触ったことあるという感じなのですが……フロントエンドって、なんだかいろいろあって大変そうですね!!
分からないことが1個や2個ではないこの感じ。どこから手を付けたらいいのかNA・YA・MU!!というかWA・KA・RA・NA・I!!

Twitterで偉い人の知り合いのサーファーの友達が言っていたらしいのですが、「新しいことを始める時は1個ずつがいいよ。多くても2個。3個以上一緒に新しいことを始めるのはやめたほうがいい。……たぶん」

なんとなく説得力がありますね!そんな感じでいきましょう!
本記事はその第1回として「Webpackを使ってみよう」です。

Webpackとは

公式サイトはこちらです。

Webpackを使用する目的としては、上記のコンセプトイメージのとおりです。
Webpackを利用することで、JavaScriptやCSS、PNG/JPGなどを依存関係をもとに、いい感じにまとめる(bundle)することが出来ます。
このあたりを見た感じだと、指定されたエントリーポイントとなるモジュールを基準として、Webpackの内部でDependency Graph(依存関係グラフ)という解析を行って、いい感じにbundleしてくれるみたいですね!(いい感じにって便利ですね!)

加えてWebpackでは、「webpack-dev-server」や「Hot Module Replacement(HMR)」などの便利機能を提供してくれているみたいですね。そこはかとなくいい感じですね!

Create React App

実は、とりあえずReactを書くというだけなら、みんな大好きCreate React Appを使う手もあります。しかし、あれは便利すぎてフロントエンド初心者が手を出すと、「とりあえずはReactを書けるけど、ビルドするとかリリースするとかになると何をしていいのか分からないおじさん」を大量生産してしまう代物だなと個人的に思っています。
使っている道具が何をしているのかさえ隠蔽できてしまっているほどに便利です。
(余談ですが、昨今のプログラミング学習の環境って全体的に便利すぎて、どの言語もそこらへんの理解をする機会が減っているような気がします。私が子供の時は入門書にC言語のコンパイラが入ったCDがついていたりしました。人によってはそれすらも便利な時代じゃないか!と憤る方もいらっしゃるかもしれませんが(笑))

なので今回はWebpackを使った開発環境を整えるところをReact入門の第1回としました。

それでは実際に必要な環境やファイルなどを準備しながら、Reactの開発環境を整えつつ理解を進めてみましょう。

開発環境構築

Node.jsインストール

まずは、Node.jsをインストールしましょう。特にこだわりがないのであれば、LTSを使用するようにしてください。Node.js公式

インストールが完了したら、ターミナルを開いてNode.jsがインストールされていることを確認しましょう。

node --version
> v14.18.0

今回は、10月3日時点で最新のLTSであるv14.18.0をインストールしています。

npm init => package.json

次に、reactのアプリを作っていくディレクトリを作成し、アプリの依存関係や開発やビルドのためのスクリプトを定義するファイル(package.json)を作成していきましょう。
ターミナルを開いて次のようにコマンドをカタカタ打っていきます。

cd <アプリを作成するディレクトリ>
mkdir front-app-react-beginner
cd front-app-react-beginner
npm init

npm initを叩くといくつかの質問が出ますのでいい感じに入力していきます。

package name: (front-app-react-beginner)
version: (1.0.0)
description: Reactの勉強用プロジェクト
entry point: (index.js)
test command:
git repository: Some Repository
keywords:
author: Yoshihiro Fujita
license: (ISC)

このように入力することで、作成したfront-app-react-beginnerディレクトリにpackage.jsonというファイルが生成されます。

今後利用したいライブラリをこのディレクトリでnpm installすると、devDependenciesdependenciesが更新されていき、このアプリで使用するライブラリが記録されていきます。

npm install

npm installというコマンドを使って開発に必要なライブラリを導入していきます。

今回は大きく分けて次のようなカテゴリのライブラリを導入していきます。

  1. Babel: "新しいJavaScript"を"古いブラウザ"(実行環境)でも理解できるようにコンパイルしてくれます。
  2. Webpack: .js, .jsx, .css, .png, .svgなどの多種多様なファイルをloaderによっていい感じにまとめてくれるほか、開発に便利な機能(webpack-dev-serverやHot Module Replacement)などを提供してくれます。
  3. React: 状態を持った画面を宣言的に書くことが出来るようになる便利ライブラリ。今回の本命ですね!

Babel

はい、ではBabelを入れましょう!次のようにコマンドを叩いてください。
(npm inpm installと同じ意味です)

npm i --save-dev @babel/core @babel/cli @babel/preset-env @babel/preset-react

インストールが完了したら、プロジェクトルート(package.jsonと同じ階層)に.babelrcというファイルを作成して、次の内容を記載してください。

{
  "presets": ["@babel/env", "@babel/preset-react"]
}

これによりBabelが@babel/envと@babel/preset-reactをコンパイル時に使うんだなということを理解してくれます。

現段階で、front-app-react-beginnerディレクトリはこんな感じになっていると思います。どうでしょうか?

-front-app-react-beginner/
 |- node_modules/
 |- .babelrc
 |- package-lock.json
 |- package.json

Webpack

さて、Webpackを導入しましょう!次のようにコマンドを叩いてください。

npm i --save-dev webpack webpack-cli webpack-dev-server style-loader css-loader babel-loader

これによりいい感じにファイルをまとめてくれる(bundleしてくれる)Webpackが使えるようになりました!

さらにwebpack.config.jsというファイルをプロジェクトルート(package.jsonと同じ階層)に作成し、次の内容を記載してください。

const path = require("path");

module.exports = {
  entry: "./src/index.jsx",
  mode: "development",
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        loader: "babel-loader",
        options: {
          presets: [
            "@babel/env",
            "@babel/preset-react",
          ]
        }
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/,
        type: "asset/resource",
      }
    ]
  },
  resolve: { extensions: ["*", ".js", ".jsx"] },
  output: {
    path: path.resolve(__dirname, "dist/"),
    filename: "bundle.js"
  },
  devServer: {
    static: "./dist",
    port: 3000,
    hot: true
  },
};

簡単に解説をすると、

  • entry: プログラムのエントリーポイントとDependency Graphの基準となるモジュールをWebpackに教えます。今回はindex.jsxです。
  • mode: 'development'モードであることを示します。'development' or 'production'のフラグを使用するときに必要になります。デフォルトでは'production'が設定されていてbundleの最適化が行われ"より軽く"なるのですが、不具合などが追いにくくなる場合もあるため開発時にはmodeをdevelopmentに設定します。参考
  • module.rules: .js, .jsx, .css, png, etc...などのファイルごとにbundleするルールを定義します。どのファイル(拡張子)の時にどのloaderを使用するのかを指定します。画像についてはWebpack 5のビルトインであるAsset Modulesを使用します。(Webpack 4以前のfile-loaderに相当)
  • resolve: 拡張子なしでのimportできるファイルの種類を指定します。
  • output: bundleした成果物を出力する場所を指定します。
  • devServer: webpack-dev-serverをどのように使うか定義します。staticによりプロジェクトルート配下のどのディレクトリのファイルをどのポートで公開するか定義します。hot: trueでHot Module Replacementを使用することをWebpackに教えます。

package.jsonの修正と.gitignoreの追加

Reactのインストールに進む前に、package.jsonの修正と.gitignoreの追加(git initしてるなら)を行っておきたいと思います。
以下2点を行ってください。

  1. webpack.config.jsによりエントリーポイントを指定したので、package.jsonの"main": "index.js"は不要です。削除しましょう。
  2. プロジェクトルートに.gitignoreファイルを作成し、以下の内容を記載してください。(node_modulesの中身であったり、buildの成果物は基本的にソース管理用のリポジトリにcommit不要だと思うので)
node_modules
package-lock.json
/dist/bundle.*

また、package.jsonscriptsに以下の内容を追記してください。
これによりnpm run buildのコマンドでビルドを、npm run devのコマンドでローカル環境での実行を行う事が出来ます。

"scripts": {
  "test": "echo \"Error: no test specified\" && exit 1",
  "build": "webpack --mode development",
  "dev": "webpack serve --open"
}

React

はい、いよいよReactをインストールしていきましょう!次のようにコマンドを叩いてください。

npm i --save-dev react react-dom

ほい、これでReactがこのプロジェクトで使えるようになりました。

dist/index.html, components/App.jsx, css/App.cssの作成

さぁ、いよいよ開発環境の準備の最後になります。

まずは、プロジェクトのディレクトリ構成を以下のように整理して、ファイルを作成してください。ファイルの内容についても記載します。

index.jsx


import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";

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

components/App.jsx


import React from "react";
import "../css/App.css";
import imgFunReact from "../img/fun_react.png";

const App = () => {
  return (
    <div className={"app_wrapper"}>
      <h1>Hello React with Webpack</h1>
      <img
        src={imgFunReact}
        alt=""
      />
    </div>
  );
};

export default App;

css/App.css


.app_wrapper {
  color: #ffffff;
  background-color: #414141;
  text-align: center;
}

img/fun_react.png


何か好きな画像を適当に入れてください。
今回はこんな画像を入れました。

dist/index.html


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My React App</title>
</head>
<body>
  <div id="root"></div>
  <script src="bundle.js"></script>
</body>
</html>

はい、これで開発環境の準備は完了です。
長かったですね(笑)

動作確認

はい、では作成したアプリの動作確認をしてみましょう。

起動

ターミナルを開いて以下のようにコマンドを叩いてみてください。

npm run dev

しばらくしてブラウザに次のような画面が表示されたら環境構築成功です。

ちょこっと修正

Hot Modules Replacementがどんな感じなのか見てみましょう。
まずは、アプリが表示されているブラウザの開発者コンソールを開いてConsoleタブを選択して、次のような画面が表示されているか確認します。([Ctrl + Shft + I]が便利です。)

期待通りにHMRが動いているようならば、ちょこっとアプリを修正して保存したときに、ブラウザに自動的に変更分が反映されるか試してみましょう。

App.jsxのimgタグのすぐ後に下のように修正を行って保存してみます。

import React from "react";
import "../css/App.css";
import imgFunReact from "../img/fun_react.png";

const App = () => {
  return (
    <div className={"app_wrapper"}>
      <h1>Hello React with Webpack</h1>
      <img
        src={imgFunReact}
        alt=""
      />
      <h2>Done is Better than Perfect.</h2>
    </div>
  );
};

export default App;

下図のように変更が反映されたならば、Hot Modules Replacementもうまく動いているといえるでしょう。

ビルドも確認

動作確認の最後として、ビルドも試してみましょう。

ターミナルを開いて次のようにコマンドを叩いてみてください。

npm run build

しばらくするとプロジェクトルートのdistディレクトリが以下のようになっていると思います。

807c19a.....pngがpng画像を展開したもので、bundle.jsがReactのソースコードをスタイルを設定したCSSも含めてbundleしたものになります。

例えば、今回作成したアプリを外部に公開しようとするならば、build後にdistディレクトリに展開されているindex.html, bundle.js, 807c19a.....pngをしかるべき場所にホスティングしてあげれば大丈夫です。

どうでしょうか?Webpackって便利ですね。

まとめ

今回はWebpackを中心にして、Reactの開発環境を構築しました。各種ファイルがいい感じにbundleされる様を確認できたと思います。
また、Webpackの便利機能であるwebpack-dev-serverHot Modules Replacementについても開発環境に取り込み、動作を確認しました。今後の開発が効率よく進められると思います。

次回以降は、Reactを実際に書いてみてstateやpropへの理解を深めていきたいと思います。