媒介
在webpack特徵內里,它能夠支撐將非javaScript文件打包,但前面寫到webpack的模塊化打包只能應用於含有特定範例的JavaScript文件。本次引見的loader則是用來處理這類題目的。本文章loader的完成基於code-splitting
功能剖析
舉個例子:
webpack.config.js中的設置loader
module: {
rules: [
{
test: /\.js$/,
loader: "test-loader!test-loader2"
}
]
}
營業代碼中的內聯loader
require('d!c');
剖析:
我們須要將這些loader剖析成可運轉的函數,並在parse模塊剖析語法樹之前運轉掉這些loader函數
所以我們須要:
- resolve模塊:剖析出module對應的loader字符串,並剖析出各個loader的絕對途徑
- buildDeps模塊:經由過程文件途徑獵取須要運轉的loader函數,將其壓入行列,以後再順次順次遞歸出loader函數運轉,如果是異步loader,則要經由過程回調函數來遞歸下一個loader函數。
完成
resolve 模塊
完成思緒:
- 將設置內的loaders,shell敕令的loaders,require/import的內聯loader夙昔至后構成一個數組。設置內的loaders須要正則婚配test屬性,來獵取設置內的loader字符串。一切loader字符串內部又能夠截取’!’,獵取完全的loader。
- 剖析並剖析該數組內的字符串,獵取各個loader的絕對途徑。並返回剖析好的字符串。這塊的完成和文件打包相似。
終究require內的字符串以下
/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/node_modules/d.js!
/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/node_modules/test-loader/index.js!
/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/node_modules/test-loader2/index.js!
/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/node_modules/c.js
buildDeps模塊
完成思緒:
- 剖析文件途徑,並獵取須要運轉的loader函數,存入數組
- 數組在經由過程pop函數一個個遞歸,考慮到存在異步loader函數的狀況,須要為運轉函數供應async,以及callback的上下文。詳細的上下文可參考Loader API
loader遞歸邏輯以下:
nextLoader.apply(null, content);
function nextLoader() {
const args = Array.prototype.slice.apply(arguments);
if (loaderFunctions.length > 0) {
const loaderFunction = loaderFunctions.pop();
let async = false;
const context = {
fileName,
options,
debug: options.debug,
async: function () {
async = true;
return nextLoader;
},
callback: function () {
async = true;
nextLoader.apply(null, arguments)
}
};
const resVal = loaderFunction.apply(context, args);
if (!async) {
nextLoader(resVal);
}
} else {
callback(null, args[0])
}
}
測試
將以上3個loader,test-loader,test-loader2,異步loader d.js,打包c.js
test-loader
module.exports = function(content) {
return content+"\nexports.answer = 42;\n"
}
test-loader2
module.exports = function(content) {
return content+"\nexports.test2 = test2;\n"
}
異步loader d.js
module.exports = function (content) {
const d = 'd';
this.async();
const b = content + "\nexports.d = 2000;\n";
setTimeout(this.callback.bind(this, b), 2000);
}
c.js
const c = 'c';
module.exports = c;
終究打包出來的c.js的代碼以下
....
/* 1 */
/***/(function(module, exports,__webpack_require__) {
const c = 'c';
module.exports = c;
exports.test2 = test2;
exports.answer = 42;
exports.d = 2000;
/***/}
....
代碼完成
本人的簡易版webpack完成simple-webpack
(完)