DevToolBoxGRATIS
Blog

Webpack 5 Configuratiegids: Loaders, Plugins, Code Splitting

13 minby DevToolBox

Webpack 5 blijft de dominante bundler voor grootschalige productietoepassingen. Deze gids behandelt alles van basisloaders tot geavanceerde optimalisatietechnieken.

Webpack 5 basisprincipes en entry/output

Het webpack.config.js-bestand beheert al het bundlinggedrag.

// webpack.config.js — Complete Production Config

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

const isDev = process.env.NODE_ENV !== 'production';

module.exports = {
  mode: isDev ? 'development' : 'production',

  entry: {
    main: './src/index.tsx',
    // Multiple entry points for different pages
    // admin: './src/admin/index.tsx',
  },

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: isDev ? '[name].js' : '[name].[contenthash:8].js',
    chunkFilename: isDev ? '[name].chunk.js' : '[name].[contenthash:8].chunk.js',
    assetModuleFilename: 'assets/[hash:8][ext][query]',
    clean: true,   // Remove old files on each build
    publicPath: '/',
  },

  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.jsx', '.json'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
    },
  },

  // Persistent filesystem cache — huge speed improvement for incremental builds
  cache: {
    type: 'filesystem',
    buildDependencies: {
      config: [__filename], // Invalidate cache when config changes
    },
  },

  devServer: {
    port: 3000,
    hot: true,
    historyApiFallback: true,
    compress: true,
  },
};

Essentiële loaders

Loaders transformeren bestanden voordat ze worden toegevoegd aan de afhankelijkheidsgraph.

// Essential Webpack Loaders Configuration

module.exports = {
  module: {
    rules: [
      // 1. TypeScript/JavaScript with Babel
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', { targets: '>0.25%, not dead' }],
              ['@babel/preset-react', { runtime: 'automatic' }],
              '@babel/preset-typescript',
            ],
            // Cache Babel results for faster rebuilds
            cacheDirectory: true,
            cacheCompression: false,
          },
        },
      },

      // 2. CSS / SCSS / PostCSS
      {
        test: /\.module\.(css|scss)$/,  // CSS Modules
        use: [
          isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: { modules: true, importLoaders: 2 },
          },
          'postcss-loader',
          'sass-loader',
        ],
      },
      {
        test: /(?!\.module)\.(css|scss)$/,  // Global CSS
        use: [
          isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader',
        ],
      },

      // 3. Images and fonts (Webpack 5 Asset Modules — no loader needed)
      {
        test: /\.(png|jpg|jpeg|gif|webp)$/i,
        type: 'asset',  // Auto-chooses between inline and resource
        parser: {
          dataUrlCondition: { maxSize: 10 * 1024 }, // Inline if < 10KB
        },
      },
      {
        test: /\.svg$/,
        use: ['@svgr/webpack'],  // Import SVGs as React components
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
      },
    ],
  },
};

Code splitting en lazy loading

Code splitting is de belangrijkste optimalisatiefunctie van Webpack.

// Code Splitting and Lazy Loading

// 1. Dynamic imports (automatic code splitting)
// React.lazy creates a separate chunk for each lazy component
import React, { lazy, Suspense } from 'react';
import { Routes, Route } from 'react-router-dom';

const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));
const Analytics = lazy(() => import('./pages/Analytics'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/dashboard" element={<Dashboard />} />
        <Route path="/settings" element={<Settings />} />
        <Route path="/analytics" element={<Analytics />} />
      </Routes>
    </Suspense>
  );
}

// 2. Manual chunk naming with magic comments
const HeavyChart = lazy(
  () => import(/* webpackChunkName: "charts" */ './components/HeavyChart')
);

// 3. Webpack SplitChunksPlugin configuration
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        // Vendor chunk: node_modules
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
          priority: 20,
        },
        // Separate React from other vendors
        react: {
          test: /[\\/]node_modules[\\/](react|react-dom|react-router)[\\/]/,
          name: 'react-vendor',
          chunks: 'all',
          priority: 30,
        },
        // Shared chunks used by 2+ modules
        common: {
          name: 'common',
          minChunks: 2,
          priority: 10,
          reuseExistingChunk: true,
        },
      },
    },
    runtimeChunk: 'single',  // Separate runtime chunk
  },
};

Productieoptimalisatie

Productiebuilds vereisen agressieve optimalisatie.

// Production Optimization Configuration
module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true,  // Use all CPU cores
        terserOptions: {
          compress: {
            drop_console: true,    // Remove console.log in production
            drop_debugger: true,
            pure_funcs: ['console.log'],
          },
          format: { comments: false },
        },
      }),
      new CssMinimizerPlugin(),
    ],
    // Tree shaking — only include used exports
    usedExports: true,
    sideEffects: true,  // Respect package.json sideEffects field
  },

  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash:8].css',
    }),
    new HtmlWebpackPlugin({
      template: './public/index.html',
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true,
      },
    }),
    // Only add analyzer when needed: ANALYZE=true npm run build
    process.env.ANALYZE && new BundleAnalyzerPlugin(),
  ].filter(Boolean),
};

Veelgestelde vragen

Wanneer Webpack gebruiken in plaats van Vite?

Kies Webpack voor Module Federation, grote bestaande codebases of IE11-ondersteuning.

Hoe analyseer ik mijn Webpack-bundelgrootte?

Gebruik webpack-bundle-analyzer voor interactieve visualisatie.

Wat is Module Federation in Webpack 5?

Module Federation staat meerdere Webpack-builds toe om code te delen tijdens runtime.

Waarom is mijn Webpack-build zo traag?

Veelvoorkomende oorzaken: geen persistent caching, te veel loaders, babel zonder node_modules uitsluiten.

Gerelateerde tools

𝕏 Twitterin LinkedIn
Was dit nuttig?

Blijf op de hoogte

Ontvang wekelijkse dev-tips en nieuwe tools.

Geen spam. Altijd opzegbaar.

Try These Related Tools

{ }JSON FormatterJSJavaScript Minifier

Related Articles

Vite Plugin Ontwikkeling: Bouw Custom Plugins van Scratch 2026

Aangepaste Vite plugins maken 2026: plugin-hooks, transform-API, virtuele modules, HMR-integratie.

Webpack vs Vite 2026: Welke build tool moet je kiezen?

Uitgebreide vergelijking van Webpack en Vite in 2026: prestaties, ecosysteem en migratiestrategieën.

Monorepo Tools 2026: Turborepo vs Nx vs Lerna vs pnpm Workspaces

Volledige vergelijking van monorepo-tools 2026: Turborepo, Nx, Lerna en pnpm workspaces voor de juiste keuze.