Loader Interface
loader-utils
loader-runner
一个最简单的 loader 代码结构
定义: loader 只是一个导出为函数的 JavaScript 模块
module.exports = function (source) {
return source;
};
使用loader-runner进行loader的调试
定义:允许你在不安装webpack的情况下运行loaders
作用:作为webpack的依赖,在webpack中执行loader
进行loader的开发和调试
import {runLoaders} from 'loader-runner';
runLoaders({
resource: "/abs/path/to/file.txt?query",
loaders: [],
context: {},
readResource: fs.readFile.bind(fs)
}, function(err, result) {
// err
// result
});
属性名 | 说明 |
---|---|
resource | 资源的绝对路径(可以增加查询字符串) |
loaders | loader 的绝对路径(可以增加查询字符串) |
context | 基础上下文之外的额外 loader 上下文 |
readResource | 读取资源的函数 |
loader的参数获取
通过loader-utils的getOptions方法获取
const loaderUtils = require("loader-utils");
module.exports = function(content) {
const { name } = loaderUtils.getOptions(this);
};
loader的异常处理
1、loader 内直接通过 throw 抛出
2、通过传递错误
this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?:any
);
loader的异步处理
module.exports = function(input) {
const callback = this.async();
// No callback -> return synchronous results // if (callback) { ... }
callback(null, input + input); //第一个参数是 Error,第二个参数是处理的结果
};
在 loader 中使用缓存
webpack 中默认开启 loader 缓存
(可以使用 this.cacheable(false) 关掉缓存)
缓存条件: loader 的结果在相同的输入下有确定的输出
(有依赖的 loader 无法使用缓存)
loader 如何进行文件输出
const loaderUtils = require("loader-utils");
module.exports = function (content) {
const url = loaderUtils.interpolateName(this, "[hash].[ext]", {
content,
});
this.emitFile(url, content);
const path = `__webpack_public_path__ + ${JSON.stringify(url)};`;
return `export default ${path}`;
};
插件的运行环境
只能在 webpack 里面运行
插件的基本结构
基本结构
/* 插件名称 */
class MyPlugin {
/* apply方法 */
apply(compiler) {
/* 插件的hooks */
compiler.hooks.done.tap(' My Plugin', (
stats/* stats is passed as argument when done hook is tapped. */
) => {
/* 逻辑 */
console.log('Hello World!');
});
}
}
module.exports = MyPlugin;
插件使用:
plugins: [ new MyPlugin() ]
搭建插件的运行环境
const path = require("path");
const DemoPlugin = require("./plugins/demo-plugin.js");
const PATHS = {
lib: path.join(__dirname, "app", "shake.js"),
build: path.join(__dirname, "build")
};
module.exports = {
entry: {
lib: PATHS.lib,
},
output: {
path: PATHS.build,
filename: "[name].js",
},
plugins: [new DemoPlugin()]
};
插件中如何获取传递的参数
通过插件的构造函数进行获取
constructor(options) {
this.options = options;
}
new ZipPlugin({
filename: 'offline'
})
插件的错误处理
参数校验阶段可以直接 throw 的方式抛出
throw new Error(“ Error Message”);
通过 compilation 对象的 warnings 和 errors 接收
compilation.warnings.push("warning");
compilation.errors.push("error");
通过 Compilation 进行文件写入
Compilation 上的 assets 可以用于文件写入
文件写入需要使用 webpack-sources (https://www.npmjs.com/package/webpack-sources)
const {
RawSource
} = require("webpack-sources");
module.exports = class DemoPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
const {
name
} = this.options;
compiler.plugin("emit", (compilation, cb) => {
compilation.assets[name] = new RawSource("demo");
cb();
})
}
};