Webpack的loader和plugin是其核心功能,loader用于转换文件,plugin用于扩展功能。
常用Loader
1. 样式相关Loader
css-loader & style-loader
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
// style-loader: 将CSS插入到DOM中
// css-loader: 解析CSS文件中的@import和url()
}
]
}
};sass-loader & less-loader
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader' // 将Sass编译为CSS
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader' // 将Less编译为CSS
]
}postcss-loader
// webpack.config.js
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
['autoprefixer'], // 自动添加浏览器前缀
['cssnano'] // CSS压缩
]
}
}
}
]
}
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer'),
require('cssnano')
]
};2. JavaScript相关Loader
babel-loader
// webpack.config.js
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env', // ES6+转换
'@babel/preset-react' // React JSX转换
],
plugins: [
'@babel/plugin-proposal-class-properties'
]
}
}
}
// .babelrc
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["last 2 versions"]
}
}],
"@babel/preset-react"
]
}ts-loader
{
test: /\.tsx?$/,
use: 'ts-loader', // TypeScript编译
exclude: /node_modules/
}
// tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"jsx": "react"
}
}3. 文件相关Loader
file-loader & url-loader
// webpack.config.js
{
test: /\.(png|jpe?g|gif|svg)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
outputPath: 'images/'
}
}
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: {
loader: 'url-loader', // 小文件转base64,大文件使用file-loader
options: {
limit: 8192, // 8KB以下转base64
name: '[name].[hash].[ext]',
outputPath: 'fonts/'
}
}
}现代替代方案(Webpack 5内置)
// Webpack 5内置asset modules
{
test: /\.(png|jpe?g|gif|svg)$/,
type: 'asset/resource', // 相当于file-loader
generator: {
filename: 'images/[name].[hash][ext]'
}
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
type: 'asset', // 相当于url-loader
parser: {
dataUrlCondition: {
maxSize: 8192
}
}
}4. 其他常用Loader
raw-loader
{
test: /\.txt$/,
use: 'raw-loader' // 将文件作为字符串导入
}
// 使用
import textContent from './file.txt';
console.log(textContent);html-loader
{
test: /\.html$/,
use: 'html-loader' // 处理HTML中的图片等资源
}常用Plugin
1. HTML相关Plugin
HtmlWebpackPlugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // 模板文件
filename: 'index.html', // 输出文件名
title: '我的应用', // 页面标题
minify: {
removeComments: true, // 删除注释
collapseWhitespace: true // 删除空格
},
chunks: ['main'] // 指定包含的chunk
}),
// 多页面应用
new HtmlWebpackPlugin({
template: './src/about.html',
filename: 'about.html',
chunks: ['about']
})
]
};2. CSS相关Plugin
MiniCssExtractPlugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // 替代style-loader
'css-loader'
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash].css', // CSS文件名
chunkFilename: 'css/[id].[contenthash].css'
})
]
};CssMinimizerWebpackPlugin
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin({
parallel: true, // 并行压缩
minimizerOptions: {
preset: [
'default',
{
discardComments: { removeAll: true }
}
]
}
})
]
}
};3. JavaScript相关Plugin
TerserWebpackPlugin
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true, // 并行压缩
terserOptions: {
compress: {
drop_console: true, // 删除console
drop_debugger: true // 删除debugger
},
mangle: true, // 混淆变量名
format: {
comments: false // 删除注释
}
},
extractComments: false // 不提取注释到单独文件
})
]
}
};4. 开发相关Plugin
DefinePlugin
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env.API_URL': JSON.stringify('https://api.example.com'),
__DEV__: false
})
]
};
// 在代码中使用
if (__DEV__) {
console.log('开发模式');
}HotModuleReplacementPlugin
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.HotModuleReplacementPlugin() // 热模块替换
],
devServer: {
hot: true
}
};5. 优化相关Plugin
CleanWebpackPlugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ['**/*'], // 构建前清理
cleanAfterEveryBuildPatterns: ['*.js.map'] // 构建后清理
})
]
};CopyWebpackPlugin
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: 'public', // 源目录
to: 'assets', // 目标目录
globOptions: {
ignore: ['*.DS_Store'] // 忽略文件
}
},
{
from: 'src/images',
to: 'images'
}
]
})
]
};BundleAnalyzerPlugin
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static', // 生成静态HTML文件
openAnalyzer: false, // 不自动打开浏览器
reportFilename: 'bundle-report.html'
})
]
};6. PWA相关Plugin
WorkboxWebpackPlugin
const { GenerateSW } = require('workbox-webpack-plugin');
module.exports = {
plugins: [
new GenerateSW({
clientsClaim: true,
skipWaiting: true,
runtimeCaching: [
{
urlPattern: /^https:\/\/api\./,
handler: 'NetworkFirst',
options: {
cacheName: 'api-cache'
}
}
]
})
]
};完整配置示例
开发环境配置
// webpack.dev.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader']
},
{
test: /\.(png|jpe?g|gif|svg)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8192
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html'
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
],
devServer: {
hot: true,
open: true,
port: 3000
}
};生产环境配置
// webpack.prod.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[contenthash].js',
clean: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { targets: 'defaults' }],
'@babel/preset-react'
]
}
}
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{
test: /\.(png|jpe?g|gif|svg)$/,
type: 'asset',
generator: {
filename: 'images/[name].[contenthash][ext]'
}
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true
}
}),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash].css'
})
],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
compress: {
drop_console: true
}
}
}),
new CssMinimizerPlugin()
],
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
};这些loader和plugin构成了现代前端构建工具链的核心,能够处理各种文件类型、优化代码、提升开发体验。