デザインについての学習メモブログ

React入門 #20 – 本番環境へのデプロイとまとめ

記事内に広告が含まれています。

React入門 #20 – 本番環境へのデプロイとまとめ

React入門シリーズもついに最終回です。

これまで学んできた知識を使って、実際にアプリケーションを本番環境に公開する方法を学びましょう。

また、シリーズ全体を振り返り、次のステップについても紹介します。

本番ビルドの作成

開発中に使っていたコードを、ユーザーに公開できる「本番用」の形に変換する手順がわかります。

開発環境と本番環境の違いを理解し、npm run build で生成されたファイルを実際に動作確認するところまでを身につけます。

開発環境と本番環境の違い

開発環境(手元で動かしている状態)と本番環境(実際に公開する状態)は、見た目は同じでも内部の動きが大きく異なります。

まずはこの2つがどう違うのかを整理します。

開発環境(Development)

  • 詳細なエラーメッセージ
  • ホットリロード機能(コードを編集して保存した瞬間に、変更内容が画面に自動で反映される機能)
  • ソースマップ付き(本番用に圧縮・変換されたコードと、元の読みやすいソースコードを対応づけるためのファイル)
  • 最適化されていない大きなファイルサイズ

本番環境(Production)

  • 圧縮・最適化されたコード
  • エラーメッセージは最小限
  • 高速な実行速度
  • 小さなファイルサイズ

本番ビルドの実行

実際にコマンドを叩いて、最適化済みのファイル一式を生成する方法です。

Vite・Create React Appそれぞれのコマンドを紹介します。

Bash
# Viteの場合
npm run build

# Create React Appの場合
npm run build

ビルドが完了すると、distまたはbuildフォルダに最適化されたファイルが生成されます。

ビルドの確認

生成された本番ビルドを、デプロイ前にローカル環境で実際に動かして確認する方法です。

本番特有の不具合(パス指定ミスなど)をここで発見できます。

Bash
# Viteでローカルプレビュー
npm run preview

# Create React Appの場合
npx serve -s build

環境変数の管理

APIのURLやアプリ名など、環境によって変えたい値を「環境変数」として管理する方法がわかります。

さらに、フロントエンドに秘密情報を絶対に含めてはいけないというセキュリティ上の重要な考え方も身につきます。

環境変数ファイルの作成

開発用・本番用で異なる設定値を切り替えるための.envファイルの作り方です。

開発環境用(.env.development)

Bash
VITE_API_URL=http://localhost:3000/api
VITE_APP_TITLE=My App (Dev)

本番環境用(.env.production)

Bash
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App

環境変数の使用

.envファイルに書いた値をコード側からどう読み込むか、Viteと Create React Appでの書き方の違いを紹介します。

JavaScript
// Viteの場合
const apiUrl = import.meta.env.VITE_API_URL;
const appTitle = import.meta.env.VITE_APP_TITLE;

// Create React Appの場合
const apiUrl = process.env.REACT_APP_API_URL;
const appTitle = process.env.REACT_APP_APP_TITLE;

console.log('API URL:', apiUrl);
console.log('App Title:', appTitle);

環境変数のセキュリティ

環境変数は便利ですが、使い方を誤るとAPIキーなどの秘密情報が誰でも見える状態で公開されてしまいます。

何を含めてよく、何を含めてはいけないかを明確にします。

⚠️ 重要な注意事項

JavaScript
// ❌ 絶対にしてはいけない
// フロントエンドに秘密情報を含めてはいけません
const API_KEY = import.meta.env.VITE_SECRET_API_KEY; // 危険!

// ✅ 正しい方法
// 秘密情報はバックエンドで管理
// フロントエンドには公開可能な情報のみ
const PUBLIC_API_ENDPOINT = import.meta.env.VITE_API_URL; // OK

デプロイ方法の選択

数あるホスティングサービスの中から、自分のアプリに合ったものを選ぶための判断基準がわかります。

料金・機能・使いやすさを比較する視点を身につけます。

主要なホスティングサービス比較

代表的な無料ホスティングサービスを表で比較します。

