读 minipack 源码

Issues

解读 minipack 源码

整体流程

  1. 同步读取入口文件,然后通过 babylon 解析js文件,再通过 babel-traverse 来操作js的语法树,再交给 babel-core 转码成现在浏览器可以跑起来的代码,
  1. 其中通过一个数组来保存已经构建好父文件和子文件的依赖关系,

``js [ './message.js' ] [ './name.js' ] [] ``

  1. 然后不断去遍历这个存有依赖关系的数组,得出另外一个数组,这个数组包含文件的索引id,文件名,它的依赖文件,还有通过 `babel-core ` 转码出来的代码。

```js queue: [ { id: 0, filename: './example/entry.js', dependencies: [ './message.js' ], code: '"use strict";\n\nvar _message = require("./message.js");\n\nvar _message2 = _interopRequireDefault(_message);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nconsole.log(_message2.default);', mapping: { './message.js': 1 } }, { id: 1, filename: 'example/message.js', dependencies: [ './name.js' ], code: '"use strict";\n\nObject.defineProperty(exports, "__esModule", {\n value: true\n});\n\nvar _name = require("./name.js");\n\nexports.default = "hello " + _name.name + "!";', mapping: { './name.js': 2 } }, { id: 2, filename: 'example/name.js', dependencies: [], code: '"use strict";\n\nObject.defineProperty(exports, "__esModule", {\n value: true\n});\nvar name = exports.name = \'world\';', mapping: {} } ]

```

  1. 最关键的是,通过遍历生成的 queue 数组 ,把 其中的 code 属性值 放进 CommomJs 模块规范的代码打包函数里。

``js function (require, module, exports) { // 写的代码,即上面的 queue 数组对象中的不同对象的code属性的值 }) ``

  1. 最后一步就是,让浏览器读取到第4步打包好的代码,这里没有引入其他插件,是通过内部的代码块实现的。

例子是下面的:

```js (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(){console.log('hhhhh')}]}) ```

真实的代码如下:

```js (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'; }, {}, ],}) ```

总结来说

通过babel解析代码成ES5代码,通过构建文件依赖关系,使用 commomJs 模块化打包文件,使用浏览器能理解的代码实现引入打包文件。

---

原始 Issue:heycqing/blog#7