jpskill.com
🛠️ 開発・MCP コミュニティ

webpack-vite

WebpackやViteといった主要なフロントエンドのビルドツール設定を最適化し、開発効率とパフォーマンスを向上させるSkill。

📜 元の英語説明(参考)

Frontend bundler configuration for Webpack and Vite. Use when user mentions "webpack", "vite", "bundler", "vite config", "webpack config", "code splitting", "tree shaking", "hot module replacement", "HMR", "build optimization", "bundle size", "chunk splitting", "loader", "plugin", "esbuild", "rollup", "dev server", or configuring JavaScript build tools.

🇯🇵 日本人クリエイター向け解説

一言でいうと

WebpackやViteといった主要なフロントエンドのビルドツール設定を最適化し、開発効率とパフォーマンスを向上させるSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o webpack-vite.zip https://jpskill.com/download/6145.zip && unzip -o webpack-vite.zip && rm webpack-vite.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/6145.zip -OutFile "$d\webpack-vite.zip"; Expand-Archive "$d\webpack-vite.zip" -DestinationPath $d -Force; ri "$d\webpack-vite.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して webpack-vite.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → webpack-vite フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-17
取得日時
2026-05-17
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

WebpackとViteのリファレンス

Viteの設定

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
    },
  },
  server: { port: 3000, open: true, strictPort: true },
  build: {
    outDir: 'dist',
    sourcemap: true,
    target: 'esnext',
    minify: 'esbuild',               // または 'terser' で drop_console
    rollupOptions: {
      output: {
        manualChunks: { vendor: ['react', 'react-dom'], router: ['react-router-dom'] },
      },
    },
  },
  optimizeDeps: {
    include: ['lodash-es', 'axios'],  // 強制的に事前バンドル
    exclude: ['your-local-package'],
  },
  css: {
    modules: { localsConvention: 'camelCaseOnly' },
    preprocessorOptions: { scss: { additionalData: `@use "@/styles/variables" as *;` } },
  },
});

Viteの環境変数

# .env / .env.local / .env.development / .env.production / .env.[mode]
# VITE_で始まる変数のみクライアントコードに公開されます
VITE_API_URL=https://api.example.com
DB_PASSWORD=secret                     # クライアントには公開されません
const apiUrl = import.meta.env.VITE_API_URL;
const isDev = import.meta.env.DEV;       // boolean
const mode = import.meta.env.MODE;       // 'development' | 'production' | custom

// 型宣言 (env.d.ts)
/// <reference types="vite/client" />
interface ImportMetaEnv { readonly VITE_API_URL: string }

Viteのプラグイン

import react from '@vitejs/plugin-react';           // Babelベース
import reactSWC from '@vitejs/plugin-react-swc';    // SWCベース (高速)
import vue from '@vitejs/plugin-vue';
import svgr from 'vite-plugin-svgr';                // SVGをReactコンポーネントとして
import { VitePWA } from 'vite-plugin-pwa';
import legacy from '@vitejs/plugin-legacy';          // IE11 / 古いブラウザのサポート
import { visualizer } from 'rollup-plugin-visualizer'; // バンドル分析

export default defineConfig({
  plugins: [
    reactSWC(),
    svgr(),
    VitePWA({ registerType: 'autoUpdate', workbox: { globPatterns: ['**/*.{js,css,html,ico,png,svg}'] } }),
    legacy({ targets: ['defaults', 'not IE 11'] }),
    visualizer({ open: true, gzipSize: true, brotliSize: true }),
  ],
});

Vite開発サーバーとプロキシ

export default defineConfig({
  server: {
    proxy: {
      '/api': { target: 'http://localhost:4000', changeOrigin: true, rewrite: (p) => p.replace(/^\/api/, '') },
      '/ws': { target: 'ws://localhost:4000', ws: true },
    },
    https: { key: './certs/key.pem', cert: './certs/cert.pem' },
    cors: true,
    fs: { allow: ['../..'] },            // モノレポ: ルート外のファイルを配信
  },
});

