file => FileExistsPluginjson
這個事件流快接近尾聲了,接下來是FileExistsPlugin,很奇怪的是在最後纔來檢驗路徑文件是否存在。app
源碼以下:async
FileExistsPlugin.prototype.apply = function(resolver) { var target = this.target; resolver.plugin(this.source, function(request, callback) { var fs = this.fileSystem; // file => d:\workspace\doc\input.js var file = request.path; fs.stat(file, function(err, stat) { // stat => 文件信息 if (err || !stat) { if (callback.missing) callback.missing.push(file); if (callback.log) callback.log(file + " doesn't exist"); return callback(); } // 是否爲文件 if (!stat.isFile()) { if (callback.missing) callback.missing.push(file); if (callback.log) callback.log(file + " is not a file"); return callback(); } // 只作信息提示 不對結果作處理 this.doResolve(target, request, "existing file: " + file, callback, true); }.bind(this)); }); };
這裏只是簡單的對路徑文件進行狀態獲取,而後判斷是否存在?是不是文件?最後調用一個有message的doResolve方法進入到下一個事件流。函數
existing-file => NextPlugin測試
這個插件沒什麼卵用,以前提到過,會直接跳到下一個事件流。this
resolved => ResultPluginspa
這是最後一個插件,在注入的時候只有一個參數,表明事件流的結尾。prototype
ResultPlugin.prototype.apply = function(resolver) { resolver.plugin(this.source, function(request, callback) { var obj = Object.assign({}, request); // 調用resolver的事件流 resolver.applyPluginsAsyncSeries1("result", obj, function(err) { if (err) return callback(err); callback(null, obj); }); }); };
這裏直接調用了resolver的result事件流,並無經過doResolve方法。插件
通過測試,這個事件流並不存在,因此會直接調用無參callback,這個callback是什麼呢???code
找了好久好久,終於找到了,回到最開始的resolve方法中,有個函數:
function onResolve(err, result) { // 無錯誤狀況下調用這個 if (!err && result) { return callback(null, result.path === false ? false : result.path + (result.query || ""), result); } localMissing = []; log = []; // 錯誤處理 return resolver.doResolve("resolve", obj, message, createInnerCallback(onError, { log: writeLog, missing: localMissing, stack: callback.stack })); }
這裏由於成功執行完事件流,第一個參數爲null,因此會進入第一個if分支,最後返回的是path與result。
這個callback就簡單了,回到了resolve方法的調用地點:
asyncLib.parallel([ callback => this.resolveRequestArray(contextInfo, context, elements, this.resolvers.loader, callback), callback => { if (resource === "" || resource[0] === "?") return callback(null, { resource }); this.resolvers.normal.resolve(contextInfo, context, resource, (err, resource, resourceResolveData) => { // 從這裏開始 if (err) return callback(err); /* resource => d:\workspace\doc\input.js resourceResolveData => { context: { issuer: '', compiler: undefined }, path: 'd:\\workspace\\doc\\input.js', request: undefined, query: '', module: false, file: false, descriptionFilePath: 'd:\\workspace\\doc\\package.json', descriptionFileData:{ *配置文件內容* }, descriptionFileRoot: 'd:\\workspace\\doc', relativePath: './input.js', __innerRequest_request: undefined, __innerRequest_relativePath: './input.js', __innerRequest: './input.js' } */ callback(null, { resourceResolveData, resource }); }); } ], (err, results) => { /**/ })
總結
這裏對以前的resolve方法所作的流程作一個總結,畫一個圖。
剔除一些諸如NextPlugin這種垃圾插件以及重複加載的插件,插件加載按順序,全部的type的before、after均視爲一個事件流,特殊分支給給出說明。