サービス無料プラン自動デプロイカスタムドメインおすすめ度
Vercel★★★★★
Netlify★★★★★
GitHub Pages★★★★☆
Cloudflare Pages★★★★☆
Render★★★☆☆

選択のポイント

各サービスがどんな用途に向いているか、特徴ごとに簡単に整理します。

  • Vercel: Reactに最適化、高速、簡単
  • Netlify: フォーム機能、サーバーレス関数
  • GitHub Pages: GitHubと統合、シンプル
  • Cloudflare Pages: CDN最適化、高速配信

Vercelへのデプロイ(推奨)

もっとも手軽でReactとの親和性が高い「Vercel」を使って、GitHub連携から本番公開、カスタムドメイン設定までの一連の流れを実際に手を動かしながら習得します。

Vercelアカウントの作成

デプロイの第一歩として、Vercelのアカウントを準備する手順です。

  1. Vercel公式サイトにアクセス
  2. GitHubアカウントで登録
  3. 無料プランで開始

GitHubリポジトリの準備

Vercelでデプロイするには、コードがGitHub上にある必要があります。

Gitの初期化からプッシュまでの基本コマンドを確認します。

Bash
# Gitの初期化(まだの場合)
git init

# .gitignoreの確認
echo "node_modules/" >> .gitignore
echo "dist/" >> .gitignore
echo ".env.local" >> .gitignore

# コミット
git add .
git commit -m "Initial commit"

# GitHubにプッシュ
git remote add origin https://github.com/username/my-react-app.git
git branch -M main
git push -u origin main

Vercelでプロジェクトをインポート

GitHubリポジトリをVercelに取り込み、ビルド設定を確認しながら実際に公開するまでの手順です。

  1. Vercelダッシュボードで「New Project」をクリック
  2. GitHubリポジトリを選択
  3. プロジェクト設定を確認
    • Framework Preset: Vite(自動検出される)
    • Build Command: npm run build
    • Output Directory: dist
  4. 環境変数を設定(必要な場合)
  5. 「Deploy」をクリック

カスタムドメインの設定

xxx.vercel.appではなく、自分が取得した独自ドメインで公開する方法です。SSL証明書も自動発行されます。

Bash
1. Vercelダッシュボード  Settings  Domains
2. カスタムドメインを追加
3. DNSレコードを設定(指示に従う)
4. 自動的にSSL証明書が発行される

Netlifyへのデプロイ

Vercelと並ぶ人気サービス「Netlify」での設定ファイルの書き方と、GitHub連携・ドラッグ&ドロップという2つのデプロイ方法を身につけます。

netlify.tomlの作成

ビルドコマンドや公開フォルダ、SPA特有のリダイレクト設定をまとめて記述する設定ファイルです。

Bash
[build]
  command = "npm run build"
  publish = "dist"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200
  
[build.environment]
  NODE_VERSION = "18"  

デプロイ手順

GitHub経由の自動デプロイと、ビルド済みファイルを直接アップロードする方法の2パターンを紹介します。

方法1: GitHubからのデプロイ

  1. Netlifyにログイン
  2. 「Add new site」→「Import an existing project」
  3. GitHubリポジトリを選択
  4. ビルド設定を確認してデプロイ

方法2: ドラッグ&ドロップデプロイ

Bash
# ビルド
npm run build

# Netlifyダッシュボードにdistフォルダをドラッグ&ドロップ

GitHub Pagesへのデプロイ

追加サービスの登録なしにGitHubだけで公開できる「GitHub Pages」の使い方がわかります。

Viteのbase設定など、このサービス特有の落とし穴に対する理解も深まります。

vite.config.tsの設定

GitHub Pagesはリポジトリ名のサブパス配下で公開されるため、Vite側でbaseパスを明示的に指定する必要があります。

JavaScript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  base: '/リポジトリ名/', // ユーザーページの場合は '/'
})

デプロイスクリプトの追加

ビルドからGitHub Pagesへの公開までを自動化してくれるgh-pagesパッケージの導入方法です。

Bash
# gh-pagesのインストール
npm install --save-dev gh-pages

package.jsonに追加

JSON
{
  "scripts": {
    "predeploy": "npm run build",
    "deploy": "gh-pages -d dist"
  }
}

