webpack的使用離不開loader,搞清楚loader的基本運行原理能有效的讓咱們搞清楚webpack的總體工做流程。css
Loader 是支持鏈式執行的,如處理 sass 文件的 loader,能夠由 sass-loader、css-loader、style-loader 組成,由 compiler 對其由右向左執行,第一個 Loader 將會拿到需處理的原內容,上一個 Loader 處理後的結果回傳給下一個接着處理,最後的 Loader 將處理後的結果以 String 或 Buffer 的形式返回給 compiler。 這種鏈式的處理方式卻是和 gulp 有點兒相似,當然也是但願每一個 loader 只作該作的事,純粹的事,而不但願一籮筐的功能都集成到一個 Loader 中。node
{ module: { loaders: [{ test: /\.scss$/, loader: 'style!css!sass' }] } };
若是你所寫的 Loader 須要依賴其餘模塊的話,那麼一樣以 module 的寫法,將依賴放在文件的頂部聲明,讓人清晰看到webpack
// Module dependencies. var fs = require("fs"); module.exports = function(source) { return source; };
上面使用返回 return 返回,是由於是同步類的 Loader 且返回的內容惟一,若是你但願將處理後的結果(不止一個)返回給下一個 Loader,那麼就須要調用 Webpack 所提供的 API。 通常來講,構建系統都會提供一些特有的 API 供開發者使用。Webpack 也如此,提供了一套 Loader API,能夠經過在 node module 中使用 this 來調用,如 this.callback(err, value...),這個 API 支持返回多個內容的結果給下一個 Loader 。web
// return multiple result module.exports = function(source, other) { // do whatever you want // ... this.callback(null, source, other); };
總結:gulp
而實際上,掌握上面所介紹的內容及思想,就能夠開始寫一個簡單的 Loader 了,不是嗎? 由上所說的,在你的 Loader 中,你能夠拿到須要處理的文件內容,而且知道了處理後的結果應該怎麼去返回,在中間部分,你能夠以正常使用 node 的姿態對內容進行怎樣的處理,Do Whatever You Want,Loader 沒有其餘特殊要求。緩存
上半部分的介紹雖然確實能搭建起一個普通的 Loader 了,但這樣就夠了嗎?sass
從提升執行效率上,如何處理利用緩存是極其重要的。 Mac OS 會讓內存充分使用、儘可能佔滿來提升交互效率。回到 Webpack,Hot-Replace 以及 React Hot Loader 也充分地利用緩存來提升編譯效率。 Webpack Loader 一樣能夠利用緩存來提升效率,而且只需在一個可緩存的 Loader 上加一句 this.cacheable(); 就是這麼簡單異步
// 讓 Loader 緩存 module.exports = function(source) { this.cacheable(); return source; };
不少 Loader 都是能夠緩存的,但也有例外。能夠緩存的 Loader 須要具有可預見性,不變性等等async
異步並不陌生,當一個 Loader 無依賴,可異步的時候我想都應該讓它再也不阻塞地去異步。在一個異步的模塊中,回傳時須要調用 Loader API 提供的回調方法 this.async(),使用起來也很簡單工具
// 讓 Loader 緩存 module.exports = function(source) { var callback = this.async(); // 作異步的事 doSomeAsyncOperation(content, function(err, result) { if(err) return callback(err); callback(null, result); }); };
pitching Loader
前面所述的 Loader 從右到左鏈式執行。這種說法實際說的是 Loader 中 module.exports 出來的執行方法順序。在一些場景下,Loader 並不依賴上一個 Loader 的結果,而只關心原輸入內容。這時候,從左到右執行並無什麼問題。在 Loader 的 module 中,可以使用 module.exports.pitch = function(); pitch 方法在 Loader 中即是從左到右執行的,而且能夠經過 data 這個變量來進行 pitch 和 normal 之間傳遞。
module.exports.pitch = function(remaining, preceding, data) { if(somothingFlag()) { return "module.exports = require(" + JSON.stringify("-!" + remaining) + ");"; } data.value = 1; };
具體的實踐能夠查看 style-loader,裏面就有使用到 pitch。
raw loader
默認的狀況,原文件是以 UTF-8 String 的形式傳入給 Loader,而在上面有提到的,module 可以使用 buffer 的形式進行處理,針對這種狀況,只須要設置 module.exports.raw = true; 這樣內容將會以 raw Buffer 的形式傳入到 loader 中了
module.exports = function(content) { }; module.exports.raw = true;
Loader API 將提供給每個 Loader 的 this 中,API 可讓咱們的調用方式更加地方便,更加靈活。 data pitch loader 中能夠經過 data 讓 pitch 和 normal module 進行數據共享。 query 則能獲取到 Loader 上附有的參數。 如 require("./somg-loader?ls"); 經過 query 就能夠獲得 "ls" 了。 emitFile emitFile 可以讓開發者更方便的輸出一個 file 文件,這是 webpack 特有的方法,使用的方法也很直接
emitFile(name: string, content: Buffer|String, sourceMap: {...})
在 file-loader 中有調用到 this.emitFile(url, content); 這個方法,具體能夠查看其源碼瞭解。 更多的 API 就不在此 一 一 說明了,建議查看官網文檔瞭解。最後推薦一個工具模塊 loader-utils,大多數的 Loader 都會用上它來解析或者使用它提供的一些 util 方法,很方便。
針對 Loader 的基礎介紹大體就到這了,很少,但願這篇文章可以對 Webpack Loader 有一個大體的瞭解。 更多進階的方案及實戰經驗容我再整理整理,遲些輸出。