webpack loader 本质是导出函数的 node.js 模块,接收源文件内容(字符串或 buffer),经处理后返回转换结果;需适配同步/异步调用、支持 sourcemap、兼容多种输入类型,并保持纯函数特性。

Webpack 的 Loader 本质是一个导出函数的 Node.js 模块,接收源文件内容(字符串或 Buffer),经过处理后返回转换后的内容。实现文本替换或编译转换类 Loader,关键在于正确读取、修改、返回内容,并适配 Webpack 的异步/同步调用约定。
基础结构:同步 Loader 示例
最简单的文本替换 Loader(如将 __VERSION__ 替换为当前 package.json 版本):
// version-replace-loader.js
const fs = require('fs');
const path = require('path');
module.exports = function(source) {
// this.callback 可用于异步或报错;此处用同步方式
const pkgPath = path.resolve(this.rootContext, 'package.json');
let version = '0.0.0';
try {
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
version = pkg.version;
} catch (e) {
// 用 this.emitWarning 或 this.emitError 报错更规范
this.emitWarning(new Error(`Failed to read version from ${pkgPath}`));
}
return source.replace(/__VERSION__/g, version);
};
使用时在 webpack.config.js 中配置:
module: {
rules: [{
test: /\.(js|ts|jsx|tsx)$/,
use: [
{ loader: './version-replace-loader.js' },
'babel-loader'
]
}]
}
支持异步与 SourceMap 的规范写法
真实项目中推荐用 this.async() 处理异步逻辑,并传递 SourceMap 以支持调试:
用于 inference.sh 的 JavaScript/TypeScript SDK,可运行 AI 应用、构建代理、集成 150+ 模型。包名:@inferencesh/sdk(npm install),完整 TypeScript 支持。
// async-replace-loader.js
module.exports = function(source, map) {
const callback = this.async(); // 告诉 Webpack:我将异步返回
// 模拟异步读取配置(例如从远程 API 或复杂文件解析)
setTimeout(() => {
const replaced = source.replace(/__API_BASE__/g, 'https://api.example.com');
// 第二个参数是 source map(可选),第三个是元数据(如 AST)
callback(null, replaced, map);
}, 10);
};
- 必须调用 callback,否则构建会卡住
- 第一个参数为 error,非 null 则中断构建并报错
- 第二个参数是处理后的 source 字符串(不能是 Buffer)
- 第三个参数可传入原始 SourceMap,Webpack 会自动合并链式 Loader 的 map
处理多种输入类型(字符串 / Buffer)和编码
Loader 接收的 source 可能是字符串或 Buffer(尤其启用 resourceQuery 或 raw 模式时)。应统一转为字符串处理:
module.exports = function(source) {
// 兼容 Buffer 和 string
const content = typeof source === 'string'
? source
: source.toString(this.options.charset || 'utf8');
// 执行替换
const result = content.replace(/{{\s*([^}]+)\s*}}/g, (match, key) => {
return this.getOptions?.()?.[key.trim()] ?? match;
});
// 返回字符串(Webpack 会按需转成 Buffer)
return result;
};
- 通过 this.getOptions() 获取 Loader 配置项(需安装
loader-utils并调用getOptions(this)) - 避免直接修改 source 原始引用,始终返回新字符串
- 不建议在 Loader 中做耗时操作(如读大文件、启动子进程),应提前缓存或移至 Plugin
调试技巧与注意事项
开发 Loader 时常用以下方式快速验证:
- 在 Loader 函数开头加 console.log(this.resource) 查看当前处理的文件路径
- 用 this.emitWarning(new Error('xxx')) 在控制台输出警告但不停止构建
- 在
webpack.config.js中临时加enforce: 'pre'让 Loader 优先执行,方便隔离测试 - 若 Loader 报错 “Cannot use import statement”,需确保其本身被 Babel 编译,或改用
require+module.exports
不复杂但容易忽略:Loader 必须是纯函数——相同输入始终返回相同输出,且不能有副作用(如写文件、改全局变量),否则影响持久化缓存和 HMR 行为。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