デプロイ実行

設定したスクリプトを実行し、実際にGitHub Pages上へ公開するコマンドです。

Bash
npm run deploy

GitHub設定

公開を有効にするため、GitHub側のリポジトリ設定で参照ブランチを指定する手順です。

  1. GitHubリポジトリ → Settings → Pages
  2. Source: gh-pages ブランチを選択
  3. Save

パフォーマンス最適化

公開したアプリをより速く、軽くするための実践的な最適化テクニックが身につきます。

コード分割・画像最適化・バンドルサイズ分析という3つの観点からアプリのパフォーマンスを改善できるようになります。

コード分割(Code Splitting)

ページ全体を一度に読み込むのではなく、必要なページだけを遅延ロードすることで初期表示を高速化する手法です。

JavaScript
import { lazy, Suspense } from 'react';

// 遅延ロード
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Profile = lazy(() => import('./pages/Profile'));

function App() {
  return (
    <Suspense fallback={<div>読み込み中...</div>}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/profile" element={<Profile />} />
      </Routes>
    </Suspense>
  );
}

画像の最適化

画像はWebページの中でも特に重いリソースです。

サイズ別画像の出し分けやloading="lazy"、WebP形式の活用で読み込みを軽くする方法です。

JavaScript
// 複数サイズの画像を用意
<img
  src="/images/photo.jpg"
  srcSet="
    /images/photo-small.jpg 400w,
    /images/photo-medium.jpg 800w,
    /images/photo-large.jpg 1200w
  "
  sizes="(max-width: 400px) 400px, (max-width: 800px) 800px, 1200px"
  alt="説明"
  loading="lazy"
/>

// WebP形式の使用
<picture>
  <source srcSet="/images/photo.webp" type="image/webp" />
  <source srcSet="/images/photo.jpg" type="image/jpeg" />
  <img src="/images/photo.jpg" alt="説明" />
</picture>

WebP形式については、

一般的なWebサービス
→ WebPだけでほぼ問題なし

官公庁・医療・金融など古い環境が残りやすい業種
→ <picture>でフォールバックを用意する価値あり

IE(Internet Explorer)のサポートが必要
→ WebP非対応なので必ずフォールバックが必要   ただしMicrosoftが2022年にサポート終了済みなので   現在はほぼ考慮不要

バンドルサイズの分析

「何が原因でファイルが大きくなっているか」を可視化し、改善ポイントを見つけるためのツール導入方法です。

Bash
# rollup-plugin-visualizerのインストール
npm install --save-dev rollup-plugin-visualizer

TypeScript
//vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig({
  plugins: [
    react(),
    visualizer({
      open: true,
      gzipSize: true,
      brotliSize: true,
    })
  ],
})
Bash
npm run build
# stats.htmlが開いてバンドルサイズを確認できる

SEOとメタタグ

検索結果やSNSでのシェア時にきちんと表示されるよう、ページごとのメタ情報を設定する方法がわかります。

あわせて、検索エンジン向けのrobots.txtsitemap.xmlの役割も理解できます。

react-helmetの使用

ページごとに<title>やOGPタグを動的に切り替えるためのライブラリの使い方です。

Bash
npm install react-helmet-async
JSX
import { Helmet } from 'react-helmet-async';

function HomePage({ path }) {
  const [post, setPost] = useState(null);

  useEffect(() => {
    fetch(`/api/${path}`)
      .then(res => res.json())
      .then(data => setPost(data));
  }, [postId]);

  return (
    <>
      <Helmet>
        <title>{post?.title} | サイト名</title>
        <meta name="description" content={post?.summary} />
        <meta property="og:title" content={post?.title} />
        <meta property="og:image" content={post?.thumbnailUrl} />
        <meta property="og:description" content={post?.summary} />

        <link rel="canonical" href="https://example.com/" />
      </Helmet>
      
      <h1>ホームページ</h1>
      {/* コンテンツ */}
    </>
  );
}

公開ディレクトリのファイル

検索エンジンのクローラーに対してサイト構造を伝えるための、publicフォルダに置く2つの定番ファイルです。

public/robots.txt

Bash
User-agent: *
Allow: /

