webpack打包原理

webpack是一个打包模块的机制,只是把依赖的模块转化成可以代表这些包的静态文件。并不是什么commonjs或者amd之类的模块化规范。webpack就是识别你的 入口文件,识别你的模块依赖,来打包你的代码。至于你的代码使用的是commonjs还是amd或者es6的import,webpack都会对其进行分析,来获取代码的依赖。webpack做的就是分析代码、转换代码、编译代码、输出代码。webpack本身是一个node的模块,所以webpack.config.js是以commonjs形式书写的(node中的模块化是commonjs规范的)

webpack中每个模块有一个唯一的id,是从0开始递增的。整个打包后的bundle.js是一个匿名函数自执行。参数则为一个数组。数组的每一项都为个function。function的内容则为每个模块的内容,并按照require的顺序排列。

// webpack.config.js
module.exports = {
  entry:'./a.js',
  output:{
    filename:'bundle.js'
  }
};
复制代码
// a.js
var b = require('./b.js');

console.log('a');

b.b1();
复制代码
// b.js
exports.b1 = function () {
  console.log('b1')
};

exports.b2 = function () {
  console.log('b2')
};
复制代码
// bundle.js
(function(modules) { // webpackBootstrap
   // The module cache
   var installedModules = {};

   // The require function
  function __webpack_require__(moduleId) {
       // Check if module is in cache
       if(installedModules[moduleId])
           return installedModules[moduleId].exports;
       // Create a new module (and put it into the cache)
       var module = installedModules[moduleId] = {
          exports: {},
          id: moduleId,
          loaded: false
       };

     // Execute the module function
      modules[moduleId].call(module.exports, module, module.exports,__webpack_require__);

      // Flag the module as loaded
     module.loaded = true;

      // Return the exports of the module
      return module.exports;
   }


  // expose the modules object (__webpack_modules__)
   __webpack_require__.m = modules;

   // expose the module cache
  __webpack_require__.c = installedModules;

  // __webpack_public_path__
   __webpack_require__.p = "";
   // Load entry module and return exports
  return __webpack_require__(0);
 })
 
([
/* 0 */
 function(module, exports, __webpack_require__) {
    var b = __webpack_require__(1);
    console.log('a');
    b.b1();
},

/* 1 */
 function(module, exports) {

    exports.b1 = function () {
      console.log('b1')
    };

    exports.b2 = function () {
      console.log('b2')
    };

 }
]);
复制代码

我们看到_webpack_require是模块加载函数,接收模块id(webpack中每个模块都会有一个独一无二的id,其实也就是在IIFE传参数组中的索引值(0,1,2…..)
a依赖b,所以在a中调用webpack加载模块的函数

webpack为什么能把任何形式的资源都视作模块呢?因为loader机制。不同的资源采用不同的loader进行转换。CMD、AMD 、import、css 、等都有相应的loader去进行转换。那为什么我们平时写的es6的模块机制,不用增加import的loader呢。因为我们使用了babel把import转换成了require。并且Webpack 2 将增加对 ES6 模块的原生支持并且混用 ES6、AMD 和 CommonJS 模块。这意味着 Webpack 现在可以识别 import 和 export 了,不需要先把它们转换成 CommonJS 模块的格式:Webpack 2 有哪些新东西webpack对于es模块的实现,也是基于自己实现的webpack_requirewebpack_exports ,装换成类似于commonjs的形式。es6 module是静态的依赖,所以在运行前进行代码转换,这里的实现是将所有导出项作为一个对象的属性,在入口文件执行时,去递归的加载模块。

webpack2是如何对实现es6 modules的
webpack模块化原理-ES module

如何实现一个简单的webpack

  1. 读取文件分析模块依赖
  2. 对模块进行解析执行(深度遍历)
  3. 针对不同的模块使用相应的loader
  4. 编译模块,生成抽象语法树AST。
  5. 循环遍历AST树,拼接输出js。
    webpack 源码解析
    细说 webpack 之流程篇
    如何实现一个简单的webpack

loader原理

在解析对于文件,会自动去调用响应的loaderloader 本质上是一个函数,输入参数是一个字符串,输出参数也是一个字符串。当然,输出的参数会被当成是 JS 代码,从而被 esprima 解析成 AST,触发进一步的依赖解析。 webpack会按照从右到左的顺序执行loader。
Webpack——令人困惑的地方

cli.vuejs.org/zh/config/#…
blog.csdn.net/u014440483/…

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享