WebpackとBabelによるReact/TypeScript開発環境の構築方法

本記事では、webpackBabel を用いて、ReactとTypeScriptを使ったモダンなWebアプリケーション開発環境をゼロから構築する手順を解説します。

Webpackとは

Webpack は、JavaScriptアプリケーションのためのモジュールバンドラーです。複数のJavaScriptファイルやその他のアセット(CSS、画像など)を依存関係に基づいて解析し、ブラウザで実行可能な単一または複数のファイルにまとめます。

  • 主な機能:
    • モジュール解決: importrequire などの構文を解釈し、依存関係を解決します。
    • バンドル: 複数のファイルを一つにまとめます。
    • トランスパイル: Babelなどのローダーと連携し、新しいJavaScript構文を古いブラウザでも動作するように変換します。
    • 最適化: コードの圧縮、不要なコードの削除など、パフォーマンス向上のための最適化を行います。

Babelとは

Babel は、JavaScriptのトランスコンパイラーです。主に、最新のJavaScript(ES2015+)で書かれたコードを、古いブラウザや実行環境でも動作する互換性のあるJavaScript(ES5など)に変換するために使用されます。

  • 主な機能:
    • 新しい構文の変換: async/await, アロー関数、クラス構文などを変換します。
    • JSXの変換: ReactのJSX構文を通常のJavaScriptに変換します。
    • TypeScriptの変換: TypeScriptコードをJavaScriptに変換します(型チェックは行いません)。

環境構築

以下の記事を参考に、React/TypeScript開発環境を構築します。

必要なモジュールのインストール

プロジェクトディレクトリを作成し、npmで初期化します。

mkdir react_test
cd react_test

# プロジェクトの初期化
npm init -y

# Babel関連モジュール
npm install -D @babel/core          # Babel本体
npm install -D @babel/preset-env    # 最新のJS構文をターゲット環境に合わせて変換
npm install -D @babel/preset-react  # ReactのJSXを変換
npm install -D @babel/preset-typescript # TypeScriptを変換

# Webpack関連モジュール
npm install -D webpack webpack-cli babel-loader ts-loader # webpack本体とCLI、Babel/TSをwebpackで扱うためのローダー
npm install -D webpack-dev-server html-webpack-plugin     # 開発サーバーとHTML生成プラグイン

# ReactとTypeScript関連モジュール
npm install react react-dom         # React本体とDOM操作ライブラリ
npm install -D typescript @types/react @types/react-dom # TypeScript本体とReact/ReactDOMの型定義

# tsconfig.json の生成
npx tsc --init

ファイル構成

最終的なファイル構成は以下のようになります。

.
├── dist/
│   ├── index.html
│   └── main.js
├── node_modules/
├── package-lock.json
├── package.json
├── src/
│   ├── index.html
│   └── index.tsx
├── tsconfig.json
└── webpack.config.js

各種設定ファイル

src/index.html

ReactアプリケーションのエントリポイントとなるHTMLファイルです。div 要素にReactコンポーネントがマウントされます。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React App</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- WebpackによってバンドルされたJavaScriptがここに自動的に挿入される -->
  </body>
</html>

src/index.tsx

Reactアプリケーションのメインエントリファイルです。TypeScriptとJSXで記述されます。

import React from "react";
import { createRoot } from "react-dom/client"; // React 18からcreateRootを使用

const App = () => {
  return <h1>Hello React with TypeScript!</h1>;
};

// React 18の新しいAPIを使用
const container = document.getElementById("app");
if (container) {
  const root = createRoot(container);
  root.render(<App />);
}

.babelrc

Babelの設定ファイルです。どのプリセット(プラグインのセット)を使用してコードを変換するかを定義します。

{
  "presets": [
    "@babel/preset-env",          // 最新のJSをターゲット環境に合わせて変換
    "@babel/preset-react",        // ReactのJSXを変換
    "@babel/preset-typescript"    // TypeScriptを変換 (型チェックは行わない)
  ]
}

package.json

プロジェクトのメタデータとスクリプト、依存関係を定義します。scripts セクションに開発サーバーの起動コマンドとビルドコマンドを追加します。

