Webpack 5 är fortfarande den dominanta bundlern för storskaliga produktionsapplikationer. Denna guide täcker allt från grundläggande loaders till avancerade optimeringstekniker.
Webpack 5 grunder och entry/output
Filen webpack.config.js styr allt bundlingbeteende.
// 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,
},
};Viktiga loaders
Loaders transformerar filer innan de läggs till beroendegrafen.
// 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',
},
],
},
};Koddelning och lazy loading
Koddelning är Webpacks viktigaste optimeringsfunktion.
// 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
},
};Produktionsoptimering
Produktionsbyggen kräver aggressiv optimering.
// 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),
};Vanliga frågor
När ska jag använda Webpack istället för Vite?
Välj Webpack för Module Federation, stora befintliga kodbaser eller IE11-stöd.
Hur analyserar jag min Webpack-bundelstorlek?
Använd webpack-bundle-analyzer för interaktiv visualisering.
Vad är Module Federation i Webpack 5?
Module Federation tillåter flera Webpack-builds att dela kod vid körning.
Varför är min Webpack-build så långsam?
Vanliga orsaker: ingen persistent caching, för många loaders, babel utan node_modules-undantag.