webpack - minipack 打包原理

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

  

固然,真正的打包還須要不少工做,如循環依賴、異常捕獲及提示等等。此爲冰山一角

相關文章
相關標籤/搜索