模块依赖加载解析
// webpack.config.js配置const path = require('path')module.exports = {  devtool: 'none',		// 不生成映射url,也就是不生成source-map文件
  mode: 'development',	// development | production
  entry: './src/index.js',  output: {path: path.resolve(__dirname, 'dist'),  // 在当前目录下添加dist目录,并且将输出的内容放在filename指定的文件中filename: 'bundle.[hash:8].js'          // bundle.[hash:8].js防止有缓存,所以每次生成不一样的bundle.js就是加hash,后面的 ':8'表示hash的位数
  },  // 这里还配置了一些解析css的loader,省略了
 }复制代码
// index.jsrequire('./index.css')let aa = require('./a.js')console.log(aa);console.log('hello webpack');let fn = () => {  console.log('我是fn');
}
fn()// a.jsfunction testshow () {  console.log('哈哈哈哈哈哈');
}module.exports = testshow复制代码
/* index.css */@import './a.css';body {  background-color: pink;  transform: rotate(45deg);  background: url('./w3.png');
}/* a.css */body{  background-color: red;
}复制代码
// bundle.js(function (modules) {  // 缓存模块对象,如果已经被缓存过了,就不需要再重新加载,直接从这个对象中获取模块文件moduleId对应的exports导出对象
  var installedModules = {};  // webpack实现的require导入函数,这个函数用于递归导入依赖模块
  function __webpack_require__ (moduleId) {if (installedModules[moduleId]) {      return installedModules[moduleId].exports;
    }var module = installedModules[moduleId] = {      i: moduleId,	// moduleId是模块文件名,第一次传入模块文件就是./src/index.js  l: false,		// 标记这个模块文件是否被加载过  exports: {}	// moduleId对应的模块文件的导出的对象保存在这里};//  第一次的modules[moduleId]相当于modules[./src/index.js],获取到的是传入./src/index.js模块对应的函数// modules[moduleId].call() ,直接加载了moduleId模块文件对应的函数代码,并把函数内部的this指向改为module.exports,还把递归函数__webpack_require__传入。这样相当于执行了./src/index.js模块对象的函数,在函数中又有其他模块的导入,则可以使用__webpack_require__再进行递归加载modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);    // 标记moduleId这个模块已经被加载过了module.l = true;    // 最终把导出返回,每个模块最终在这里把自己的模块导出对象exports返回到上一层调用处return module.exports;
  }  // m属性向外暴露传入的模块参数对象
  __webpack_require__.m = modules;  // c属性向外暴露缓存对象
  __webpack_require__.c = installedModules;  // d方法兼容各种导出模式,重写getter方法
  __webpack_require__.d = function (exports, name, getter) {if (!__webpack_require__.o(exports, name)) {      Object.defineProperty(exports, name, { enumerable: true, get: getter });
    }
  };  // r方法用于是import导入方式时,则会给模块导出对象exports增加`__esModule`属性标记
  __webpack_require__.r = function (exports) {if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
    }Object.defineProperty(exports, '__esModule', { value: true });
  };  // t方法 todo暂时没看明白
  __webpack_require__.t = function (value, mode) {if (mode & 1) value = __webpack_require__(value);if (mode & 8) return value;if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;var ns = Object.create(null);
    __webpack_require__.r(ns);Object.defineProperty(ns, 'default', { enumerable: true, value: value });if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key));return ns;
  };  // 获取模块默认导出对象,是ES的导出方式,则使用default为默认导出对象,否则按照commonJS的默认导出module
  // 主要用于这种场景,导入导出不一致。如果在一个模块文件中,使用import导入了某模块,但是导入的这个模块又是以commonJS的方式导出的
  // 导入判断是否ES Module,采用r方法判断;导出是否使用ES Module采用n函数判断
  __webpack_require__.n = function (module) {var getter = module && module.__esModule ?      function getDefault () { return module['default']; } :      function getModuleExports () { return module; };
    __webpack_require__.d(getter, 'a', getter);return getter;
  };  // o方法用于判断property属性是否是object对象自己的属性
  __webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); };  // p属性存放公共访问路径
  __webpack_require__.p = "";  //__webpack_require__方法在这里调用,并且传入了配置的入口模块"./src/index.js"
  return __webpack_require__(__webpack_require__.s = "./src/index.js");		
})
  ({"./src/a.js":
      (function (module, exports) {function testshow () {          console.log('哈哈哈哈哈哈');
        }module.exports = testshow;
      }),"./src/index.css":
      (function (module, __webpack_exports__, __webpack_require__) {        "use strict";// 由于index.css的源代码中使用ES Module导入的a.css,所以这里调r方法__webpack_require__.r(__webpack_exports__);
      }),"./src/index.js":
      (function (module, exports, __webpack_require__) {// __webpack_require__递归导入index.css,和a.js,就跟导入index.js一样__webpack_require__("./src/index.css");//  __webpack_require__("./src/a.js")返回的是a.js的导出export,然后赋值给aavar aa = __webpack_require__("./src/a.js");console.log(aa);console.log('hello webpack');var fn = function fn () {          console.log('我是fn');
        };
        fn();
      })
  });复制代码

基于webpack4.x模块依赖加载流程_webpack4.x



commonJS和ES Module的导入导出有区别
// index.js// require('./index.css')// let aa = require('./a.js')import a from './a.js';import './index.css'let aa = aconsole.log(aa);console.log('hello webpack');let fn = () => {  console.log('我是fn');
}
fn()// a.jsfunction testshow () {  console.log('哈哈哈哈哈哈');
}module.exports = testshow复制代码
// bundle.js 只截取了参数对象这部分
  ({"./src/a.js":
      (function (module, exports) {function testshow () {          console.log('哈哈哈哈哈哈');
        }module.exports = testshow;
      }),"./src/index.css":
      (function (module, __webpack_exports__, __webpack_require__) {        "use strict";
        __webpack_require__.r(__webpack_exports__);
      }),"./src/index.js":
      (function (module, __webpack_exports__, __webpack_require__) {        "use strict";// r方法标识了index.js是个ESModule__webpack_require__.r(__webpack_exports__);var _a_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/a.js");// 因为a模块是import导入的,这里使用n方法判断出a.js的默认导出是commonJS的导出var _a_js__WEBPACK_IMPORTED_MODULE_0___default = __webpack_require__.n(_a_js__WEBPACK_IMPORTED_MODULE_0__);var _index_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__("./src/index.css");var aa = _a_js__WEBPACK_IMPORTED_MODULE_0___default.a;console.log(aa);console.log('hello webpack');var fn = function fn () {          console.log('我是fn');
        };
        fn();
      })
  });复制代码


模块依赖加载流程总结
0. 自调用函数接收到modules模块集合对象开始执行1. 执行到 return __webpack_require__(__webpack_require__.s = "./src/index.js");时,调用webpack_require函数传入第一个模块文件index.js2. webpack_require函数内部开始执行,判断传入的模块index.js是否存在缓存中,有的话直接从缓存中返回导出index.js的export导出,没有则将其存入缓存,并创建新对象module。3. 直接获取index.js模块对应的函数,直接执行,并传入响应的参数4. 执行index.js对象的函数时发现导入了a.js和index.css————>注意这里采用webpack_require函数递归导入a.js等,就跟导入index.js一样,最终将返回的结果在webpack_require的return module.exports处返回对应模块的导出,接着回到index.js对应的方法webpack_require('a.js')获取到a.js模块的exports,然后在index.js中进行使用export导出的值。复制代码