Webpack Loader 与 Plugin 的区别及执行原理
请解释 Webpack 中 Loader 和 Plugin 的核心区别、各自的执行原理,以及如何手写一个简单的 Loader 和 Plugin。
回答
屠龙少年
Loader vs Plugin:
| 特性 | Loader | Plugin |
|------|--------|--------|
| 职责 | 文件级别转换(非 JS → JS) | 打包流程钩子(任何构建阶段) |
| 执行 | 从右到左链式管道 | Tapable 事件钩子系统 |
| 输入 | 文件内容(string/buffer) | 打包上下文(compiler/compilation) |
| 输出 | 转换后的模块内容 | 影响打包结果、输出文件、优化等 |
| 配置 | module.rules | plugins 数组 |
Loader 原理:
// 简单的 reverse-loader
module.exports = function(source) {
const result = source.split('').reverse().join('');
return result; // 或 this.callback(null, result)
};
// 从右到左: style-loader → css-loader → less-loader
- Loader 是函数,接收资源文件内容
this指向 LoaderContext,提供this.async()、this.query、this.emitFile()等pitch方法可拦截 Loader 链
Plugin 原理:
class MyPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
compilation.assets['my-file.txt'] = {
source: () => 'hello',
size: () => 5,
};
callback();
});
}
}
- Plugin 是类,有
apply(compiler)方法 - 通过
compiler.hooks(Tapable)监听构建生命周期事件 - 常见钩子:
emit、done、compile、make、thisCompilation