Sitemap: https://example.com/sitemap.xml

public/sitemap.xml

XML
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/</loc>
    <changefreq>daily</changefreq>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://example.com/about</loc>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
  </url>
</urlset>

エラー監視とアナリティクス

公開後にアプリで何が起きているかを把握するための仕組み、すなわちエラー監視ツール(Sentry)とアクセス解析ツール(Google Analytics)の導入方法がわかります。

Sentryの導入(エラー追跡)

本番環境で発生したエラーを自動で検知・記録してくれるツールの基本セットアップです。

Bash
npm install @sentry/react
JSX
import * as Sentry from "@sentry/react";

Sentry.init({
  dsn: "YOUR_SENTRY_DSN",
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.replayIntegration(),
  ],
  tracesSampleRate: 1.0,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
});

function App() {
  return (
    <Sentry.ErrorBoundary fallback={<ErrorFallback />}>
      {/* アプリ */}
    </Sentry.ErrorBoundary>
  );
}

Google Analyticsの導入

ユーザーがどのページを見ているかを把握するためのアクセス解析の導入と、React Router連携時のページビュー記録方法です。

Bash
npm install react-ga4
JSX
import ReactGA from 'react-ga4';

// 初期化
ReactGA.initialize('G-XXXXXXXXXX');

// ページビューの記録
function App() {
  const location = useLocation();

  useEffect(() => {
    ReactGA.send({ hitType: "pageview", page: location.pathname });
  }, [location]);

  return <Routes>{/* ... */}</Routes>;
}

デプロイチェックリスト

公開する前」と「公開した後」、それぞれのタイミングで何を確認すればよいかが体系的にわかります。

抜け漏れのない安全なリリース作業ができるようになります。

デプロイ前の確認事項

公開ボタンを押す前に確認しておきたい項目を、コード品質・パフォーマンス・セキュリティ・SEO・UXの5つの観点でまとめます。

コード品質

  • ESLintエラーがない
  • TypeScriptエラーがない
  • ビルドが成功する
  • すべてのテストが通る

パフォーマンス

  • 不要なconsole.logを削除
  • 画像を最適化
  • 不要なパッケージを削除
  • コード分割を実装

セキュリティ

  • 環境変数に秘密情報がない
  • npm auditでセキュリティ問題がない
  • HTTPSを使用
  • セキュリティヘッダーを設定

SEO

  • メタタグを設定
  • robots.txtを作成
  • sitemap.xmlを作成
  • 適切なHTMLセマンティクス

ユーザー体験

  • ローディング状態を実装
  • エラー処理を実装
  • レスポンシブデザイン
  • アクセシビリティ対応

デプロイ後の確認事項

  • 本番環境でアプリが正常に動作
  • すべてのページが表示される
  • フォームが正常に送信できる
  • API連携が機能している
  • モバイルで正常に表示される
  • 異なるブラウザで動作確認

継続的デプロイ(CI/CD)

コードをGitHubにプッシュするだけで、テスト・ビルド・デプロイが自動で走る仕組み(CI/CD)の作り方がわかります。

手動デプロイのミスや手間をなくす考え方を身につけます。

GitHub Actionsの設定

GitHub Actionsを使って、push時に自動でテストとデプロイを実行するワークフローの書き方です。

プロジェクトのルート/.github/workflows/deploy.yml

YAML
name: Deploy to Vercel

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run tests
      run: npm test
    
    - name: Build
      run: npm run build
    
    - name: Deploy to Vercel
      uses: amondnet/vercel-action@v20
      with:
        vercel-token: ${{ secrets.VERCEL_TOKEN }}
        vercel-org-id: ${{ secrets.ORG_ID }}
        vercel-project-id: ${{ secrets.PROJECT_ID }}

トラブルシューティング

デプロイ作業でほぼ必ず遭遇する4つの典型的なエラー(404・環境変数・ビルドサイズ・CORS)について、原因と解決方法をセットで理解できるようになります。

よくある問題と解決方法

実際の現場でつまずきやすいポイントを、原因と対処法の形で1つずつ整理します。

問題1: ページをリロードすると404エラー

