During this time, I was thinking about writing a build tool by myself, but before that, let's try to sort out the concept of webpack. After all, it can be used as a stone of the mountain, which will help us figure out how to design our own projects.

Introduction

Webpack is a static module bundler for modern JavaScript applications.
This is an introduction to webpack, which is essentially a bundler. Package js modules into one or more. Implement the capabilities in the following code:
 a.js + b.js + c.js. => bundle.js

The reason for the appearance of the packager will not be discussed here. There are many articles on the Internet. Next, let's talk about the core idea of webpack packaging multiple js files into one bundle file.

Reverse the core process from the build product

Webpack is a huge system. If you analyze the process from start to finish from the perspective of source code, it will be too complicated and unnecessary. After all, we are mainly learning core design concepts.
Then, we can try to reverse the process from the results, analyze the packaged code, and the idea of webpack.
Under the configuration of mode: 'none', devtool: 'cheap-source-map', we can see that the packaged code looks like this:

 (function webpackUniversalModuleDefinition(root, factory) {
  if(typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
  else if(typeof define === 'function' && define.amd)
    define([], factory);
  else if(typeof exports === 'object')
    exports["Magotan"] = factory();
  else
    root["Magotan"] = factory();
})(window, function(){
    return (function(modules){
        // xxxx    
    })([
        //xxxx
    ])['default']
})

It is obvious that this is an IIFE. Simplify it, and add the specific implementation code, it becomes the following:

 (function webpackUniversalModuleDefinition() {
  exports["Magotan"] = (function (modules) {
    function __webpack_require__(moduleId) {
      if (installedModules[moduleId]) {
        return installedModules[moduleId].exports;
      }
      var module = installedModules[moduleId] = {
        i: moduleId,
        l: false,
        exports: {}
      };
      modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
      module.l = true;
      return module.exports;
    }
    return __webpack_require__(0);
  })([ 
    /* 0 */ //模块数组列表 数组下标即为模块id 
    (function (module, __webpack_exports__, __webpack_require__) {
      __webpack_exports__["default"] = ({
        getInstance: function getInstance() {
          if (magotan === null) {
            throw new Error('未初始化实例,请先通过config初始化');
          }
          return magotan;
        },
    }),
    /* 1 */
    (function (module, exports, __webpack_require__) {
      var toObject = __webpack_require__(2);
      var $keys = __webpack_require__(4);
      __webpack_require__(21)('keys', function () {
        return function keys(it) {
          return $keys(toObject(it));
        };
      });
    }),
  // ...
});
  ])['default'];
})()

From the above code, we can see that we store the code and dependencies of all modules used in the project in an array of modules, and then through the require method customized by webpack, from the entry file, that is, the module with id = 0 is The starting point, recursively execute the module.

So far we can analyze that the core process of webpack is two steps

  1. The reslove modules stage recursively parses and produces Dependency graphs
  2. The Bundle stage assembles the product of the previous stage into an array and wraps it with a function, and executes it recursively from the entry file

    follow-up

    After clarifying the design ideas of webpack, there are more specific implementation issues, such as how to get the relationship between modules (using AST), how to ensure that there is no circular reference (using the installedModules object), etc., and more The content will be introduced in subsequent documents.


notself
134 声望13 粉丝