Appearance
Webpack 加载器(Loaders)
加载器(Loaders)是 Webpack 的核心特性之一,它允许 Webpack 处理其他类型的文件(不仅仅是 JavaScript),并将它们转换为有效的模块。
加载器基础概念
加载器本质上是一个函数,它接受源文件作为参数,并返回转换后的结果。加载器可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。
加载器配置结构
javascript
module.exports = {
module: {
rules: [
{
test: /\.css$/, // 用于匹配文件的正则表达式
use: [ // 使用的加载器(从右到左执行)
'style-loader', // 最后执行
'css-loader' // 首先执行
]
}
]
}
};
常用加载器
1. CSS 相关加载器
javascript
module.exports = {
module: {
rules: [
// 基础 CSS 加载器
{
test: /\.css$/,
use: [
'style-loader', // 将 CSS 注入到 DOM 中
'css-loader' // 解析 CSS 文件中的 @import 和 url()
]
},
// 带有 PostCSS 的 CSS 加载器
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true, // 启用 CSS 模块
importLoaders: 1 // 在 css-loader 前应用的 loader 数量
}
},
'postcss-loader' // PostCSS 处理
]
},
// SCSS/SASS 加载器
{
test: /\.(scss|sass)$/,
use: [
'style-loader',
'css-loader',
'sass-loader' // 将 Sass 编译为 CSS
]
},
// LESS 加载器
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader' // 将 Less 编译为 CSS
]
}
]
}
};
2. JavaScript 相关加载器
javascript
module.exports = {
module: {
rules: [
// Babel 加载器
{
test: /\.js$/,
exclude: /node_modules/, // 排除 node_modules 目录
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: {
browsers: ['last 2 versions']
}
}]
],
plugins: [
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-object-rest-spread'
]
}
}
},
// TypeScript 加载器
{
test: /\.tsx?$/,
use: 'ts-loader', // 或者使用 babel-loader
exclude: /node_modules/
},
// CoffeeScript 加载器
{
test: /\.coffee$/,
use: 'coffee-loader'
}
]
}
};
3. 资源加载器
javascript
module.exports = {
module: {
rules: [
// 图片资源加载器 (Webpack 5)
{
test: /\.(png|jpe?g|gif|svg|webp)$/i,
type: 'asset/resource', // 输出单独文件
generator: {
filename: 'images/[name].[hash][ext]'
}
},
// 小图片转 Base64 (Webpack 5)
{
test: /\.(png|jpe?g|gif|svg)$/i,
type: 'asset/inline', // 转换为 data URI
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8kb 以下的文件转为 base64
}
}
},
// 字体加载器
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash][ext]'
}
},
// 音频视频加载器
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)$/i,
type: 'asset/resource',
generator: {
filename: 'media/[name].[hash][ext]'
}
}
]
}
};
4. 文件加载器(Webpack 4 兼容)
javascript
module.exports = {
module: {
rules: [
// 文件加载器 - 保留原始文件名
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[hash].[ext]',
outputPath: 'images/'
}
}
]
},
// URL 加载器 - 小文件转 Base64
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 8kb 以下转为 base64
name: '[name].[hash].[ext]',
outputPath: 'images/'
}
}
]
}
]
}
};
高级加载器配置
1. 自定义加载器
javascript
// 自定义加载器示例
function myLoader(source) {
// source 是模块的原始源代码
const newSource = doSomeTransformation(source);
return `export default ${JSON.stringify(newSource)}`;
}
// 异步加载器
function asyncLoader(source) {
const callback = this.async();
someAsyncOperation(source, (err, result) => {
if (err) return callback(err);
callback(null, result);
});
}
module.exports = {
module: {
rules: [
{
test: /\.custom$/,
use: path.resolve(__dirname, 'my-loader.js')
}
]
}
};
2. 加载器链配置
javascript
module.exports = {
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'thread-loader', // 在 worker 池中运行
options: {
workers: 2
}
},
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
]
}
]
}
};
3. 条件加载器
javascript
module.exports = {
module: {
rules: [
// 开发环境下使用 CSS 模块
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: process.env.NODE_ENV === 'development'
}
}
]
},
// 生产环境下提取 CSS
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, // 生产环境下使用 MiniCssExtractPlugin
'css-loader'
]
}
]
}
};
常见加载器详解
1. CSS 加载器
javascript
// 完整的 CSS 配置
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
process.env.NODE_ENV === 'production'
? MiniCssExtractPlugin.loader // 生产环境提取 CSS
: 'style-loader', // 开发环境注入 CSS
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[local]_[hash:base64:5]' // CSS 模块类名
},
sourceMap: true, // 启用源映射
importLoaders: 2 // import 的资源经过后续 2 个 loader 处理
}
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
['autoprefixer', {}],
['postcss-preset-env', {}]
]
}
}
}
]
}
]
}
};
2. 图片优化加载器
javascript
module.exports = {
module: {
rules: [
// 响应式图片生成
{
test: /\.(jpe?g|png|webp)$/i,
use: [
{
loader: 'responsive-loader',
options: {
adapter: require('responsive-loader/sharp'),
sizes: [300, 600, 1000],
placeholder: true,
placeholderSize: 50
}
}
]
},
// SVG 优化
{
test: /\.svg$/,
use: [
{
loader: 'svg-inline-loader', // 内联 SVG
options: {
removeTags: true,
removingTags: ['desc', 'defs', 'title']
}
}
]
}
]
}
};
3. 模板加载器
javascript
module.exports = {
module: {
rules: [
// Handlebars 模板
{
test: /\.hbs$/,
use: 'handlebars-loader'
},
// Pug 模板
{
test: /\.pug$/,
use: 'pug-loader'
},
// HTML 模板
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: {
minimize: true,
sources: {
list: [
{
tag: 'img',
attribute: 'src',
type: 'src'
}
]
}
}
}
]
}
]
}
};
加载器性能优化
1. 排除不必要的目录
javascript
module.exports = {
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
include: path.resolve(__dirname, 'src'), // 只处理 src 目录
exclude: /node_modules/ // 排除 node_modules
}
]
}
};
2. 使用缓存
javascript
module.exports = {
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true, // 启用缓存
cacheCompression: false // 禁用缓存压缩
}
}
]
}
]
}
};
3. 并行处理
javascript
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'thread-loader',
options: {
workers: require('os').cpus().length - 1
}
},
'babel-loader'
]
}
]
},
optimization: {
minimizer: [
new TerserPlugin({
parallel: true // 并行压缩
})
]
}
};
小结
加载器是 Webpack 的重要组成部分,它们扩展了 Webpack 处理不同文件类型的能力。通过合理配置加载器,我们可以处理 CSS、图片、字体、模板等各种资源,并将它们转换为 JavaScript 模块。理解加载器的工作原理和配置方法,可以帮助我们更好地优化构建流程。