2017-07-26 101 views
3

每天的WebPack决心插件遵循以下结构:Webpack插件 - 何时调用doResolve和何时回调?

resolver.plugin(this.source, function(request, callback) { 
    if (something) { 
     resolver.doResolve(target, obj, "aliased with mapping '" + name + "': '" + ...) 
    } else { 
     callback(...); 
    } 

任何人都可以请解释当我应该叫doResolve,当回调。我发现这句话在的WebPack文档:

将请求传递给其他解决插件,使用 this.doResolve(类型:字符串|字符串[],请求:请求,回调) 方法

但是,我不知道该怎么做。看起来doResolve从一开始就开始这个过程。下面是堆栈看起来像在doResolve

enter image description here

你可以看到,从阶段开始启动。为什么?

回答

2

Webpack使用applyPluginsAsyncSeriesBailResult1方法运行解析器的所有插件。这个方法运行连续的所有插件 - 下一个插件仅在当前插件执行完成后才运行。 这里的bail表示一旦一个插件返回错误,该序列就会中断。这种方法也被称为“快速失败”。但是BailResult意味着只要一个插件返回结果,序列也会中断。您可以从来源看出来:

applyPluginsAsyncSeriesBailResult1 = function applyPluginsAsyncSeriesBailResult1(name, param, callback) { 
    var plugins = this._plugins[name]; 
    if(!plugins || plugins.length === 0) return callback(); 
    var i = 0; 
    var _this = this; 
    var innerCallback = function next(err, result) { 
     // if the plugin returned an error or a result - break 
     if(arguments.length > 0) return callback(err, result); 
     i++; 
     // if all plugins have run - break 
     if(i >= plugins.length) { 
      return callback(); 
     } 
     // trigger next plugin - continue 
     plugins[i].call(_this, param, innerCallback); 
    }); 
    plugins[0].call(this, param, innerCallback); 
}; 

所以从这个代码,您可以尽快看到您拨打callback插件里面有参数,你中断序列。第一个参数是错误,第二个参数是结果。这符合Node.js期望的回调签名。如果您拨打不带参数的callback,则序列为继续

现在,您还可以拨打doResolve,这将再次运行整个插件序列。这通常是在对请求进行一些更改时完成的,因此您希望再次给所有其他插件以对新请求做出反应。由于当前的插件将在下一个doResolve轮次中再次调用,因此请确保构建它以防止递归。的WebPack后卫再次递归,但只有当pathrequestquerydirectorymodule比赛作为可以从源头上可以看出:

Resolver.prototype.doResolve = function doResolve(type, request, message, callback) { 
    var resolver = this; 
    var stackLine = type + ": (" + request.path + ") " + 
     (request.request || "") + (request.query || "") + 
     (request.directory ? " directory" : "") + 
     (request.module ? " module" : ""); 
    var newStack = [stackLine]; 
    if(callback.stack) { 
     newStack = callback.stack.concat(newStack); 
     if(callback.stack.indexOf(stackLine) >= 0) { 
      // Prevent recursion 
      var recursionError = new Error("Recursion in resolving\nStack:\n " + newStack.join("\n ")); 

而且回调到doResolve你平时打电话callback()从本轮插件打破内因为他们有机会对更新的请求做出反应:

resolver.plugin(this.source, function(request, callback) { 
    if (something) { 
     resolver.doResolve(target, obj, 
       "aliased with mapping '" + name + "': '" + ..., 
       function() { callback(error, result) } 
     )