Webpack 5 Configuration: From Basics to Advanced
Webpack 5 Configuration: From Basics to Advanced
Webpack 5 brings significant improvements in performance and features. Let's explore how to configure it effectively.
Basic Configuration
Installation
npm install -D webpack webpack-cli webpack-dev-server
Minimal Config
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
mode: 'development',
};
Entry and Output
Multiple Entry Points
module.exports = {
entry: {
main: './src/index.js',
admin: './src/admin.js',
vendor: ['react', 'react-dom'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true, // Clean dist folder before build
},
};
Loaders
Loaders transform files into modules.
Babel Loader
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
};
CSS Loaders
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
},
// CSS Modules
{
test: /\.module\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: { modules: true },
},
],
},
],
},
};
Asset Handling
module.exports = {
module: {
rules: [
// Images
{
test: /\.(png|jpg|gif|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024, // 8kb
},
},
generator: {
filename: 'images/[hash][ext]',
},
},
// Fonts
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[hash][ext]',
},
},
],
},
};
Plugins
Plugins extend webpack's capabilities.
HTML Plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
title: 'My App',
favicon: './public/favicon.ico',
}),
],
};
Mini CSS Extract Plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
],
};
Define Plugin
const { DefinePlugin } = require('webpack');
module.exports = {
plugins: [
new DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.API_URL': JSON.stringify('https://api.example.com'),
}),
],
};
Optimization
Code Splitting
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
react: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'react',
chunks: 'all',
},
},
},
},
};
Minification
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
compress: {
drop_console: true,
},
},
}),
new CssMinimizerPlugin(),
],
},
};
Caching
module.exports = {
output: {
filename: '[name].[contenthash].js',
},
optimization: {
runtimeChunk: 'single',
moduleIds: 'deterministic',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
};
Development Server
module.exports = {
devServer: {
static: './dist',
hot: true,
port: 3000,
open: true,
historyApiFallback: true,
proxy: {
'/api': {
target: 'http://localhost:4000',
changeOrigin: true,
},
},
client: {
overlay: {
errors: true,
warnings: false,
},
},
},
};
Source Maps
module.exports = {
devtool: 'eval-source-map', // Development
// 'source-map' // Production
// 'hidden-source-map' // Production without reference
// 'nosources-source-map' // Production without sources
};
Module Federation (Webpack 5)
Share code between applications at runtime:
// App 1 - Host
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'host',
remotes: {
remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',
},
}),
],
};
// App 2 - Remote
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/Button',
'./Header': './src/Header',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
}),
],
};
Using Remote Components
// In host app
const RemoteButton = React.lazy(() => import('remoteApp/Button'));
function App() {
return (
<React.Suspense fallback="Loading...">
<RemoteButton />
</React.Suspense>
);
}
Environment Configuration
// webpack.common.js
const { merge } = require('webpack-merge');
module.exports = {
// Common config
};
// webpack.dev.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
devServer: { /* ... */ },
});
// webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map',
optimization: {
minimize: true,
},
});
TypeScript Support
module.exports = {
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
};
Performance Tips
module.exports = {
cache: {
type: 'filesystem', // Enable persistent caching
},
performance: {
hints: 'warning',
maxAssetSize: 244 * 1024,
maxEntrypointSize: 244 * 1024,
},
stats: {
colors: true,
modules: false,
},
};
Full Production Config
const path = require('path');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
],
optimization: {
minimize: true,
minimizer: [new TerserPlugin(), new CssMinimizerPlugin()],
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
performance: {
hints: false,
},
});
Conclusion
Webpack 5 provides powerful tools for building modern JavaScript applications. Understanding entry points, loaders, plugins, and optimization techniques allows you to create efficient build pipelines tailored to your needs.