标签:tps erro timeout 依赖 test style 配置 top 包含
?己编写一个Loader的过程是比较简单的,
Loader就是?个函数,声明式函数,不能?用箭头函数
拿到源代码,作进一步的修饰处理,再返回处理后的源码就可以了
//index.js
console.log("hello world");
//replaceLoader.js
module.exports = function(source) {
console.log(source, this, this.query);
return source.replace(world,‘大家好‘)
};
//需要?声明式函数,因为要上到上下文的this,用到this的数据,该函数接受一个参数
//需要使用node核心模块path来处理路径
const path = require(‘path‘);
......
module: {
rules: [
{
test: /\.js$/,
use: path.resolve(__dirname, "./loader/replaceLoader.js")
}
]
},
² this.query
² loader-utils
²
//需要使用node核?心模块path来处理路径
const path = require(‘path‘);
module: {
rules: [
{
test: /\.js$/,
use: path.resolve(__dirname, "./loader/replaceLoader.js")
}
]
},
//webpack.config.js
.........
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: path.resolve(__dirname, "./loader/replaceLoader.js"),
options: {
name: "你好吗"
}
}
]
}
]
},
//replaceLoader.js
//方式一: this.query获取参数
module.exports = function(source) {
//this.query 通过this.query来接受配置文件传递进来的参数
//return source.replace("world", this.query.name);
return source.replace("world", options.name);
}
//方式二: loader-utils获取参数,官方推荐
const loaderUtils = require("loader-utils");//官方推荐处理loader,query的?具
module.exports = function(source) {
//this.query 通过this.query来接受配置文件传递进来的参数
const options = loaderUtils.getOptions(this);
return source.replace("world", options.name);
}
//replaceLoader.js
const loaderUtils = require("loader-utils");//官?方推荐处理理loader,query的?工具
module.exports = function(source) {
const options = loaderUtils.getOptions(this);
const result = source.replace("world", options.name);
this.callback(null, result);
};
//this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any );
我们使?this.async来处理,他会返回this.callback
//replaceLoader.js
const loaderUtils = require("loader-utils");//官?方推荐处理理loader,query的?工具
module.exports = function(source) {
const options = loaderUtils.getOptions(this);
const result = source.replace("world", options.name);
this.callback(null, result);
};
//this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any
);
const loaderUtils = require("loader-utils");
module.exports = function(source) {
const options = loaderUtils.getOptions(this);
setTimeout(() => {
const result = source.replace("world", options.name);
return result;
}, 1000);
};
//先?setTimeout处理下试试,发现会报错
我们使?用this.async来处理理,他会返回this.callback
const loaderUtils = require("loader-utils");
module.exports = function(source) {
const options = loaderUtils.getOptions(this);
//定义一个异步处理,告诉webpack,这个loader?有异步事件,在里?调?下这个异步
//callback 就是 this.callback 注意参数的使?
const callback = this.async();
setTimeout(() => {
const result = source.replace("world", options.name);
callback(null, result);
}, 3000);
};
//replaceLoader.js
module.exports = function(source) {
return source.replace("软谋课堂", "word");
};
//replaceLoaderAsync.js
const loaderUtils = require("loader-utils");
module.exports = function(source) {
const options = loaderUtils.getOptions(this);
//定义?一个异步处理理,告诉webpack,这个loader?里里有异步事件,在?里里?面调?用下这个异步
const callback = this.async();
setTimeout(() => {
const result = source.replace("world", options.name);
callback(null, result);
}, 3000); };
//webpack.config.js
module: {
rules: [
{
test: /\.js$/,
use: [
path.resolve(__dirname, "./loader/replaceLoader.js"),
{
loader: path.resolve(__dirname, "./loader/replaceLoaderAsync.js"),
options: {
name: "你好吗"
}
}
]
// use: [path.resolve(__dirname, "./loader/replaceLoader.js")]
}
]
}
顺序,自下?上,自右到左
resolveLoader: {
modules: ["node_modules", "./loader"]
},
module: {
rules: [
{
test: /\.js$/,
use: [
"replaceLoader",
{
loader: "replaceLoaderAsync",
options: {
name: "软谋课堂"
}
}
]
}
]
},
..............
参考:loader API
https://webpack.js.org/api/loaders
Plugin: 开始打包,在某个时刻,帮助我们处理一些什么事情的机制 plugin要比loader稍微复杂一些,在webpack的源码中,用plugin的机制还是占有非常大的场景,可以说plugin是webpack的灵魂
l 设计模式
l 事件驱动
l 发布订阅
plugin是一个类,?面包含一个apply函数,接受一个参数,compiler
案例:
class CopyrightWebpackPlugin {
constructor() { }
// 将 `apply` 定义为其原型方法,此方法以 compiler 作为参数
apply(compiler) { }
}
module.exports = CopyrightWebpackPlugin;
const CopyrightWebpackPlugin = require("./plugin/copyright-webpack-plugin");
plugins: [new CopyrightWebpackPlugin()]
//webpack配置?文件
plugins: [
new CopyrightWebpackPlugin({
name: "你好吗"
})
]
//copyright-webpack-plugin.js
class CopyrightWebpackPlugin {
constructor(options) {
//接受参数
console.log(options);
}
apply(compiler) { }
}
module.exports = CopyrightWebpackPlugin;
class CopyrightWebpackPlugin {
constructor(options) {
// console.log(options);
}
apply(compiler) {
//hooks.emit 定义在某个时刻 ,
// 指定要附加到的事件钩子函数
compiler.hooks.emit.tapAsync(
"CopyrightWebpackPlugin",
(compilation, cb) => {
// 使用 webpack 提供的 plugin API 操作构建结果
compilation.assets["copyright.txt"] = {
source: function() {
return "hello copy";
},
size: function() {
return 20;
}
};
cb();
} );
//同步的写法
//compiler.hooks.compile.tap("CopyrightWebpackPlugin", compilation => {
// console.log("开始了了");
//});
}
}
module.exports = CopyrightWebpackPlugin;
参考:compiler-hooks
https://webpack.js.org/api/compiler-hooks
由上面的步骤可知,插件功能的实现主要依赖于compiler和complation对象,而两者都是继承自Tapable对象。它暴露三种注册监听的方法Tapable对象主要是9种钩子:
const {
SyncHook,
SyncBailHook,
SyncWaterfallHook,
SyncLoopHook,
AsyncParallelHook,
AsyncParallelBailHook,
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncSeriesWaterfallHook
} = require("tapable");
其中同步四种,异步并行两种,异步串行3种。
同步钩子进行同步操作;异步钩子中进行异步操作。
compiler和compilation中的钩子都是来自这9种钩子。钩子的工作机制类似于浏览器的事件监听。
1)生成的钩子可以注册监听事件,其中同步钩子通过tap方法监听,异步钩子通过tapAsync(+回调函数)和tapPromise(+返回promise)进行监听。
2)还可以进行拦截,通过intercept方法。
3)对于监听事件的触发,同步钩子通过call方法; 异步钩子通过callAsync方法和promise
标签:tps erro timeout 依赖 test style 配置 top 包含
原文地址:https://www.cnblogs.com/laneyfu/p/12269965.html