React buildコマンド解説|本番環境への準備を完全理解

React buildコマンドの詳細解説から本番環境デプロイまで。最適化、設定、トラブルシューティングを実践的なサンプルとともに詳しく紹介します。

Learning Next 運営
56 分で読めます

「React アプリを作ったけど、本番環境にはどうやって公開するの?」 「npm run build って何をしているの?」

そんな疑問を持ったことはありませんか? 開発が完了したら、次は本番環境への準備が必要です。 でも、build コマンドって何だか難しそうですよね。

この記事では、React の build コマンドを基礎から詳しく解説します。 最適化から本番環境設定、デプロイまでを実践的なサンプルとともに学んでいきましょう。

大丈夫です! 一つずつ丁寧に進めていけば、きっと理解できるはずです。

React build コマンドって何?

まずは React build コマンドの基本的な役割から理解していきましょう。 開発中のコードと本番環境のコードには、大きな違いがあります。

基本的な仕組みを理解しよう

React build コマンドは、開発用のコードを本番環境向けに最適化する機能です。 簡単に言うと、あなたが書いたコードを実際のユーザーが使いやすい形に変換してくれます。

基本的な build コマンドの実行方法

# 基本的なbuildコマンド
npm run build

# もしくは
yarn build

# Create React Appの場合
npx create-react-app my-app
cd my-app
npm run build

このコマンドを実行するだけで、本番用のファイルが自動的に生成されます。 特別な設定は必要ありません!

build プロセスで何が行われるの?

build を実行すると、以下のような処理が自動で行われます。

// package.json内のbuildスクリプト
{
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
}

npm run build を実行すると、react-scripts build が呼び出されます。 この中で、たくさんの最適化処理が行われています。

具体的には、こんな処理が実行されます。

  • JSX → JavaScript 変換: あなたが書いた JSX コードを、ブラウザが理解できる JavaScript に変換
  • ファイルのまとめ: 複数のファイルを 1 つにまとめて、読み込み時間を短縮
  • コードの圧縮: 余分なスペースや改行を削除して、ファイルサイズを小さく
  • 画像の最適化: 画像ファイルを圧縮して、表示速度を向上
  • CSS の最適化: CSS ファイルも圧縮して、スタイルの読み込みを高速化

これらの処理により、ユーザーが快適に使えるアプリケーションが完成します。

開発版と本番版の違いを見てみよう

開発中と本番環境では、出力されるファイルの内容が全く違います。 その違いを具体的に見てみましょう。

ファイル構造の比較

開発中のファイル構造と、build 後のファイル構造を比較してみます。

# 開発版(npm start)
src/
├── App.js
├── App.css
├── index.js
└── components/
    ├── Header.js
    └── Footer.js

# 本番版(npm run build)
build/
├── index.html
├── static/
│   ├── css/
│   │   └── main.abc123.css
│   ├── js/
│   │   ├── main.def456.js
│   │   └── vendor.ghi789.js
│   └── media/
│       └── logo.jkl012.png
└── asset-manifest.json

本番版では、ファイルにハッシュ値が付きます。 これは、ファイルが更新された時にブラウザのキャッシュを確実に更新するためです。

最適化の具体的な違い

開発版と本番版では、以下のような違いがあります。

開発版の特徴

  • ファイル変更時の自動リロード
  • エラーが発生した時の詳細な表示
  • デバッグしやすい読みやすいコード
  • React DevTools のサポート

本番版の特徴

  • コードの圧縮でファイルサイズを削減
  • 使用していないコードの自動削除
  • ブラウザキャッシュに対応
  • 画像の最適化
// 開発版のJavaScriptコード例
function App() {
  const [count, setCount] = useState(0);
  
  return (
    <div className="App">
      <h1>カウンター: {count}</h1>
      <button onClick={() => setCount(count + 1)}>
        クリック
      </button>
    </div>
  );
}

// 本番版のJavaScriptコード例(圧縮済み)
function App(){const[e,t]=useState(0);return React.createElement("div",{className:"App"},React.createElement("h1",null,"カウンター: ",e),React.createElement("button",{onClick:()=>t(e+1)},"クリック"))}

