太上老俊

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

  

当然,真正的打包还需要很多工作,如循环依赖、异常捕获及提示等等。此为冰山一角

 

posted on 2019-04-10 16:59  太上老俊  阅读(721)  评论(0编辑  收藏  举报

导航