JSON
原因: React Routerを使っている場合、サーバー側でルーティング設定が必要
解決: リダイレクト設定を追加

Vercel: vercel.json
{
  "rewrites": [
    { "source": "/(.*)", "destination": "/index.html" }
  ]
}

Netlify: netlify.toml
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

問題2: 環境変数が反映されない

JSX
// ❌ 間違い
const apiUrl = process.env.API_URL;

// ✅ 正しい(Vite)
const apiUrl = import.meta.env.VITE_API_URL;

// ✅ 正しい(Create React App)
const apiUrl = process.env.REACT_APP_API_URL;

問題3: ビルドサイズが大きすぎる

Bash
# 使っていないパッケージを削除
npm uninstall unused-package

# 依存関係を分析
npm run build -- --report

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

問題4: CORSエラー

JSX
原因: APIサーバーとフロントエンドのドメインが異なる
解決: バックエンドでCORS設定を追加

// Express.jsの例
app.use(cors({
  origin: 'https://your-frontend-domain.com',
  credentials: true
}));

React入門シリーズまとめ

全20回のシリーズを通して何を学んできたかを振り返り、知識を整理し直すことができます。

Reactという技術全体の強みを再確認し、自分の習得状況を客観的に把握できるようになります。

学んだこと

シリーズ全体を、基礎・状態管理・応用・発展の4つのフェーズに分けて振り返ります。

基礎編(#01-#05)

  • Reactの基本概念とセットアップ
  • JSXの書き方
  • コンポーネントの作成
  • propsとstateの管理

状態管理とイベント(#06-#10)

  • useStateフック
  • イベントハンドリング
  • フォーム処理
  • 条件分岐とリスト表示

応用編(#11-#15)

  • useEffectとライフサイクル
  • カスタムフック
  • React Router
  • API連携
  • 実践的なアプリ開発

発展編(#16-#20)

  • useContextとグローバル状態管理
  • パフォーマンス最適化
  • TypeScriptとの組み合わせ
  • スタイリング手法
  • 本番環境へのデプロイ

Reactの強み

なぜReactがこれほど広く使われているのか、その理由を端的にまとめます。

コンポーネントベースの再利用性

宣言的なUI

豊富なエコシステム

大規模アプリケーションに対応

React Nativeでモバイル開発も可能

今後のステップ

「その先」に進むための具体的な道筋がわかります。

状態管理ライブラリやフレームワーク、テストなど次に学ぶべき技術の候補と、学習を続けるための情報源・練習プロジェクトのアイデアが手に入ります。

さらに学ぶべきトピック

Reactの基礎を終えた後に学ぶ価値のある技術領域を、カテゴリ別に紹介します。

状態管理ライブラリ

  • Redux / Redux Toolkit
  • Zustand
  • Jotai
  • Recoil

フレームワーク

  • Next.js(SSR/SSG)
  • Remix
  • Gatsby

テスト

  • Jest
  • React Testing Library
  • Vitest
  • Playwright / Cypress

バックエンド連携

  • GraphQL
  • tRPC
  • React Query / TanStack Query
  • SWR

UI開発

  • Storybook
  • Chakra UI / Material-UI
  • Framer Motion(アニメーション)

実践プロジェクトのアイデア

初級

  • Todoアプリ
  • 天気予報アプリ
  • 電卓
  • クイズアプリ

中級

  • ブログシステム
  • Eコマースサイト
  • チャットアプリ
  • 音楽プレイヤー

上級

  • ソーシャルメディア
  • プロジェクト管理ツール
  • リアルタイムコラボレーションツール
  • ダッシュボード管理システム

おわりに

React入門シリーズを最後まで読んでいただき、ありがとうございました!

このシリーズを通じて、Reactの基礎から実践的なアプリケーション開発、そして本番環境へのデプロイまでを学びました。しかし、これはあくまでスタート地点です。

継続的な学習が重要です:

  1. 毎日少しずつコードを書く
  2. 実際のプロジェクトを作る
  3. コミュニティに参加する
  4. 最新情報をキャッチアップする
  5. 他の人のコードを読む

Reactエコシステムは常に進化しています。

新しい機能や best practices が登場しますが、このシリーズで学んだ基礎は変わりません。