本番版では、コードが圧縮されて読めなくなりますが、ファイルサイズが大幅に小さくなります。

build コマンドの実行結果を見てみよう

実際に build コマンドを実行すると、どんな結果が表示されるか見てみましょう。

# buildコマンドの実行
npm run build

# 実行時の出力例
> my-app@0.1.0 build
> react-scripts build

Creating an optimized production build...
Compiled successfully.

File sizes after gzip:

  41.33 KB    build/static/js/main.abc123.js
  1.17 KB     build/static/js/runtime.def456.js
  539 B       build/static/css/main.ghi789.css

The project was built assuming it is hosted at the server root.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.
You may serve it with a static server:

  npm install -g serve
  serve -s build

このログを見ると、以下のことが分かります。

  • ファイルサイズ: 圧縮後の実際のファイルサイズ
  • 最適化結果: どれだけ小さくなったか
  • 配信方法: 作成されたファイルの使い方

特に重要なのは、File sizes after gzip の部分です。 これは、実際にユーザーがダウンロードするファイルサイズを示しています。

build で生成されるファイルを詳しく見よう

build コマンドで生成されるファイルの内容を詳しく見てみましょう。 それぞれのファイルがどんな役割を持っているか理解することで、より効果的な最適化ができます。

生成されるファイル構造

build フォルダの中には、以下のようなファイルが生成されます。

# build フォルダの詳細構造
build/
├── index.html                 # メインHTMLファイル
├── favicon.ico               # ファビコン
├── logo192.png              # PWA用アイコン
├── logo512.png              # PWA用アイコン
├── manifest.json            # PWA設定
├── robots.txt               # 検索エンジン設定
├── asset-manifest.json      # アセット一覧
├── static/
│   ├── css/
│   │   ├── main.abc123.css           # 圧縮済みCSS
│   │   └── main.abc123.css.map       # CSSソースマップ
│   ├── js/
│   │   ├── main.def456.js            # メインJSバンドル
│   │   ├── main.def456.js.map        # JSソースマップ
│   │   ├── runtime.ghi789.js         # webpack runtime
│   │   └── vendor.jkl012.js          # サードパーティライブラリ
│   └── media/
│       ├── logo.mno345.png           # 最適化済み画像
│       └── font.pqr678.woff2         # フォントファイル
└── service-worker.js         # サービスワーカー(オプション)

それぞれのファイルに、キャッシュ対策のためのハッシュ値が含まれています。

index.html の内容を見てみよう

生成される index.html ファイルの内容を詳しく見てみましょう。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <meta name="theme-color" content="#000000">
  <meta name="description" content="React app built with create-react-app">
  <link rel="apple-touch-icon" href="/logo192.png">
  <link rel="manifest" href="/manifest.json">
  <title>React App</title>
  <!-- 最適化されたCSSファイル -->
  <link href="/static/css/main.abc123.css" rel="stylesheet">
</head>
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
  
  <!-- 最適化されたJavaScriptファイル -->
  <script src="/static/js/runtime.def456.js"></script>
  <script src="/static/js/vendor.ghi789.js"></script>
  <script src="/static/js/main.jkl012.js"></script>
</body>
</html>

このファイルを見ると、以下のことが分かります。

  • CSS ファイル: 圧縮された CSS が head 部分で読み込まれます
  • JavaScript ファイル: 複数のファイルに分割されて読み込まれます
  • メタタグ: SEO やモバイル対応のためのメタタグが自動で追加されます

asset-manifest.json の役割

asset-manifest.json ファイルは、生成されたファイルの一覧を管理します。

{
  "files": {
    "main.css": "/static/css/main.abc123.css",
    "main.js": "/static/js/main.def456.js",
    "runtime.js": "/static/js/runtime.ghi789.js",
    "vendor.js": "/static/js/vendor.jkl012.js",
    "index.html": "/index.html",
    "main.css.map": "/static/css/main.abc123.css.map",
    "main.js.map": "/static/js/main.def456.js.map"
  },
  "entrypoints": [
    "static/js/runtime.ghi789.js",
    "static/js/vendor.jkl012.js",
    "static/css/main.abc123.css",
    "static/js/main.def456.js"
  ]
}

