webpack の使い方

Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.

v5.105.442.2M/週MITビルドツール
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

webpack の使い方 — JavaScriptモジュールバンドラーの決定版

一言でいうと

webpackは、JavaScript/TypeScriptをはじめとするあらゆるアセットを依存関係を解決しながらバンドル(結合)するモジュールバンドラーです。ES Modules・CommonJS・AMDの各モジュール形式に対応し、コード分割やローダーによるファイル変換など、フロントエンド開発に必要なビルド機能を包括的に提供します。

どんな時に使う?

  • フロントエンドアプリケーションのビルド — 複数のJavaScript/TypeScriptファイルをブラウザで実行可能な形にバンドルしたいとき
  • コード分割(Code Splitting)による最適化 — 初期ロード時間を短縮するために、アプリケーションを複数のチャンクに分割し、必要なタイミングで非同期読み込みしたいとき
  • CSS・画像・フォントなど非JSアセットの統合管理 — ローダーを使ってTypeScript→JavaScript変換、Sass→CSS変換、画像のBase64化などをビルドパイプラインに組み込みたいとき

インストール

# npm
npm install --save-dev webpack webpack-cli

# yarn
yarn add --dev webpack webpack-cli

# pnpm
pnpm add -D webpack webpack-cli

注意: webpack 本体に加えて、CLIから実行するために webpack-cli も必要です。

基本的な使い方

プロジェクト構成

my-app/
├── src/
│   └── index.ts
├── dist/
├── webpack.config.js
├── tsconfig.json
└── package.json

webpack.config.js(TypeScript対応の基本構成)

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

module.exports = {
  mode: 'production',
  entry: './src/index.ts',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
};

src/index.ts

import { greet } from './utils';

const message: string = greet('webpack');
console.log(message);

ビルド実行

npx webpack

package.json にスクリプトを追加しておくのが一般的です。

{
  "scripts": {
    "build": "webpack --mode production",
    "dev": "webpack serve --mode development"
  }
}

よく使うAPI・設定オプション — webpack の使い方を深掘り

1. entry — エントリーポイントの設定

バンドルの起点となるファイルを指定します。複数エントリーにも対応しています。

// 単一エントリー
module.exports = {
  entry: './src/index.ts',
};

// 複数エントリー(マルチページアプリケーション向け)
module.exports = {
  entry: {
    main: './src/index.ts',
    admin: './src/admin.ts',
  },
  output: {
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
  },
};

2. module.rules(ローダー) — ファイル変換の設定

webpack単体ではJavaScriptとJSONしか理解できません。ローダーを使うことで、あらゆるファイル形式をモジュールとして扱えます。

module.exports = {
  module: {
    rules: [
      // TypeScript
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      // CSS + CSS Modules
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      // Sass/SCSS
      {
        test: /\.s[ac]ss$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },
      // 画像ファイル(webpack 5 の Asset Modules)
      {
        test: /\.(png|jpg|gif|svg)$/,
        type: 'asset/resource',
      },
    ],
  },
};

ポイント: use 配列のローダーは**右から左(下から上)**の順に適用されます。['style-loader', 'css-loader', 'sass-loader'] の場合、Sass → CSS → DOMへの注入の順で処理されます。

3. plugins — ビルドプロセスの拡張

プラグインはバンドル全体に対する処理を行います。HTML生成、CSS抽出、環境変数注入など多岐にわたります。

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');

module.exports = {
  plugins: [
    // HTMLファイルを自動生成し、バンドルを自動挿入
    new HtmlWebpackPlugin({
      template: './src/index.html',
      title: 'My App',
    }),
    // CSSを別ファイルとして抽出(本番向け)
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
    }),
    // 環境変数をコード内で参照可能にする
    new webpack.DefinePlugin({
      'process.env.API_URL': JSON.stringify('https://api.example.com'),
    }),
  ],
};

4. optimization — コード分割と最適化

module.exports = {
  optimization: {
    // コード分割の設定
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
    // ランタイムコードを別チャンクに分離
    runtimeChunk: 'single',
    // 本番ビルド時のminify(mode: 'production' ではデフォルトで有効)
    minimize: true,
  },
};

5. devServer — 開発サーバーの設定

webpack-dev-server パッケージを追加インストールすると、HMR(Hot Module Replacement)対応の開発サーバーが使えます。

npm install --save-dev webpack-dev-server
module.exports = {
  devServer: {
    static: './dist',
    port: 3000,
    hot: true,
    open: true,
    // APIプロキシ設定
    proxy: [
      {
        context: ['/api'],
        target: 'http://localhost:8080',
        changeOrigin: true,
      },
    ],
    historyApiFallback: true, // SPA向け:全ルートをindex.htmlにフォールバック
  },
};
npx webpack serve