Webpack 5の設定

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

module.exports = {
  mode: 'production',
  entry: { main: './src/index.tsx', admin: './src/admin.tsx' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
    chunkFilename: '[name].[contenthash].chunk.js',
    clean: true,
    publicPath: '/',
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.jsx'],
    alias: { '@': path.resolve(__dirname, 'src') },
  },
  module: {
    rules: [
      { test: /\.(ts|tsx|js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader',
          options: { presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'] } } },
      { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'] },
      { test: /\.module\.css$/, use: [MiniCssExtractPlugin.loader,
          { loader: 'css-loader', options: { modules: true } }, 'postcss-loader'] },
      { test: /\.s[ac]ss$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'] },
      { test: /\.(png|jpg|gif|svg|webp)$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 8 * 1024 } } },
      { test: /\.(woff|woff2|eot|ttf|otf)$/, type: 'asset/resource' },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './public/index.html', minify: { collapseWhitespace: true } }),
    new MiniCssExtractPlugin({ filename: 'css/[name].[contenthash].css' }),
  ],
};
// 注: Webpack 5のアセットモジュールは、file-loader、url-loader、raw-loaderを置き換えます。

Webpackプラグイン

const { DefinePlugin, ProvidePlugin } = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
  plugins: [
    new DefinePlugin({
      'process.env.API_URL': JSON.stringify(process.env.API_URL),
      __DEV__: JSON.stringify(process.env.NODE_ENV === 'development'),
    }),
    new ProvidePlugin({ React: 'react' }),
    new CopyWebpackPlugin({ patterns: [{ from: 'public/assets', to: 'assets' }] }),
    new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: false }),
  ],
};

コード分割

// 動的インポート -- オンデマンドでロードされる個別のチャンクを作成
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
const Admin = React.lazy(() => import(/* webpackChunkName: "admin" */ './AdminPanel'));

// Webpack splitChunks
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: 20,
      minSize: 20000,
      cacheGroups: {
        vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: -10 },
        commons: { minChunks: 2, priority: -20, reuseExistingChunk: true },
      },
    },
    runtimeChunk: 'single',
  },
};

// Vite manual chunks
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('node_modules')) {
            if (id.includes('react')) return 'react-vend
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Webpack and Vite Reference

Vite Configuration

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@components': path.resolve(__dirname, './src/components'),
    },
  },
  server: { port: 3000, open: true, strictPort: true },
  build: {
    outDir: 'dist',
    sourcemap: true,
    target: 'esnext',
    minify: 'esbuild',               // or 'terser' for drop_console
    rollupOptions: {
      output: {
        manualChunks: { vendor: ['react', 'react-dom'], router: ['react-router-dom'] },
      },
    },
  },
  optimizeDeps: {
    include: ['lodash-es', 'axios'],  // force pre-bundling
    exclude: ['your-local-package'],
  },
  css: {
    modules: { localsConvention: 'camelCaseOnly' },
    preprocessorOptions: { scss: { additionalData: `@use "@/styles/variables" as *;` } },
  },
});

Vite Environment Variables

# .env / .env.local / .env.development / .env.production / .env.[mode]
# Only VITE_ prefixed vars are exposed to client code
VITE_API_URL=https://api.example.com
DB_PASSWORD=secret                     # NOT exposed to client
const apiUrl = import.meta.env.VITE_API_URL;
const isDev = import.meta.env.DEV;       // boolean
const mode = import.meta.env.MODE;       // 'development' | 'production' | custom

// Type declarations (env.d.ts)
/// <reference types="vite/client" />
interface ImportMetaEnv { readonly VITE_API_URL: string }

Vite Plugins