このファイルは、デプロイツールや動的なファイル読み込みで使用されます。 ハッシュ値が変わっても、このファイルを参照することで正しいファイルを見つけられます。

JavaScript ファイルの分割について

build 時に JavaScript ファイルは複数に分割されます。 なぜ分割されるのか、その理由を見てみましょう。

main.js: あなたが書いたアプリケーションのコード vendor.js: React や他のライブラリのコード runtime.js: webpack の実行に必要な小さなコード

// main.js の内容(圧縮前のイメージ)
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

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

// vendor.js の内容(React本体など)
// React, ReactDOM, その他のライブラリ

// runtime.js の内容(webpack runtime)
// モジュールの読み込み処理

この分割により、以下のメリットがあります。

  • キャッシュ効率: ライブラリ部分(vendor.js)は変更されにくいため、長期間キャッシュされる
  • 並列読み込み: 複数のファイルを同時にダウンロードできる
  • 初期読み込み最適化: 必要な部分だけを先に読み込める

環境変数で build をカスタマイズしよう

build プロセスでは、環境変数を使って様々な設定を調整できます。 本番環境、ステージング環境、開発環境など、それぞれに適した設定が可能です。

基本的な環境変数の設定

React では、REACT_APP_ プレフィックスを付けた環境変数を使用できます。

# .env.production ファイル
REACT_APP_API_URL=https://api.example.com
REACT_APP_ENVIRONMENT=production
REACT_APP_VERSION=1.0.0
REACT_APP_ANALYTICS_ID=GA-123456789

注意点として、必ず REACT_APP_ で始まる必要があります。 これは、セキュリティのための制限です。

環境別の設定を作ってみよう

異なる環境用の設定ファイルを作成できます。

# .env.development(開発環境)
REACT_APP_API_URL=http://localhost:3001
REACT_APP_ENVIRONMENT=development
REACT_APP_DEBUG_MODE=true

# .env.staging(ステージング環境)
REACT_APP_API_URL=https://staging-api.example.com
REACT_APP_ENVIRONMENT=staging
REACT_APP_DEBUG_MODE=false

# .env.production(本番環境)
REACT_APP_API_URL=https://api.example.com
REACT_APP_ENVIRONMENT=production
REACT_APP_DEBUG_MODE=false

package.json でそれぞれの環境用のスクリプトを定義できます。

{
  "scripts": {
    "build": "react-scripts build",
    "build:staging": "REACT_APP_ENV=staging react-scripts build",
    "build:production": "REACT_APP_ENV=production react-scripts build"
  }
}

JavaScript コードで環境変数を使ってみよう

設定した環境変数を JavaScript コードで使用する方法を見てみましょう。

// src/config/env.js
const config = {
  apiUrl: process.env.REACT_APP_API_URL || 'http://localhost:3000',
  environment: process.env.REACT_APP_ENVIRONMENT || 'development',
  version: process.env.REACT_APP_VERSION || '0.0.0',
  analytics: {
    googleId: process.env.REACT_APP_ANALYTICS_ID,
    enabled: process.env.REACT_APP_ENVIRONMENT === 'production'
  },
  features: {
    debugMode: process.env.REACT_APP_ENVIRONMENT !== 'production',
    mockApi: process.env.REACT_APP_MOCK_API === 'true'
  }
};

export default config;

このコードでは、環境変数を使って設定を管理しています。 process.env.REACT_APP_* で環境変数にアクセスできます。

実際のコンポーネントでの使用例も見てみましょう。

// src/App.js での使用
import React from 'react';
import config from './config/env';

const App = () => {
  return (
    <div>
      <h1>My App</h1>
      <p>Environment: {config.environment}</p>
      <p>Version: {config.version}</p>
      
      {config.features.debugMode && (
        <div style={{ backgroundColor: 'yellow', padding: '10px' }}>
          🐛 Debug Mode Active
        </div>
      )}
      
      {config.analytics.enabled && (
        <script
          async
          src={`https://www.googletagmanager.com/gtag/js?id=${config.analytics.googleId}`}
        />
      )}
    </div>
  );
};

export default App;

このように、環境に応じて表示内容を変更できます。

セキュリティ上の注意点