実践的な設定例:開発/本番の切り替え

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = (env, argv) => {
  const isProduction = argv.mode === 'production';

  return {
    entry: './src/index.ts',
    output: {
      filename: isProduction ? '[name].[contenthash].js' : '[name].js',
      path: path.resolve(__dirname, 'dist'),
      clean: true,
    },
    devtool: isProduction ? 'source-map' : 'eval-source-map',
    resolve: {
      extensions: ['.ts', '.tsx', '.js'],
      alias: {
        '@': path.resolve(__dirname, 'src'),
      },
    },
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          use: 'ts-loader',
          exclude: /node_modules/,
        },
        {
          test: /\.css$/,
          use: [
            isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
            'css-loader',
          ],
        },
        {
          test: /\.(png|jpg|gif|svg|woff2?)$/,
          type: 'asset',
          parser: {
            dataUrlCondition: {
              maxSize: 8 * 1024, // 8KB未満はインライン化
            },
          },
        },
      ],
    },
    plugins: [
      new HtmlWebpackPlugin({ template: './src/index.html' }),
      ...(isProduction
        ? [new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' })]
        : []),
    ],
    optimization: {
      splitChunks: { chunks: 'all' },
    },
    devServer: {
      port: 3000,
      hot: true,
    },
  };
};

類似パッケージとの比較

項目webpackViteRollupesbuild
主な用途アプリケーションバンドルアプリケーション開発・バンドルライブラリバンドル超高速バンドル/トランスパイル
開発サーバー速度△(バンドル後に配信)◎(ESM native、HMR高速)×(別途必要)
設定の複雑さ高い低い中程度低い
プラグインエコシステム◎(最大規模)○(Rollupプラグイン互換)
Tree Shaking
コード分割
レガシーブラウザ対応○(プラグインで対応)
成熟度・実績◎(10年以上の歴史)○(急速に普及中)

選定の目安:

  • 新規プロジェクト → Viteが開発体験で優位。特にReact/Vue/Svelteなどのフレームワーク利用時
  • 既存の大規模プロジェクト → webpackの豊富なプラグインとローダーが活きる
  • ライブラリ開発 → Rollupが出力の最適化に強い
  • ビルド速度最優先 → esbuildが圧倒的に高速

注意点・Tips

1. webpack 5 の Asset Modules を使う

webpack 5 では file-loaderurl-loaderraw-loader が不要になりました。代わりに組み込みの Asset Modules を使いましょう。

// ❌ webpack 4 以前のやり方
{ test: /\.png$/, use: 'file-loader' }

// ✅ webpack 5
{ test: /\.png$/, type: 'asset/resource' }
type旧ローダー相当動作
asset/resourcefile-loaderファイルを出力し、URLを返す
asset/inlineurl-loaderBase64データURLとしてインライン化
asset/sourceraw-loaderソースコードをそのまま文字列として返す
asseturl-loader(size制限付き)サイズに応じて自動判定

2. contenthash でキャッシュバスティング

本番ビルドでは [contenthash] を使うことで、ファイル内容が変わったときだけファイル名が変わり、ブラウザキャッシュを効率的に活用できます。

output: {
  filename: '[name].[contenthash:8].js', // 8文字に短縮も可能
}

3. resolve.alias でインポートパスを簡潔に

resolve: {
  alias: {
    '@components': path.resolve(__dirname, 'src/components'),
    '@utils': path.resolve(__dirname, 'src/utils'),
  },
}
// ❌ 相対パスが深くなりがち
import { Button } from '../../../components/Button';

// ✅ エイリアスですっきり
import { Button } from '@components/Button';

注意: TypeScriptを使う場合は tsconfig.jsonpaths にも同じエイリアスを設定する必要があります。

4. ビルドサイズの分析

バンドルサイズが肥大化したら webpack-bundle-analyzer で可視化しましょう。

npm install --save-dev webpack-bundle-analyzer
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin({ analyzerMode: 'static' }),
  ],
};

5. Node.js API からの利用

CLIではなくプログラムからwebpackを実行することも可能です。

import webpack, { Configuration, Stats } from 'webpack';

const config: Configuration = {
  mode: 'production',
  entry: './src/index.ts',
  output: {
    filename: 'bundle.js',
    path: __dirname + '/dist',
  },
};

const compiler = webpack(config);

compiler.run((err: Error | null, stats?: Stats) => {
  if (err) {
    console.error(err);

比較記事