{
  "name": "react_test",
  "version": "1.0.0",
  "description": "React with TypeScript development environment",
  "main": "index.js",
  "scripts": {
    "start": "webpack serve --open",  // 開発サーバーを起動し、ブラウザを自動で開く
    "build": "webpack --mode production" // 本番用にビルド
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.20.2",
    "@babel/preset-env": "^7.20.2",
    "@babel/preset-react": "^7.18.6",
    "@babel/preset-typescript": "^7.18.6",
    "@types/react": "^18.0.25",
    "@types/react-dom": "^18.0.8",
    "babel-loader": "^9.1.0",
    "html-webpack-plugin": "^5.5.0",
    "ts-loader": "^9.4.1",
    "typescript": "^4.8.4",
    "webpack": "^5.75.0",
    "webpack-cli": "^4.10.0",
    "webpack-dev-server": "^4.11.1"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}

tsconfig.json

TypeScriptのコンパイラ設定ファイルです。TypeScriptコードをJavaScriptに変換する際のルールを定義します。

{
  "compilerOptions": {
    "target": "es2015",                         // 出力するJavaScriptのバージョン (ES5でも可)
    "module": "esnext",                         // モジュールシステム (Webpackが処理するためesnextが柔軟)
    "jsx": "react-jsx",                         // JSXの変換方法 (React 17+ の新しいJSXトランスフォーム)
    "strict": true,                             // 厳格な型チェックを有効にする
    "esModuleInterop": true,                    // CommonJSモジュールとESモジュールの互換性を高める
    "skipLibCheck": true,                       // 型定義ファイルの型チェックをスキップ (ビルド高速化)
    "forceConsistentCasingInFileNames": true,   // ファイル名の大文字小文字を区別する
    "moduleResolution": "node",                 // モジュール解決戦略
    "resolveJsonModule": true,                 // JSONファイルのインポートを許可
    "isolatedModules": true,                    // 各ファイルを独立したモジュールとしてコンパイル
    "noEmit": true,                             // TypeScriptからJSへの出力を行わない (Babel/Webpackが担当)
    "allowJs": true,                            // JavaScriptファイルのコンパイルを許可
    "lib": ["dom", "dom.iterable", "esnext"]    // 利用可能なライブラリ
  },
  "include": ["src"]                            // コンパイル対象のファイル
}

webpack.config.js

Webpackのバンドル設定ファイルです。エントリポイント、出力先、ローダー、プラグインなどを定義します。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  // 開発モードに設定 (最適化やデバッグ情報が有効になる)
  mode: "development", 
  // エントリポイント (アプリケーションの開始点)
  entry: "./src/index.tsx",
  // 出力設定
  output: {
    path: path.resolve(__dirname, "dist"), // 出力ディレクトリ
    filename: "bundle.js",                 // 出力ファイル名
    clean: true,                           // ビルド前にdistディレクトリをクリーンアップ
  },
  // モジュール解決の設定
  resolve: {
    extensions: [".ts", ".tsx", ".js", ".jsx"], // インポート時に解決する拡張子
  },
  // モジュールルール (ローダーの設定)
  module: {
    rules: [
      {
        test: /\\.(ts|tsx)$/, // .tsまたは.tsxファイルに適用
        exclude: /node_modules/, // node_modulesは除外
        use: {
          loader: "babel-loader", // Babelを使って変換
          options: {
            presets: [
              "@babel/preset-env",
              "@babel/preset-react",
              "@babel/preset-typescript",
            ],
          },
        },
      },
      // CSSや画像などのローダーもここに追加できる
    ],
  },
  // プラグインの設定
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html", // テンプレートとして使用するHTMLファイル
      filename: "index.html",       // 出力されるHTMLファイル名
    }),
  ],
  // 開発サーバーの設定
  devServer: {
    static: {
      directory: path.join(__dirname, "dist"), // 静的ファイルの提供元ディレクトリ
    },
    compress: true, // gzip圧縮を有効にする
    port: 3000,     // 開発サーバーのポート番号
    open: true,     // サーバー起動時にブラウザを自動で開く
    hot: true,      // ホットモジュールリプレイスメントを有効にする
  },
  // ソースマップの設定 (デバッグ用)
  devtool: "eval-source-map",
};

これらの設定ファイルが揃ったら、npm start で開発サーバーを起動し、npm run build で本番用のビルドを行うことができます。