環境変数を使用する際の注意点をいくつか紹介します。

秘密情報は絶対に入れない

# ❌ これは絶対にやってはいけません
REACT_APP_API_SECRET=secret_key_12345
REACT_APP_DATABASE_PASSWORD=password123

# ✅ これらは問題ありません
REACT_APP_API_URL=https://api.example.com
REACT_APP_ENVIRONMENT=production

React アプリはクライアント側で実行されるため、すべての環境変数がユーザーに見えてしまいます。 そのため、API キーやパスワードなどの秘密情報は絶対に含めないでください。

適切な値の検証

// src/config/validation.js
const validateConfig = (config) => {
  // 必須項目のチェック
  if (!config.apiUrl) {
    throw new Error('API URL is required');
  }
  
  // URL形式のチェック
  try {
    new URL(config.apiUrl);
  } catch {
    throw new Error('Invalid API URL format');
  }
  
  // 環境値のチェック
  const validEnvironments = ['development', 'staging', 'production'];
  if (!validEnvironments.includes(config.environment)) {
    throw new Error(`Invalid environment: ${config.environment}`);
  }
  
  return config;
};

export default validateConfig;

このように、設定値の検証を行うことで、意図しないエラーを防げます。

webpack 設定をカスタマイズしてみよう

Create React App では、webpack の設定をカスタマイズできます。 eject せずに設定を変更する方法を学んでいきましょう。

CRACO を使った設定変更

CRACO(Create React App Configuration Override)を使うと、eject せずに設定を変更できます。

# CRACOのインストール
npm install @craco/craco --save-dev

# package.json の修正
{
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "react-scripts eject"
  }
}

CRACO を使うことで、元の Create React App の機能を保ちながら設定を変更できます。

craco.config.js の設定例

プロジェクトのルートに craco.config.js ファイルを作成します。

// craco.config.js
const path = require('path');

module.exports = {
  webpack: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@utils': path.resolve(__dirname, 'src/utils'),
      '@assets': path.resolve(__dirname, 'src/assets')
    },
    configure: (webpackConfig, { env, paths }) => {
      // 本番環境でのソースマップ無効化
      if (env === 'production') {
        webpackConfig.devtool = false;
      }
      
      // バンドル分析用設定
      if (process.env.ANALYZE_BUNDLE === 'true') {
        const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
        webpackConfig.plugins.push(
          new BundleAnalyzerPlugin({
            analyzerMode: 'static',
            openAnalyzer: false
          })
        );
      }
      
      return webpackConfig;
    }
  },
  babel: {
    plugins: [
      // プロダクションビルドでのconsole.log削除
      ...(process.env.NODE_ENV === 'production' ? [
        ['babel-plugin-transform-remove-console', { exclude: ['error', 'warn'] }]
      ] : [])
    ]
  },
  style: {
    postcss: {
      plugins: [
        require('autoprefixer'),
        require('cssnano')({
          preset: 'default'
        })
      ]
    }
  }
};

この設定により、以下のことが可能になります。

パスエイリアス: import Button from '@components/Button' のような短いパスが使用可能 ソースマップ制御: 本番環境でのソースマップを無効化 バンドル分析: バンドルサイズを可視化 console.log削除: 本番環境で不要なログを自動削除 CSS最適化: より効率的なCSS圧縮

実際の使用例

設定したパスエイリアスを使った場合の例を見てみましょう。

// 設定前
import Button from '../../components/ui/Button';
import { formatDate } from '../../../utils/dateUtils';
import logo from '../../assets/images/logo.png';

// 設定後
import Button from '@components/ui/Button';
import { formatDate } from '@utils/dateUtils';
import logo from '@assets/images/logo.png';

相対パスが短くなり、ファイルを移動しても import パスを変更する必要がなくなります。

バンドル分析をしてみよう

バンドルサイズを分析することで、アプリケーションの最適化ポイントを見つけられます。

# バンドル分析の実行
npm install --save-dev webpack-bundle-analyzer
ANALYZE_BUNDLE=true npm run build

# または専用のツールを使用
npm install --save-dev source-map-explorer
npm run build
npx source-map-explorer 'build/static/js/*.js'