import react from '@vitejs/plugin-react';           // Babel-based
import reactSWC from '@vitejs/plugin-react-swc';    // SWC-based (faster)
import vue from '@vitejs/plugin-vue';
import svgr from 'vite-plugin-svgr';                // SVG as React components
import { VitePWA } from 'vite-plugin-pwa';
import legacy from '@vitejs/plugin-legacy';          // IE11 / older browser support
import { visualizer } from 'rollup-plugin-visualizer'; // bundle analysis

export default defineConfig({
  plugins: [
    reactSWC(),
    svgr(),
    VitePWA({ registerType: 'autoUpdate', workbox: { globPatterns: ['**/*.{js,css,html,ico,png,svg}'] } }),
    legacy({ targets: ['defaults', 'not IE 11'] }),
    visualizer({ open: true, gzipSize: true, brotliSize: true }),
  ],
});

Vite Dev Server and Proxy

export default defineConfig({
  server: {
    proxy: {
      '/api': { target: 'http://localhost:4000', changeOrigin: true, rewrite: (p) => p.replace(/^\/api/, '') },
      '/ws': { target: 'ws://localhost:4000', ws: true },
    },
    https: { key: './certs/key.pem', cert: './certs/cert.pem' },
    cors: true,
    fs: { allow: ['../..'] },            // monorepo: serve files outside root
  },
});

Webpack 5 Configuration

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

module.exports = {
  mode: 'production',
  entry: { main: './src/index.tsx', admin: './src/admin.tsx' },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
    chunkFilename: '[name].[contenthash].chunk.js',
    clean: true,
    publicPath: '/',
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.jsx'],
    alias: { '@': path.resolve(__dirname, 'src') },
  },
  module: {
    rules: [
      { test: /\.(ts|tsx|js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader',
          options: { presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript'] } } },
      { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'] },
      { test: /\.module\.css$/, use: [MiniCssExtractPlugin.loader,
          { loader: 'css-loader', options: { modules: true } }, 'postcss-loader'] },
      { test: /\.s[ac]ss$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'] },
      { test: /\.(png|jpg|gif|svg|webp)$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 8 * 1024 } } },
      { test: /\.(woff|woff2|eot|ttf|otf)$/, type: 'asset/resource' },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './public/index.html', minify: { collapseWhitespace: true } }),
    new MiniCssExtractPlugin({ filename: 'css/[name].[contenthash].css' }),
  ],
};
// Note: Webpack 5 asset modules replace file-loader, url-loader, and raw-loader.

Webpack Plugins

const { DefinePlugin, ProvidePlugin } = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
  plugins: [
    new DefinePlugin({
      'process.env.API_URL': JSON.stringify(process.env.API_URL),
      __DEV__: JSON.stringify(process.env.NODE_ENV === 'development'),
    }),
    new ProvidePlugin({ React: 'react' }),
    new CopyWebpackPlugin({ patterns: [{ from: 'public/assets', to: 'assets' }] }),
    new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: false }),
  ],
};

Code Splitting

// Dynamic import -- creates a separate chunk loaded on demand
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
const Admin = React.lazy(() => import(/* webpackChunkName: "admin" */ './AdminPanel'));

// Webpack splitChunks
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: 20,
      minSize: 20000,
      cacheGroups: {
        vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: -10 },
        commons: { minChunks: 2, priority: -20, reuseExistingChunk: true },
      },
    },
    runtimeChunk: 'single',
  },
};

// Vite manual chunks
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks(id) {
          if (id.includes('node_modules')) {
            if (id.includes('react')) return 'react-vendor';
            return 'vendor';
          }
        },
      },
    },
  },
});

Tree Shaking

// package.json -- mark as side-effect-free for tree shaking
{ "sideEffects": false }
// Or specify files with side effects:
{ "sideEffects": ["*.css", "*.scss", "./src/polyfills.ts"] }
import { debounce } from 'lodash-es';     // tree-shakeable (ESM)
const { debounce } = require('lodash');    // NOT tree-shakeable (CJS), bundles everything
// Webpack: set mode 'production' to enable terser + dead code elimination
// Vite: tree shaking via Rollup is on by default in production

