webpack - minipack 打包原理
code:https://github.com/ronami/minipack
看了https://www.youtube.com/watch?v=Gc9-7PBqOC8總結一下
工具和環境:
node環境;
依賴模塊:
fs:文件讀取
path:文件路徑處理
babylon:ast樹的轉換(https://astexplorer.net/)
babel-traverse:遍歷ast數,查找所有依賴關系
babel-core:用transformFromAst方法把ast數轉換為js代碼(此處的代碼為babel解析過后的代碼:https://babeljs.io/repl/,commonJs標準)
總體流程是為:根據entry路口文件,用babylon轉換為ast樹,從中查找所有的依賴管理,然后遍歷依賴關系圖,再把所有依賴的代碼整合輸出。
最后整合輸出的代碼如下:
(function(modules) { function require(id) { const [fn, mapping] = modules[id]; function localRequire(name) { return require(mapping[name]); } const module = { exports : {} }; fn(localRequire, module, module.exports); return module.exports; } require(0); })({0: [ function (require, module, exports) { "use strict"; var _message = require("./message.js"); var _message2 = _interopRequireDefault(_message); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } console.log(_message2.default); }, {"./message.js":1}, ],1: [ function (require, module, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _name = require("./name.js"); exports.default = "hello " + _name.name + "!"; }, {"./name.js":2}, ],2: [ function (require, module, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var name = exports.name = 'world'; }, {}, ],})
解析后大概流程如下:
1、自執行函數(fun(...){})(params)
2、fun代碼
function fun1(modules) {// 接收modules對象 function require(id) { const [fn, mapping] = modules[id];// 獲取對應模塊的 fn和依賴mapping function localRequire(name) { // 遞歸,請求所有依賴 return require(mapping[name]); } const module = { exports : {} }; fn(localRequire, module, module.exports);//執行函數,因為require傳入后,在fun方法體中會執行require方法請求依賴,故會先執行最底層的依賴。 return module.exports; } require(0); }
3、params
{0: [
function (require, module, exports) {
"use strict";
var _message = require("./message.js");
var _message2 = _interopRequireDefault(_message);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
console.log(_message2.default);
},
{"./message.js":1},
],1: [
function (require, module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _name = require("./name.js");
exports.default = "hello " + _name.name + "!";
},
{"./name.js":2},
],2: [
function (require, module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var name = exports.name = 'world';
},
{},
],}
// key為模塊的id,對應的value = [fun,mapping];
// fun為一個函數,接收require,modle,exports,fun里的內容是經過babel-core轉換過的js代碼
// mapping為依賴模塊的id
當然,真正的打包還需要很多工作,如循環依賴、異常捕獲及提示等等。此為冰山一角
浙公網安備 33010602011771號