これにより、どのライブラリがどれだけのサイズを占めているかが分かります。

バンドル分析の結果を見て、以下のような最適化を行えます。

不要なライブラリの除去

// ❌ 全体をインポート
import _ from 'lodash';
import * as MUI from '@mui/material';

// ✅ 必要な部分のみ
import { debounce } from 'lodash';
import { Button } from '@mui/material';

遅延読み込みの実装

// src/utils/lazyLoad.js
import { lazy } from 'react';

// 遅延読み込みコンポーネント
export const LazyHome = lazy(() => import('../pages/Home'));
export const LazyAbout = lazy(() => import('../pages/About'));
export const LazyContact = lazy(() => import('../pages/Contact'));

これらの最適化により、初期読み込み時間を大幅に短縮できます。

本番環境での配信設定

build したファイルを本番環境で配信するための設定を学びましょう。 静的ファイルサーバーの設定からCDN配信まで、実践的な方法を紹介します。

Nginx での配信設定

Nginx を使った静的ファイルの配信設定を見てみましょう。

# /etc/nginx/sites-available/react-app
server {
    listen 80;
    server_name example.com;
    
    root /var/www/react-app/build;
    index index.html;
    
    # Gzip圧縮設定
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/xml+rss
        application/json;
    
    # キャッシュ設定
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # HTML5 History API対応
    location / {
        try_files $uri $uri/ /index.html;
    }
    
    # セキュリティヘッダー
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}

この設定により、以下の機能が提供されます。

Gzip圧縮: ファイルサイズをさらに小さくしてダウンロード時間を短縮 キャッシュ設定: 静的ファイルを1年間キャッシュして、再訪問時の読み込みを高速化 SPA対応: React Router を使用した場合の URL 対応 セキュリティ: 基本的なセキュリティヘッダーを追加

Apache での配信設定

Apache を使用する場合の設定例も見てみましょう。

# .htaccess
RewriteEngine On

# HTTPS強制(本番環境)
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Gzip圧縮
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE application/xhtml+xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
</IfModule>

# キャッシュ設定
<IfModule mod_expires.c>
    ExpiresActive on
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/jpg "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/ico "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
</IfModule>

# React Router対応
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

Apache でも Nginx と同様の機能を実現できます。

簡単な配信テスト

build したファイルを簡単にテストする方法を紹介します。

# serve パッケージを使用
npm install -g serve
serve -s build

# または Python を使用
cd build
python -m http.server 8000

# または Node.js を使用
npx http-server build

これらのコマンドで、ローカルで本番環境と同じ環境をテストできます。

ブラウザで http://localhost:5000 にアクセスすると、build されたアプリケーションが表示されます。

CDN を使った配信

CDN(Content Delivery Network)を使用することで、世界中のユーザーに高速にコンテンツを配信できます。

# AWS S3 + CloudFront での配信例
aws s3 mb s3://my-react-app-bucket
aws s3 cp build s3://my-react-app-bucket --recursive

# CloudFrontディストリビューション作成
aws cloudfront create-distribution --distribution-config file://distribution-config.json

CDN を使用することで、以下のメリットがあります。

高速配信: 世界中のサーバーから最も近いサーバーがコンテンツを配信 負荷分散: 大量のアクセスにも対応可能 コスト削減: 帯域幅コストを削減 高可用性: 障害時の自動切り替え

パフォーマンスの測定

本番環境での配信設定後、パフォーマンスを測定してみましょう。

# Lighthouse を使用したパフォーマンス測定
npm install -g lighthouse
lighthouse https://your-app.com --output json --output html

# PageSpeed Insights API を使用
curl "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=https://your-app.com&key=YOUR_API_KEY"

これらのツールを使用することで、実際のユーザーが体験するパフォーマンスを測定できます。

人気のデプロイプラットフォームを使ってみよう

React アプリをデプロイする際によく使われるプラットフォームを紹介します。 それぞれの特徴と設定方法を学んでいきましょう。

Netlify でのデプロイ

Netlify は、静的サイトのデプロイに特化したプラットフォームです。 React アプリのデプロイがとても簡単です。

# Netlify CLIのインストール
npm install -g netlify-cli

