Webpack 自定义 Loader 实现(markdown-loader 为例)
请手写一个自定义 Webpack Loader,将 .md 文件转换为 HTML 字符串,并支持传递 options(例如渲染配置)。
回答
我是大山
// markdown-loader.js
const marked = require('marked');
module.exports = function(source) {
// 开启缓存
this.cacheable(true);
// 获取 loader options
const options = this.getOptions();
// 配置 marked
marked.setOptions({
gfm: true,
breaks: options?.breaks ?? false,
...options?.marked,
});
// 转换为 HTML
const html = marked.parse(source);
// 返回 ES Module 格式(让 Webpack 当作 JS 模块处理)
return `export default ${JSON.stringify(html)};`;
};
// 使用异步版本处理大文件
module.exports = async function(source) {
const callback = this.async();
try {
const html = await marked.parse(source);
callback(null, `export default ${JSON.stringify(html)};`);
} catch (err) {
callback(err);
}
};
配置使用:
// webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.md$/,
use: [
{
loader: './loaders/markdown-loader.js',
options: {
breaks: true,
marked: { headerIds: false },
},
},
],
}],
},
};
关键 API:
this.cacheable()— 启用缓存this.getOptions()— 获取配置选项(Webpack 5)this.async()— 切换到异步模式this.emitFile(name, content)— 输出额外文件this.addDependency(file)— 声明依赖文件(用于 watch)this.resourcePath/this.resourceQuery— 当前资源信息