Webpack 5 配置完全指南:从入门到精通
Hi,我是前端人类学(之前叫布兰妮甜)!
Webpack 是现代前端开发中不可或缺的模块打包工具,它的强大功能和灵活性使其成为构建复杂前端应用的首选。本文将深入探讨Webpack 5
的配置细节,带你从基础配置到高级优化,全面掌握 Webpack 5 的使用技巧。
文章目录
- 一、环境准备与核心概念
- 1.1. 安装
- 1.2 核心概念
- 二、基础配置
- 三、入口/出口(entry/output)深度解析
- 四、处理不同类型的资源
- 4.1 JS/TS
- 4.2 CSS/LESS/Sass
- 4.3 图片/字体/资源
- 五、使用插件增强功能
- 六、开发环境配置
- 七、生产环境优化
- 八、高级配置技巧
- 8.1 环境变量配置
- 8.2 多页面应用配置
- 8.3 自定义 loader 和插件
- 九、Webpack 5 新特性
- 十、性能优化
- 10.1 构建速度优化
- 10.2 输出文件优化
- 10.3 代码分割
- 十一、常见问题解决方案
- 十二、完整配置示例
一、环境准备与核心概念
1.1. 安装
npm i -D webpack webpack-cli webpack-dev-server@latest
1.2 核心概念
- 入口(Entry):指定 webpack 从哪个模块开始构建依赖图
- 输出(Output):告诉 webpack 在哪里输出它创建的 bundle 文件
- 加载器(Loader):让 webpack 能够处理非 JavaScript 文件「翻译官」
- 插件(Plugins):执行范围更广的任务,从打包优化到资源管理「任务管家」
- 模式(Mode):可以设置为 development、production 或 none
二、基础配置
// webpack.config.jsconst path = require('path');module.exports = {entry: './src/index.js',output: {path: path.resolve(__dirname, 'dist'),filename: 'main.js',clean: true // 5.20+ 自动清空 dist},mode: 'development'
};
这个配置告诉 webpack:
- 从 src/index.js 开始打包
- 输出到 dist/main.js
- 使用开发模式(不压缩代码,有 source map 等)
三、入口/出口(entry/output)深度解析
-
多入口
entry: {home: './src/home.js',about: './src/about.js', }
-
输出占位符
[name]
[contenthash:8]
[fullhash]
[id]
output: {filename: 'js/[name].[contenthash:8].js',assetModuleFilename: 'assets/[name].[hash][ext]', // 图片/字体统一路径 }
四、处理不同类型的资源
4.1 JS/TS
npm i -D babel-loader @babel/core @babel/preset-env core-js@3
{test: /\.[jt]sx?$/,exclude: /node_modules/,use: {loader: 'babel-loader',options: {presets: [['@babel/preset-env', { useBuiltIns: 'usage', corejs: 3 }],'@babel/preset-typescript',['@babel/preset-react', { runtime: 'automatic' }],],},},
},
4.2 CSS/LESS/Sass
npm i -D css-loader mini-css-extract-plugin postcss-loader autoprefixer cssnano
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
{test: /\.s?css$/,use: [MiniCssExtractPlugin.loader,'css-loader',{loader: 'postcss-loader',options: {postcssOptions: {plugins: ['autoprefixer', ...(process.env.NODE_ENV === 'production' ? ['cssnano'] : [])],},},},'sass-loader',],
},
plugins: [new MiniCssExtractPlugin({ filename: 'css/[name].[contenthash:8].css' }),
],
这里我们使用了四个 loader:
css-loader
- 作用:解析 CSS 文件中的
@import
和url()
等引用 - 功能:处理 CSS 模块之间的依赖关系,将 CSS 转换为 JavaScript 模块
- 作用:解析 CSS 文件中的
postcss-loader
- 作用:通过 PostCSS 处理 CSS 代码
- 功能:
- 使用
autoprefixer
插件为 CSS 属性添加浏览器厂商前缀 - 在生产环境(
NODE_ENV === 'production'
)下使用cssnano
插件压缩和优化 CSS
- 使用
MiniCssExtractPlugin.loader
- 作用:将 CSS 从 JavaScript bundle 中提取到单独的 CSS 文件
- 功能:替代了
style-loader
,用于生产环境优化
sass-loader
- 作用:将 Sass/SCSS 文件编译为 CSS
- 功能:支持使用 Sass 语法编写样式文件
这四个 loader 共同构成了完整的 CSS 处理链,从 Sass 编译到 CSS 提取和优化。
4.3 图片/字体/资源
module.exports = {// ...其他配置module: {rules: [{test: /\.(png|svg|jpg|jpeg|gif)$/i,type: 'asset/resource',},{test: /\.(woff|woff2|eot|ttf|otf)$/i,type: 'asset/resource',},],},
};
Webpack 5 引入了资源模块(asset modules),可以替代 file-loader 和 url-loader。
五、使用插件增强功能
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');module.exports = {// ...其他配置plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({title: 'My App',template: './src/index.html'}),],
};
CleanWebpackPlugin
:在每次构建前清理输出目录HtmlWebpackPlugin
:自动生成 HTML 文件并注入打包后的资源
六、开发环境配置
为了提高开发体验,我们需要配置开发服务器和 source map:
module.exports = {// ...其他配置devtool: 'inline-source-map',devServer: {contentBase: './dist',hot: true,},
};
然后安装 webpack-dev-server:
npm install --save-dev webpack-dev-server
在 package.json 中添加脚本:
"scripts": {"start": "webpack serve --open"
}
七、生产环境优化
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');module.exports = {mode: 'production',optimization: {minimizer: [new TerserPlugin(),new CssMinimizerPlugin(),],splitChunks: {chunks: 'all',},},performance: {hints: false,maxEntrypointSize: 512000,maxAssetSize: 512000},
};
TerserPlugin
:压缩 JavaScriptCssMinimizerPlugin
:压缩 CSSsplitChunks
:代码分割,提取公共依赖
八、高级配置技巧
8.1 环境变量配置
我们可以区分开发和生产环境:
const webpack = require('webpack');module.exports = (env) => {return {// ...其他配置plugins: [new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify(env.production ? 'production' : 'development')}),],};
};
8.2 多页面应用配置
module.exports = {entry: {pageOne: './src/pageOne/index.js',pageTwo: './src/pageTwo/index.js',},output: {filename: '[name].bundle.js',path: path.resolve(__dirname, 'dist'),},plugins: [new HtmlWebpackPlugin({template: './src/pageOne/index.html',filename: 'pageOne.html',chunks: ['pageOne']}),new HtmlWebpackPlugin({template: './src/pageTwo/index.html',filename: 'pageTwo.html',chunks: ['pageTwo']}),],
};
8.3 自定义 loader 和插件
创建自定义 loader:
// my-loader.js
module.exports = function(source) {return source.replace('World', 'Webpack');
};
创建自定义插件:
// my-plugin.js
class MyPlugin {apply(compiler) {compiler.hooks.done.tap('MyPlugin', (stats) => {console.log('编译完成!');});}
}module.exports = MyPlugin;
九、Webpack 5 新特性
-
持久化缓存:显著提高构建速度
module.exports = {cache: {type: 'filesystem',}, };
-
资源模块:内置处理资源文件的能力,不再需要 file-loader 等
-
模块联邦:实现微前端架构
// 作为远程模块 new ModuleFederationPlugin({name: 'app1',filename: 'remoteEntry.js',exposes: {'./Button': './src/Button',}, });// 作为主机使用远程模块 new ModuleFederationPlugin({name: 'app2',remotes: {app1: 'app1@http://localhost:3001/remoteEntry.js',}, });
-
Tree Shaking 改进:更好地消除未使用代码
-
长期缓存改进:通过确定的 chunk、模块 ID 和导出名称实现
十、性能优化
10.1 构建速度优化
module.exports = {// ...其他配置resolve: {extensions: ['.js', '.jsx', '.json'],alias: {'@': path.resolve(__dirname, 'src/'),},modules: [path.resolve(__dirname, 'src'), 'node_modules'],},
};
10.2 输出文件优化
module.exports = {output: {filename: '[name].[contenthash].js',path: path.resolve(__dirname, 'dist'),},
};
使用 contenthash
可以实现长期缓存,只有文件内容变化时 hash 才会改变。
10.3 代码分割
module.exports = {optimization: {splitChunks: {cacheGroups: {vendor: {test: /[\\/]node_modules[\\/]/,name: 'vendors',chunks: 'all',},},},runtimeChunk: 'single',},
};
十一、常见问题解决方案
-
处理路径问题
module.exports = {resolve: {alias: {Assets: path.resolve(__dirname, 'src/assets/')}} };
-
处理 polyfill
Webpack 5 不再自动包含 Node.js 核心模块的 polyfill,需要手动添加:module.exports = {resolve: {fallback: {"crypto": require.resolve("crypto-browserify"),"stream": require.resolve("stream-browserify"),"assert": require.resolve("assert"),"http": require.resolve("stream-http"),"https": require.resolve("https-browserify"),"os": require.resolve("os-browserify"),"url": require.resolve("url"),"buffer": require.resolve("buffer"),}} };
-
处理大型项目构建慢的问题
- 使用
thread-loader
并行处理 - 使用
cache-loader
缓存 loader 结果 - 使用
DLLPlugin
预编译不常变化的模块
- 使用
十二、完整配置示例
最后,我们来看一个完整的 webpack 配置示例:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');module.exports = (env) => {const isProduction = env.production;return {entry: './src/index.js',output: {filename: isProduction ? '[name].[contenthash].js' : '[name].js',path: path.resolve(__dirname, 'dist'),publicPath: '/',},mode: isProduction ? 'production' : 'development',devtool: isProduction ? 'source-map' : 'eval-cheap-module-source-map',module: {rules: [{test: /\.(js|jsx)$/,exclude: /node_modules/,use: 'babel-loader',},{test: /\.css$/i,use: [isProduction ? MiniCssExtractPlugin.loader : 'style-loader','css-loader','postcss-loader',],},{test: /\.(png|svg|jpg|jpeg|gif)$/i,type: 'asset/resource',generator: {filename: 'images/[hash][ext][query]',},},{test: /\.(woff|woff2|eot|ttf|otf)$/i,type: 'asset/resource',generator: {filename: 'fonts/[hash][ext][query]',},},],},plugins: [new CleanWebpackPlugin(),new HtmlWebpackPlugin({template: './src/index.html',minify: isProduction ? {collapseWhitespace: true,removeComments: true,} : false,}),isProduction && new MiniCssExtractPlugin({filename: '[name].[contenthash].css',}),].filter(Boolean),optimization: {minimizer: [new TerserPlugin(),new CssMinimizerPlugin(),],splitChunks: {chunks: 'all',},runtimeChunk: 'single',},devServer: {contentBase: './dist',hot: true,historyApiFallback: true,},resolve: {extensions: ['.js', '.jsx'],alias: {'@': path.resolve(__dirname, 'src/'),},},performance: {hints: isProduction ? 'warning' : false,},cache: {type: 'filesystem',},};
};
Webpack 5 的配置不是「越复杂越好」,而是「按需组合」。先跑通最小配置,再逐步叠加功能,配合持久化缓存和合理拆分,可以把冷启动时间从分钟级降到秒级。祝构建愉快!