# ログイン
netlify login

# デプロイ
netlify deploy --prod --dir=build

たった 3 つのコマンドでデプロイが完了します!

Netlify の設定ファイル

プロジェクトに netlify.toml ファイルを作成することで、詳細な設定が可能です。

# netlify.toml
[build]
  publish = "build"
  command = "npm run build"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

[build.environment]
  REACT_APP_API_URL = "https://api.example.com"
  REACT_APP_ENVIRONMENT = "production"

# ヘッダー設定
[[headers]]
  for = "/static/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
  for = "*.html"
  [headers.values]
    Cache-Control = "public, max-age=0, must-revalidate"

この設定により、以下のことが自動化されます。

自動ビルド: コードをプッシュするたびに自動的にビルドが実行 SPA対応: React Router を使用した場合の URL 対応 キャッシュ最適化: 静的ファイルとHTMLファイルで異なるキャッシュ設定 環境変数: 本番環境用の環境変数を自動設定

Vercel でのデプロイ

Vercel も非常に人気の高いデプロイプラットフォームです。

# Vercel CLIのインストール
npm install -g vercel

# デプロイ
vercel --prod

Vercel も簡単にデプロイできます。

Vercel の設定ファイル

{
  "version": 2,
  "builds": [
    {
      "src": "package.json",
      "use": "@vercel/static-build",
      "config": {
        "distDir": "build"
      }
    }
  ],
  "routes": [
    {
      "src": "/static/(.*)",
      "headers": {
        "cache-control": "public, max-age=31536000, immutable"
      }
    },
    {
      "src": "/(.*)",
      "dest": "/index.html"
    }
  ],
  "env": {
    "REACT_APP_API_URL": "https://api.example.com",
    "REACT_APP_ENVIRONMENT": "production"
  }
}

Vercel でも詳細な設定が可能です。

GitHub Pages でのデプロイ

GitHub Pages を使用すると、無料でホスティングできます。

# gh-pagesパッケージのインストール
npm install --save-dev gh-pages

# package.jsonに設定を追加
{
  "homepage": "https://username.github.io/repository-name",
  "scripts": {
    "predeploy": "npm run build",
    "deploy": "gh-pages -d build"
  }
}

# デプロイ実行
npm run deploy

GitHub Pages を使用する際の注意点をいくつか紹介します。

homepage の設定: package.json の homepage フィールドを正しく設定する必要があります 相対パス: サブディレクトリでの配信になるため、パスの設定に注意が必要 HTTPS: 自動的に HTTPS が有効になります

Firebase Hosting でのデプロイ

Firebase Hosting も人気の高いホスティングサービスです。

# Firebase CLIのインストール
npm install -g firebase-tools

# Firebaseプロジェクトの初期化
firebase init hosting

# デプロイ
firebase deploy

Firebase の設定ファイルも確認してみましょう。

{
  "hosting": {
    "public": "build",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [{
      "source": "**",
      "destination": "/index.html"
    }],
    "headers": [
      {
        "source": "/static/**",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "public, max-age=31536000, immutable"
          }
        ]
      },
      {
        "source": "**/*.html",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "public, max-age=0, must-revalidate"
          }
        ]
      }
    ]
  }
}

Firebase Hosting では、以下の機能が提供されます。

高速 CDN: Google のグローバル CDN を使用 SSL 証明書: 自動的に HTTPS が有効 プレビュー機能: デプロイ前のプレビューが可能 ロールバック: 以前のバージョンに簡単に戻せる

CI/CD パイプラインの設定

GitHub Actions を使用した自動デプロイの設定を見てみましょう。

# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v2
    
    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '16'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test -- --coverage --watchAll=false
    
    - name: Build application
      run: npm run build
      env:
        REACT_APP_API_URL: ${{ secrets.REACT_APP_API_URL }}
        REACT_APP_ENVIRONMENT: production
    
    - name: Deploy to Netlify
      uses: nwtgck/actions-netlify@v1.2
      with:
        publish-dir: './build'
        production-branch: main
        github-token: ${{ secrets.GITHUB_TOKEN }}
        deploy-message: "Deploy from GitHub Actions"
      env:
        NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
        NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}

