2017-07-26 64 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) } 
     )