code:https://github.com/ronami/minipackjavascript
看了https://www.youtube.com/watch?v=Gc9-7PBqOC8總結一下java
工具和環境:node
node環境;git
依賴模塊:github
fs:文件讀取babel
path:文件路徑處理app
babylon:ast樹的轉換(https://astexplorer.net/)函數
babel-traverse:遍歷ast數,查找全部依賴關係工具
babel-core:用transformFromAst方法把ast數轉換爲js代碼(此處的代碼爲babel解析事後的代碼:https://babeljs.io/repl/,commonJs標準)ui
整體流程是爲:根據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'; }, {}, ],})
解析後大概流程以下:
一、自執行函數(fun(...){})(params)
二、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); }
三、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
固然,真正的打包還須要不少工做,如循環依賴、異常捕獲及提示等等。此爲冰山一角