この設定により、main ブランチにプッシュするたびに自動的にデプロイが実行されます。

GitHub Actions を使用することで、以下のメリットがあります。

自動化: 手動でのデプロイ作業が不要 品質保証: テストが通った場合のみデプロイが実行 履歴管理: デプロイ履歴が GitHub で管理 並列実行: 複数の環境への同時デプロイが可能

よくある問題とその解決方法

React の build で発生する一般的な問題と、その解決方法を紹介します。 事前に知っておくことで、トラブルが発生した時にすぐに対処できます。

メモリエラーの解決

大規模なアプリケーションを build する際に、メモリ不足エラーが発生することがあります。

# Node.jsのメモリ制限を増やす
NODE_OPTIONS="--max-old-space-size=8192" npm run build

# package.jsonでの設定
{
  "scripts": {
    "build": "node --max-old-space-size=8192 node_modules/.bin/react-scripts build"
  }
}

メモリ制限を 8GB に設定することで、大規模なアプリケーションでも build が成功します。

エラーメッセージの例と対処法も見てみましょう。

# よくあるエラーメッセージ
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

# 対処法
# 1. メモリ制限を増やす
NODE_OPTIONS="--max-old-space-size=8192" npm run build

# 2. 不要なファイルを削除
rm -rf node_modules package-lock.json
npm install

# 3. dependencies を見直す
npm ls --depth=0

メモリエラーが頻繁に発生する場合は、アプリケーションの構成を見直すことも重要です。

パスの問題とその解決

サブディレクトリでの配信や、異なるドメインでの配信時にパスの問題が発生することがあります。

// package.json
{
  "homepage": "https://username.github.io/repository-name",
  "scripts": {
    "predeploy": "npm run build",
    "deploy": "gh-pages -d build"
  }
}

// 環境変数での設定
PUBLIC_URL=/my-app npm run build

// 動的パス設定
const basePath = process.env.PUBLIC_URL || '';
const router = (
  <Router basename={basePath}>
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
    </Routes>
  </Router>
);

パスの設定により、サブディレクトリでの配信が可能になります。

依存関係の問題解決

依存関係の問題は、build エラーの原因として最も多いものの一つです。

# 依存関係の詳細確認
npm ls

# 重複依存関係の確認
npm ls --depth=0

# 依存関係の更新
npm update

# パッケージロックファイルの削除と再インストール
rm package-lock.json
rm -rf node_modules
npm install

# 脆弱性の確認と修正
npm audit
npm audit fix

依存関係の問題を解決するためのステップを順番に実行してみてください。

環境変数が読み込まれない問題

環境変数が正しく読み込まれない場合の対処法を見てみましょう。

// よくある問題
console.log(process.env.API_URL); // undefined

// 解決策1: REACT_APP_プレフィックスを追加
console.log(process.env.REACT_APP_API_URL); // 正しく読み込まれる

// 解決策2: デフォルト値を設定
const apiUrl = process.env.REACT_APP_API_URL || 'http://localhost:3001';

// 解決策3: 環境変数の確認
console.log('Environment Variables:', {
  NODE_ENV: process.env.NODE_ENV,
  REACT_APP_API_URL: process.env.REACT_APP_API_URL,
  REACT_APP_ENVIRONMENT: process.env.REACT_APP_ENVIRONMENT
});

環境変数の問題を特定するためのデバッグ方法も覚えておきましょう。

バンドルサイズの最適化

build されたファイルのサイズが大きすぎる場合の最適化方法を紹介します。

// src/utils/bundleOptimization.js
import { lazy } from 'react';

// 不要なライブラリの除去
// import _ from 'lodash'; // ❌ 全体をインポート
import { debounce } from 'lodash'; // ✅ 必要な部分のみ

// Tree Shakingの活用
import { Button } from '@mui/material'; // ✅ 必要なコンポーネントのみ
// import * as MUI from '@mui/material'; // ❌ 全体をインポート

// 動的インポート
const HeavyComponent = lazy(() => import('./HeavyComponent'));

// 条件付きインポート
const loadAnalytics = async () => {
  if (process.env.NODE_ENV === 'production') {
    const { analytics } = await import('./analytics');
    return analytics;
  }
  return null;
};