Bundle Analysis

# Webpack
npx webpack --profile --json > stats.json && npx webpack-bundle-analyzer stats.json
# Or use BundleAnalyzerPlugin (see Webpack Plugins section)

# Vite -- use rollup-plugin-visualizer (see Vite Plugins section)

Webpack Dev Server

module.exports = {
  devServer: {
    port: 3000,
    hot: true,
    historyApiFallback: true,            // SPA routing fallback
    compress: true,
    proxy: [{ context: ['/api'], target: 'http://localhost:4000', changeOrigin: true,
              pathRewrite: { '^/api': '' } }],
    https: true,
    static: { directory: path.join(__dirname, 'public') },
  },
};

Production Optimization

// Webpack
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = {
  mode: 'production',
  devtool: 'source-map',                // 'hidden-source-map' to hide from users
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({ terserOptions: { compress: { drop_console: true, drop_debugger: true } } }),
      new CssMinimizerPlugin(),
    ],
  },
  plugins: [
    new CompressionPlugin({ algorithm: 'gzip', test: /\.(js|css|html|svg)$/, threshold: 10240 }),
  ],
};
// Vite production
export default defineConfig({
  build: {
    sourcemap: 'hidden',
    minify: 'terser',
    terserOptions: { compress: { drop_console: true } },
    cssCodeSplit: true,
    assetsInlineLimit: 4096,             // inline assets < 4KB as base64
    chunkSizeWarningLimit: 500,
  },
});

CSS Handling

// postcss.config.js -- shared by both Webpack and Vite
module.exports = {
  plugins: {
    'tailwindcss': {},
    'autoprefixer': {},
    'cssnano': process.env.NODE_ENV === 'production' ? {} : false,
  },
};
// Vite: install sass and import .scss directly -- no loader config needed
// Webpack: add sass-loader to module.rules (see Webpack 5 Configuration)

Migration from Webpack to Vite

npm install -D vite @vitejs/plugin-react    # 1. install
# 2. Create vite.config.ts                  # see "Vite Configuration" section
# 3. Move index.html to project root, add: <script type="module" src="/src/main.tsx"></script>
# 4. Update package.json scripts: "dev": "vite", "build": "tsc && vite build", "preview": "vite preview"
Webpack Vite
require() / module.exports import / export (ESM only)
process.env.X import.meta.env.VITE_X
file-loader / url-loader Native static asset handling
webpack.DefinePlugin define option in vite.config.ts
webpackChunkName comments rollupOptions.output.manualChunks
require.context() import.meta.glob()
webpack-dev-server proxy server.proxy in vite config

Monorepo Bundling

// Vite monorepo
export default defineConfig({
  resolve: { alias: { '@shared/ui': path.resolve(__dirname, '../../packages/ui/src') } },
  optimizeDeps: { include: ['@shared/ui'] },
  server: { fs: { allow: ['../..'] } },
});

// Webpack monorepo
module.exports = {
  resolve: { alias: { '@shared/ui': path.resolve(__dirname, '../../packages/ui/src') }, symlinks: false },
  module: { rules: [{
    test: /\.(ts|tsx)$/,
    include: [path.resolve(__dirname, 'src'), path.resolve(__dirname, '../../packages')],
    use: 'babel-loader',
  }] },
};

Performance Budgets

// Webpack -- built-in performance hints
module.exports = {
  performance: {
    hints: 'error',                      // 'warning' | 'error' | false
    maxAssetSize: 250000,                // 250KB per asset
    maxEntrypointSize: 400000,           // 400KB per entry point
    assetFilter: (file) => !/\.map$/.test(file),
  },
};
# size-limit -- CI-friendly, works with both Webpack and Vite
npm install -D size-limit @size-limit/preset-app
# package.json: "size-limit": [{ "path": "dist/assets/*.js", "limit": "200 KB", "gzip": true }]
npx size-limit