export { debounce, HeavyComponent, loadAnalytics };

適切なインポート方法により、バンドルサイズを大幅に削減できます。

ソースマップの問題

本番環境でソースマップが公開されてしまう問題の解決方法を見てみましょう。

// craco.config.js
module.exports = {
  webpack: {
    configure: (webpackConfig, { env, paths }) => {
      // 本番環境でのソースマップ無効化
      if (env === 'production') {
        webpackConfig.devtool = false;
      }
      
      return webpackConfig;
    }
  }
};

// または環境変数で制御
GENERATE_SOURCEMAP=false npm run build

ソースマップを無効化することで、ソースコードの漏洩を防げます。

エラーメッセージの理解

よくあるエラーメッセージとその対処法を紹介します。

# モジュールが見つからないエラー
Module not found: Can't resolve 'some-module'
→ npm install some-module で解決

# 構文エラー
Syntax error: Unexpected token
→ Babel 設定やブラウザ対応を確認

# メモリエラー
JavaScript heap out of memory
→ メモリ制限を増やす

# 権限エラー
Permission denied
→ sudo なしで実行できるよう権限を修正

エラーメッセージを理解することで、迅速に問題を解決できます。

まとめ:React build をマスターしよう

React の build コマンドについて、基礎から応用まで詳しく解説しました。 学んだ内容を整理して、実際のプロジェクトで活用していきましょう。

今回学んだ重要なポイント

build コマンドの基本理解

  • React build は開発用コードを本番環境向けに最適化するプロセス
  • 自動的にファイル圧縮、バンドル化、最適化が実行される
  • 開発版と本番版では出力ファイルが大きく異なる

これらの基本を理解することで、build プロセスの全体像が分かります。

最適化設定の活用

  • 環境変数を使った設定管理
  • webpack 設定のカスタマイズ
  • バンドルサイズの最適化手法
  • キャッシュ戦略の実装

適切な最適化により、ユーザー体験を大幅に向上できます。

本番環境での配信方法

  • 静的ファイルサーバーの設定
  • CDN を使った高速配信
  • セキュリティとパフォーマンスの両立
  • 複数のデプロイプラットフォームの活用

これらの知識により、スケーラブルなアプリケーション配信が可能になります。

トラブルシューティング

  • よくある問題の対処法
  • エラーメッセージの理解
  • 依存関係の適切な管理
  • パフォーマンス問題の解決

問題解決能力を身につけることで、安定したアプリケーション運用が可能になります。

実践で活用するためのステップ

1. 基本的な build の理解

  • まずは npm run build を実行してみる
  • 生成されるファイルの内容を確認する
  • 開発版と本番版の違いを実感する

2. 環境変数の設定

  • 開発・ステージング・本番環境用の設定を作成
  • 適切なセキュリティ対策を実装
  • 設定の検証機能を追加

3. 最適化の実装

  • バンドルサイズの分析と最適化
  • 遅延読み込みの実装
  • 不要なライブラリの除去

4. デプロイメントの自動化

  • CI/CD パイプラインの構築
  • 複数の環境への自動デプロイ
  • 品質保証とテストの自動化

これからの学習に向けて

より高度な最適化

  • Service Worker の活用
  • PWA 対応の実装
  • パフォーマンス監視の設定
  • A/B テストの実装

運用面での改善

  • 監視とログ収集
  • エラー追跡システムの導入
  • 負荷テストの実施
  • 災害復旧計画の策定

セキュリティの強化

  • CSP(Content Security Policy)の設定
  • XSS・CSRF 対策の実装
  • 定期的なセキュリティ監査
  • 脆弱性スキャンの自動化

最後に

React の build コマンドを理解することで、開発からデプロイまでのワークフローが大幅に改善されます。 この記事で学んだ内容を基に、実際のプロジェクトで実践してみてください。

最初は複雑に感じるかもしれませんが、一つずつステップを踏んでいけば必ず理解できるはずです。 build の最適化により、ユーザーにとって快適なアプリケーションを提供できるようになります。

ぜひこの知識を活用して、素晴らしい React アプリケーションを世界に公開してくださいね!

関連記事