一文深入理解webpack实现原理,不再对编译报错无所适从

发布于:2022-12-26 ⋅ 阅读:(1159) ⋅ 点赞:(1)

nodejs、webpack都是openjs的项目,它的支持者中也是一大票美国公司,中国的自主研发的产品在哪儿,仅仅在在这一块,核心技术在哪儿?令人不快,只能学习借鉴。

接着之前的内容,在编译后的内容中,webpackBootstrap是在哪儿生成的呢?

在这里插入图片描述
这涉及到了chunk的业务。

根据module和chunk.time获得翻译的结果,如下:
在这里插入图片描述
再往前倒,看这个chunk是怎么来的。

往前倒,查看它的引用会发现,它是renderMain下的 inlineModules,如下:
在这里插入图片描述
那这个inlineModules是从哪儿来的?关键是要搞清楚,这个m是如何从chunk中转换的?再往前倒:
在这里插入图片描述
通过chunk获取对应ChunkGraphChunk的keys。这里有一个关键的点是如下内容:

_getChunkGraphChunk(chunk) {
	let cgc = this._chunks.get(chunk);
	if (cgc === undefined) {
		cgc = new ChunkGraphChunk();
		this._chunks.set(chunk, cgc);
	}
	return cgc;
}

这里的 this._chunks 是 new WeakMap() ,它实际上应该是作为了缓存,当再次使用 chunk 作为键的时候从 this._chunks 中通过 get 取值。

到这一步可以看到它对应的inlineModules下的条目对应的 _source 的值还没有被转换,它还是main.js的原生内容:
在这里插入图片描述
接着找这个源码编译的具体位置,到这一步还没有被编译,还是原生的内容:
在这里插入图片描述从这个hooks.renderStartup这个名字好像能看出来点意思,渲染启动的钩子方法。

但是这里只是添加到source,并没有调用钩子函数。而是执行完后回到了Compilation,如下:
在这里插入图片描述
alreadyWrittenFiles从名字上来看是已经写好的文件,但是它的用处是什么,得看后面的情况:
在这里插入图片描述
读取资源:
在这里插入图片描述
这个能看到提供解析的文件路径,但是具体解析的流程还是没找到,这就很头大:
在这里插入图片描述
这个地方会出现style-loader
在这里插入图片描述在这里插入图片描述
会反复进入到这个buildModule模块:
在这里插入图片描述
再往回倒,看这个 this._chunks 在赋值过程中发生的事情。在这一步骤会聚焦在 Compliation下的seal方法中:
在这里插入图片描述其中getModule如下:
在这里插入图片描述
查找引用模块的依赖项:
在这里插入图片描述connection下的module的_source如下:
在这里插入图片描述从这个到最后的输出到bundle.js中的内容还是有区别的

在这里插入图片描述
这一点比较重要。这其实也给看源码提供了一个思路,就是说当我们想要知道某一变量的状态的时候,可以从两个维度去考虑,一个是流程,一个是它本身。如果流程上无法判断它的衍变过程的情况下,就直接定位它本身通过逆推去寻找线索。

在这里插入图片描述
通过这种方式可以定位最终生成的bundle.js内容的位置,如下:

在这里插入图片描述
这里为了方便调试,在当前webpack-resource/lib/RawSource.js下的RawSource构造函数中增加了一个console.log(value)的输出,这样在中断中能够更容易得到对应的结果,如上图。

从RawSource向上一步推断,可以看到output.code就是最终在bundle.js中输出的内容:

在这里插入图片描述
这一步很关键,这个钩子在什么情况下注册的,它给compilation对象的钩子中processAssets添加处理逻辑:
在这里插入图片描述在webpack下调用的位置,也就是说这里除了使用TerserPlugin进行处理之外没有别的逻辑:
在这里插入图片描述
最后确定,在terser-webpack-pluginx/dist/index.js下的:

在这里插入图片描述
对应于webpack/Compilation/lib/Compilation中的:

在这里插入图片描述
当被拦截器拦截后执行 this.optimize。

执行到如下这一步的时候,内容就变成压缩处理后的内容,如下:
在这里插入图片描述
到这一步基本上搞清楚了,它的输入和输出的转换。但是为什么从es6就转换成了es5,在这里webpack起到了什么作用,loader在哪个环节有意义了,还是没有看到。要看的是它的webpack的函数有什么意义?

把上图中的options.input的内容拿出来看一看:

"/******/ (() => { // webpackBootstrap\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 329:\n/***/ ((module) => {\n\n\nfunction init(content)\n{\n    window.document.getElementById('app').innerHTML= content;\n}\n\n\n\nmodule.exports=init;\n\n/***/ }),\n\n/***/ 313:\n/***/ ((module, __webpack_exports__, __webpack_require__) => {\n\n\"use strict\";\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"Z\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(81);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(645);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \"#app{color:red;}\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n/***/ }),\n\n/***/ 645:\n/***/ ((module) => {\n\n\"use strict\";\n\n\n/*\n  MIT License http://www.opensource.org/licenses/mit-license.php\n  Author Tobias Koppers @sokra\n*/\nmodule.exports = function (cssWithMappingToString) {\n  var list = []; // return the list of modules as css string\n\n  list.toString = function toString() {\n    return this.map(function (item) {\n      var content = \"\";\n      var needLayer = typeof item[5] !== \"undefined\";\n\n      if (item[4]) {\n        content += \"@supports (\".concat(item[4], \") {\");\n      }\n\n      if (item[2]) {\n        content += \"@media \".concat(item[2], \" {\");\n      }\n\n      if (needLayer) {\n        content += \"@layer\".concat(item[5].length > 0 ? \" \".concat(item[5]) : \"\", \" {\");\n      }\n\n      content += cssWithMappingToString(item);\n\n      if (needLayer) {\n        content += \"}\";\n      }\n\n      if (item[2]) {\n        content += \"}\";\n      }\n\n      if (item[4]) {\n        content += \"}\";\n      }\n\n      return content;\n    }).join(\"\");\n  }; // import a list of modules into the list\n\n\n  list.i = function i(modules, media, dedupe, supports, layer) {\n    if (typeof modules === \"string\") {\n      modules = [[null, modules, undefined]];\n    }\n\n    var alreadyImportedModules = {};\n\n    if (dedupe) {\n      for (var k = 0; k < this.length; k++) {\n        var id = this[k][0];\n\n        if (id != null) {\n          alreadyImportedModules[id] = true;\n        }\n      }\n    }\n\n    for (var _k = 0; _k < modules.length; _k++) {\n      var item = [].concat(modules[_k]);\n\n      if (dedupe && alreadyImportedModules[item[0]]) {\n        continue;\n      }\n\n      if (typeof layer !== \"undefined\") {\n        if (typeof item[5] === \"undefined\") {\n          item[5] = layer;\n        } else {\n          item[1] = \"@layer\".concat(item[5].length > 0 ? \" \".concat(item[5]) : \"\", \" {\").concat(item[1], \"}\");\n          item[5] = layer;\n        }\n      }\n\n      if (media) {\n        if (!item[2]) {\n          item[2] = media;\n        } else {\n          item[1] = \"@media \".concat(item[2], \" {\").concat(item[1], \"}\");\n          item[2] = media;\n        }\n      }\n\n      if (supports) {\n        if (!item[4]) {\n          item[4] = \"\".concat(supports);\n        } else {\n          item[1] = \"@supports (\".concat(item[4], \") {\").concat(item[1], \"}\");\n          item[4] = supports;\n        }\n      }\n\n      list.push(item);\n    }\n  };\n\n  return list;\n};\n\n/***/ }),\n\n/***/ 81:\n/***/ ((module) => {\n\n\"use strict\";\n\n\nmodule.exports = function (i) {\n  return i[1];\n};\n\n/***/ }),\n\n/***/ 181:\n/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {\n\n\"use strict\";\n__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(379);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(795);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(569);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(565);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(216);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(589);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(313);\n\n      \n      \n      \n      \n      \n      \n      \n      \n      \n\nvar options = {};\n\noptions.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());\noptions.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());\n\n      options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, \"head\");\n    \noptions.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());\noptions.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());\n\nvar update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__/* [\"default\"] */ .Z, options);\n\n\n\n\n       /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__/* [\"default\"] */ .Z && _node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__/* [\"default\"].locals */ .Z.locals ? _node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__/* [\"default\"].locals */ .Z.locals : undefined);\n\n\n/***/ }),\n\n/***/ 379:\n/***/ ((module) => {\n\n\"use strict\";\n\n\nvar stylesInDOM = [];\n\nfunction getIndexByIdentifier(identifier) {\n  var result = -1;\n\n  for (var i = 0; i < stylesInDOM.length; i++) {\n    if (stylesInDOM[i].identifier === identifier) {\n      result = i;\n      break;\n    }\n  }\n\n  return result;\n}\n\nfunction modulesToDom(list, options) {\n  var idCountMap = {};\n  var identifiers = [];\n\n  for (var i = 0; i < list.length; i++) {\n    var item = list[i];\n    var id = options.base ? item[0] + options.base : item[0];\n    var count = idCountMap[id] || 0;\n    var identifier = \"\".concat(id, \" \").concat(count);\n    idCountMap[id] = count + 1;\n    var indexByIdentifier = getIndexByIdentifier(identifier);\n    var obj = {\n      css: item[1],\n      media: item[2],\n      sourceMap: item[3],\n      supports: item[4],\n      layer: item[5]\n    };\n\n    if (indexByIdentifier !== -1) {\n      stylesInDOM[indexByIdentifier].references++;\n      stylesInDOM[indexByIdentifier].updater(obj);\n    } else {\n      var updater = addElementStyle(obj, options);\n      options.byIndex = i;\n      stylesInDOM.splice(i, 0, {\n        identifier: identifier,\n        updater: updater,\n        references: 1\n      });\n    }\n\n    identifiers.push(identifier);\n  }\n\n  return identifiers;\n}\n\nfunction addElementStyle(obj, options) {\n  var api = options.domAPI(options);\n  api.update(obj);\n\n  var updater = function updater(newObj) {\n    if (newObj) {\n      if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap && newObj.supports === obj.supports && newObj.layer === obj.layer) {\n        return;\n      }\n\n      api.update(obj = newObj);\n    } else {\n      api.remove();\n    }\n  };\n\n  return updater;\n}\n\nmodule.exports = function (list, options) {\n  options = options || {};\n  list = list || [];\n  var lastIdentifiers = modulesToDom(list, options);\n  return function update(newList) {\n    newList = newList || [];\n\n    for (var i = 0; i < lastIdentifiers.length; i++) {\n      var identifier = lastIdentifiers[i];\n      var index = getIndexByIdentifier(identifier);\n      stylesInDOM[index].references--;\n    }\n\n    var newLastIdentifiers = modulesToDom(newList, options);\n\n    for (var _i = 0; _i < lastIdentifiers.length; _i++) {\n      var _identifier = lastIdentifiers[_i];\n\n      var _index = getIndexByIdentifier(_identifier);\n\n      if (stylesInDOM[_index].references === 0) {\n        stylesInDOM[_index].updater();\n\n        stylesInDOM.splice(_index, 1);\n      }\n    }\n\n    lastIdentifiers = newLastIdentifiers;\n  };\n};\n\n/***/ }),\n\n/***/ 569:\n/***/ ((module) => {\n\n\"use strict\";\n\n\nvar memo = {};\n/* istanbul ignore next  */\n\nfunction getTarget(target) {\n  if (typeof memo[target] === \"undefined\") {\n    var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself\n\n    if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n      try {\n        // This will throw an exception if access to iframe is blocked\n        // due to cross-origin restrictions\n        styleTarget = styleTarget.contentDocument.head;\n      } catch (e) {\n        // istanbul ignore next\n        styleTarget = null;\n      }\n    }\n\n    memo[target] = styleTarget;\n  }\n\n  return memo[target];\n}\n/* istanbul ignore next  */\n\n\nfunction insertBySelector(insert, style) {\n  var target = getTarget(insert);\n\n  if (!target) {\n    throw new Error(\"Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.\");\n  }\n\n  target.appendChild(style);\n}\n\nmodule.exports = insertBySelector;\n\n/***/ }),\n\n/***/ 216:\n/***/ ((module) => {\n\n\"use strict\";\n\n\n/* istanbul ignore next  */\nfunction insertStyleElement(options) {\n  var element = document.createElement(\"style\");\n  options.setAttributes(element, options.attributes);\n  options.insert(element, options.options);\n  return element;\n}\n\nmodule.exports = insertStyleElement;\n\n/***/ }),\n\n/***/ 565:\n/***/ ((module, __unused_webpack_exports, __webpack_require__) => {\n\n\"use strict\";\n\n\n/* istanbul ignore next  */\nfunction setAttributesWithoutAttributes(styleElement) {\n  var nonce =  true ? __webpack_require__.nc : 0;\n\n  if (nonce) {\n    styleElement.setAttribute(\"nonce\", nonce);\n  }\n}\n\nmodule.exports = setAttributesWithoutAttributes;\n\n/***/ }),\n\n/***/ 795:\n/***/ ((module) => {\n\n\"use strict\";\n\n\n/* istanbul ignore next  */\nfunction apply(styleElement, options, obj) {\n  var css = \"\";\n\n  if (obj.supports) {\n    css += \"@supports (\".concat(obj.supports, \") {\");\n  }\n\n  if (obj.media) {\n    css += \"@media \".concat(obj.media, \" {\");\n  }\n\n  var needLayer = typeof obj.layer !== \"undefined\";\n\n  if (needLayer) {\n    css += \"@layer\".concat(obj.layer.length > 0 ? \" \".concat(obj.layer) : \"\", \" {\");\n  }\n\n  css += obj.css;\n\n  if (needLayer) {\n    css += \"}\";\n  }\n\n  if (obj.media) {\n    css += \"}\";\n  }\n\n  if (obj.supports) {\n    css += \"}\";\n  }\n\n  var sourceMap = obj.sourceMap;\n\n  if (sourceMap && typeof btoa !== \"undefined\") {\n    css += \"\\n/*# sourceMappingURL=data:application/json;base64,\".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), \" */\");\n  } // For old IE\n\n  /* istanbul ignore if  */\n\n\n  options.styleTagTransform(css, styleElement, options.options);\n}\n\nfunction removeStyleElement(styleElement) {\n  // istanbul ignore if\n  if (styleElement.parentNode === null) {\n    return false;\n  }\n\n  styleElement.parentNode.removeChild(styleElement);\n}\n/* istanbul ignore next  */\n\n\nfunction domAPI(options) {\n  var styleElement = options.insertStyleElement(options);\n  return {\n    update: function update(obj) {\n      apply(styleElement, options, obj);\n    },\n    remove: function remove() {\n      removeStyleElement(styleElement);\n    }\n  };\n}\n\nmodule.exports = domAPI;\n\n/***/ }),\n\n/***/ 589:\n/***/ ((module) => {\n\n\"use strict\";\n\n\n/* istanbul ignore next  */\nfunction styleTagTransform(css, styleElement) {\n  if (styleElement.styleSheet) {\n    styleElement.styleSheet.cssText = css;\n  } else {\n    while (styleElement.firstChild) {\n      styleElement.removeChild(styleElement.firstChild);\n    }\n\n    styleElement.appendChild(document.createTextNode(css));\n  }\n}\n\nmodule.exports = styleTagTransform;\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t// The module cache\n/******/ \tvar __webpack_module_cache__ = {};\n/******/ \t\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/ \t\t// Check if module is in cache\n/******/ \t\tvar cachedModule = __webpack_module_cache__[moduleId];\n/******/ \t\tif (cachedModule !== undefined) {\n/******/ \t\t\treturn cachedModule.exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = __webpack_module_cache__[moduleId] = {\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\t// no module.loaded needed\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/ \t\n/******/ \t\t// Execute the module function\n/******/ \t\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n/******/ \t\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/ \t\n/************************************************************************/\n/******/ \t/* webpack/runtime/compat get default export */\n/******/ \t(() => {\n/******/ \t\t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t\t__webpack_require__.n = (module) => {\n/******/ \t\t\tvar getter = module && module.__esModule ?\n/******/ \t\t\t\t() => (module['default']) :\n/******/ \t\t\t\t() => (module);\n/******/ \t\t\t__webpack_require__.d(getter, { a: getter });\n/******/ \t\t\treturn getter;\n/******/ \t\t};\n/******/ \t})();\n/******/ \t\n/******/ \t/* webpack/runtime/define property getters */\n/******/ \t(() => {\n/******/ \t\t// define getter functions for harmony exports\n/******/ \t\t__webpack_require__.d = (exports, definition) => {\n/******/ \t\t\tfor(var key in definition) {\n/******/ \t\t\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n/******/ \t\t\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n/******/ \t\t\t\t}\n/******/ \t\t\t}\n/******/ \t\t};\n/******/ \t})();\n/******/ \t\n/******/ \t/* webpack/runtime/hasOwnProperty shorthand */\n/******/ \t(() => {\n/******/ \t\t__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))\n/******/ \t})();\n/******/ \t\n/******/ \t/* webpack/runtime/make namespace object */\n/******/ \t(() => {\n/******/ \t\t// define __esModule on exports\n/******/ \t\t__webpack_require__.r = (exports) => {\n/******/ \t\t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n/******/ \t\t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n/******/ \t\t\t}\n/******/ \t\t\tObject.defineProperty(exports, '__esModule', { value: true });\n/******/ \t\t};\n/******/ \t})();\n/******/ \t\n/******/ \t/* webpack/runtime/nonce */\n/******/ \t(() => {\n/******/ \t\t__webpack_require__.nc = undefined;\n/******/ \t})();\n/******/ \t\n/************************************************************************/\nvar __webpack_exports__ = {};\n// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.\n(() => {\n__webpack_require__(181);\nconst init=__webpack_require__(329)\ninit('问问计算机:webpack是怎么回事?');\n\n})();\n\n/******/ })()\n;"

用正则表达式替换换行和引号的内容后结果如下:

/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ 329:
/***/ ((module) => {
                function init(content) {
                    window.document.getElementById('app').innerHTML = content;
                }
                module.exports = init;
                /***/
}),

/***/ 313:
/***/ ((module, __webpack_exports__, __webpack_require__) => {
                "use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
                    /* harmony export */
});
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(81);
/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(645);
/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);
                // Imports
                var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
                // Module
                ___CSS_LOADER_EXPORT___.push([module.id, "#app{color:red;}", ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);
                /***/
}),

/***/ 645:
/***/ ((module) => {
                "use strict";
                /*
                  MIT License http://www.opensource.org/licenses/mit-license.php
                  Author Tobias Koppers @sokra
                */
                module.exports = function (cssWithMappingToString) {
                    var list = []; // return the list of modules as css string

                    list.toString = function toString() {
                        return this.map(function (item) {
                            var content = "";
                            var needLayer = typeof item[5] !== "undefined";

                            if (item[4]) {
                                content += "@supports (".concat(item[4], ") {");
                            }

                            if (item[2]) {
                                content += "@media ".concat(item[2], " {");
                            }

                            if (needLayer) {
                                content += "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {");
                            }

                            content += cssWithMappingToString(item);

                            if (needLayer) {
                                content += "}";
                            }

                            if (item[2]) {
                                content += "}";
                            }

                            if (item[4]) {
                                content += "}";
                            }

                            return content;
                        }).join("");
                    }; // import a list of modules into the list


                    list.i = function i(modules, media, dedupe, supports, layer) {
                        if (typeof modules === "string") {
                            modules = [[null, modules, undefined]];
                        }

                        var alreadyImportedModules = {};

                        if (dedupe) {
                            for (var k = 0; k < this.length; k++) {
                                var id = this[k][0];

                                if (id != null) {
                                    alreadyImportedModules[id] = true;
                                }
                            }
                        }

                        for (var _k = 0; _k < modules.length; _k++) {
                            var item = [].concat(modules[_k]);

                            if (dedupe && alreadyImportedModules[item[0]]) {
                                continue;
                            }

                            if (typeof layer !== "undefined") {
                                if (typeof item[5] === "undefined") {
                                    item[5] = layer;
                                } else {
                                    item[1] = "@layer".concat(item[5].length > 0 ? " ".concat(item[5]) : "", " {").concat(item[1], "}");
                                    item[5] = layer;
                                }
                            }

                            if (media) {
                                if (!item[2]) {
                                    item[2] = media;
                                } else {
                                    item[1] = "@media ".concat(item[2], " {").concat(item[1], "}");
                                    item[2] = media;
                                }
                            }

                            if (supports) {
                                if (!item[4]) {
                                    item[4] = "".concat(supports);
                                } else {
                                    item[1] = "@supports (".concat(item[4], ") {").concat(item[1], "}");
                                    item[4] = supports;
                                }
                            }

                            list.push(item);
                        }
                    };

                    return list;
                };

                /***/
}),

/***/ 81:
/***/ ((module) => {
                "use strict";
                module.exports = function (i) {
                    return i[1];
                };
                /***/
}),

/***/ 181:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
                "use strict";
                __webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
                    /* harmony export */
});
/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(379);
/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(795);
/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(569);
/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(565);
/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(216);
/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(589);
/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var _node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(313);
                var options = {};
                options.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());
                options.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());
                options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, "head");
                options.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());
                options.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());
                var update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__/* ["default"] */.Z, options);
       /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__/* ["default"] */.Z && _node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__/* ["default"].locals */.Z.locals ? _node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__/* ["default"].locals */.Z.locals : undefined);
                /***/
}),

/***/ 379:
/***/ ((module) => {
                "use strict";
                var stylesInDOM = [];
                function getIndexByIdentifier(identifier) {
                    var result = -1;
                    for (var i = 0; i < stylesInDOM.length; i++) {
                        if (stylesInDOM[i].identifier === identifier) {
                            result = i;
                            break;
                        }
                    }
                    return result;
                }
                function modulesToDom(list, options) {
                    var idCountMap = {};
                    var identifiers = [];

                    for (var i = 0; i < list.length; i++) {
                        var item = list[i];
                        var id = options.base ? item[0] + options.base : item[0];
                        var count = idCountMap[id] || 0;
                        var identifier = "".concat(id, " ").concat(count);
                        idCountMap[id] = count + 1;
                        var indexByIdentifier = getIndexByIdentifier(identifier);
                        var obj = {
                            css: item[1],
                            media: item[2],
                            sourceMap: item[3],
                            supports: item[4],
                            layer: item[5]
                        };

                        if (indexByIdentifier !== -1) {
                            stylesInDOM[indexByIdentifier].references++;
                            stylesInDOM[indexByIdentifier].updater(obj);
                        } else {
                            var updater = addElementStyle(obj, options);
                            options.byIndex = i;
                            stylesInDOM.splice(i, 0, {
                                identifier: identifier,
                                updater: updater,
                                references: 1
                            });
                        }

                        identifiers.push(identifier);
                    }

                    return identifiers;
                }

                function addElementStyle(obj, options) {
                    var api = options.domAPI(options);
                    api.update(obj);

                    var updater = function updater(newObj) {
                        if (newObj) {
                            if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap && newObj.supports === obj.supports && newObj.layer === obj.layer) {
                                return;
                            }

                            api.update(obj = newObj);
                        } else {
                            api.remove();
                        }
                    };

                    return updater;
                }

                module.exports = function (list, options) {
                    options = options || {};
                    list = list || [];
                    var lastIdentifiers = modulesToDom(list, options);
                    return function update(newList) {
                        newList = newList || [];

                        for (var i = 0; i < lastIdentifiers.length; i++) {
                            var identifier = lastIdentifiers[i];
                            var index = getIndexByIdentifier(identifier);
                            stylesInDOM[index].references--;
                        }

                        var newLastIdentifiers = modulesToDom(newList, options);

                        for (var _i = 0; _i < lastIdentifiers.length; _i++) {
                            var _identifier = lastIdentifiers[_i];

                            var _index = getIndexByIdentifier(_identifier);

                            if (stylesInDOM[_index].references === 0) {
                                stylesInDOM[_index].updater();

                                stylesInDOM.splice(_index, 1);
                            }
                        }

                        lastIdentifiers = newLastIdentifiers;
                    };
                };

                /***/
}),

/***/ 569:
/***/ ((module) => {
                "use strict";
                var memo = {};
                /* istanbul ignore next  */
                function getTarget(target) {
                    if (typeof memo[target] === "undefined") {
                        var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself

                        if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {
                            try {
                                // This will throw an exception if access to iframe is blocked
                                // due to cross-origin restrictions
                                styleTarget = styleTarget.contentDocument.head;
                            } catch (e) {
                                // istanbul ignore next
                                styleTarget = null;
                            }
                        }
                        memo[target] = styleTarget;
                    }
                    return memo[target];
                }
                /* istanbul ignore next  */
                function insertBySelector(insert, style) {
                    var target = getTarget(insert);
                    if (!target) {
                        throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");
                    }
                    target.appendChild(style);
                }

                module.exports = insertBySelector;
                /***/
}),

/***/ 216:
/***/ ((module) => {

                "use strict";


                /* istanbul ignore next  */
                function insertStyleElement(options) {
                    var element = document.createElement("style");
                    options.setAttributes(element, options.attributes);
                    options.insert(element, options.options);
                    return element;
                }

                module.exports = insertStyleElement;

                /***/
}),

/***/ 565:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

                "use strict";


                /* istanbul ignore next  */
                function setAttributesWithoutAttributes(styleElement) {
                    var nonce = true ? __webpack_require__.nc : 0;

                    if (nonce) {
                        styleElement.setAttribute("nonce", nonce);
                    }
                }

                module.exports = setAttributesWithoutAttributes;

                /***/
}),

/***/ 795:
/***/ ((module) => {

                "use strict";


                /* istanbul ignore next  */
                function apply(styleElement, options, obj) {
                    var css = "";

                    if (obj.supports) {
                        css += "@supports (".concat(obj.supports, ") {");
                    }

                    if (obj.media) {
                        css += "@media ".concat(obj.media, " {");
                    }

                    var needLayer = typeof obj.layer !== "undefined";

                    if (needLayer) {
                        css += "@layer".concat(obj.layer.length > 0 ? " ".concat(obj.layer) : "", " {");
                    }

                    css += obj.css;

                    if (needLayer) {
                        css += "}";
                    }

                    if (obj.media) {
                        css += "}";
                    }

                    if (obj.supports) {
                        css += "}";
                    }

                    var sourceMap = obj.sourceMap;

                    if (sourceMap && typeof btoa !== "undefined") {
                        css += "\
/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */");
                    } // For old IE

                    /* istanbul ignore if  */


                    options.styleTagTransform(css, styleElement, options.options);
                }

                function removeStyleElement(styleElement) {
                    // istanbul ignore if
                    if (styleElement.parentNode === null) {
                        return false;
                    }

                    styleElement.parentNode.removeChild(styleElement);
                }
                /* istanbul ignore next  */


                function domAPI(options) {
                    var styleElement = options.insertStyleElement(options);
                    return {
                        update: function update(obj) {
                            apply(styleElement, options, obj);
                        },
                        remove: function remove() {
                            removeStyleElement(styleElement);
                        }
                    };
                }

                module.exports = domAPI;

                /***/
}),

/***/ 589:
/***/ ((module) => {

                "use strict";


                /* istanbul ignore next  */
                function styleTagTransform(css, styleElement) {
                    if (styleElement.styleSheet) {
                        styleElement.styleSheet.cssText = css;
                    } else {
                        while (styleElement.firstChild) {
                            styleElement.removeChild(styleElement.firstChild);
                        }

                        styleElement.appendChild(document.createTextNode(css));
                    }
                }

                module.exports = styleTagTransform;

                /***/
})

        /******/
});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
            /******/
}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			id: moduleId,
/******/ 			// no module.loaded needed
/******/ 			exports: {}
            /******/
};
/******/
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
        /******/
}
/******/
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
            /******/
};
        /******/
})();
/******/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for (var key in definition) {
/******/ 				if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
                    /******/
}
                /******/
}
            /******/
};
        /******/
})();
/******/
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
        /******/
})();
/******/
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
                /******/
}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
            /******/
};
        /******/
})();
/******/
/******/ 	/* webpack/runtime/nonce */
/******/ 	(() => {
/******/ 		__webpack_require__.nc = undefined;
        /******/
})();
    /******/
    /************************************************************************/
    var __webpack_exports__ = {};
    // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
    (() => {
        __webpack_require__(181);
        const init = __webpack_require__(329)
        init('问问计算机:webpack是怎么回事?');
    })();
    /******/
})()
    ;

折叠起代码块如下:

在这里插入图片描述
把这个文件重命名为 bundle.js 放在dist文件夹下,浏览 index.html 效果如下:

在这里插入图片描述
也就是说这个效果和最终输出的编译压缩后的bundle.js的效果是一样的。但是这个对于查看编译结果的内容来说更加直白。

初始化 __webpack_modules__ 对象,各模块对应的属性名称是 数字,如下:329,313,645,81,181,379,569,216,565,795,589

在这里插入图片描述
这里在第一次加载的时候实际上它只是给对 __webpack_require__.n进行了赋值而已,并没有调用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D186EO44-1662528249572)(static/image-20220822092020034.png)]

后面几个方法同理,只是对 __webpack_require__.d、 __webpack_require__.o __webpack_require__.r、 __webpack_require__.nc进行赋值:

在这里插入图片描述
在最后才开始真正的业务实现,如下:

在这里插入图片描述
调用__webpack_require__(181),先经过如下过程,判断缓存对象中是否存在对应于181的模块,如果存在直接获取,如果不存在久再创建一个新的对应moduleId的模块对象。然后使用 __webpack_module__[moduleId]执行对应的方法(注:这里的 __webpack_module_cache 只是当前环境下的一个对象,并不是操作系统的角度去理解的物理意义上的缓存机制):

/*
 * __webpack_module_cache 模块缓存对象
 * author:askcomputer
 * **/
var __webpack_module_cache__ = {};
 /*
 * __webpack_require 方法
 * author:askcomputer
 * **/
function __webpack_require__(moduleId) {
	// 判断模块是否在cache中
    var cachedModule = __webpack_module_cache__[moduleId];
    if (cachedModule !== undefined) {
        return cachedModule.exports;
	}
	//如果cache对象中没有,就创建一个新的模块,并把它放在cache中
    var module = __webpack_module_cache__[moduleId] = {
        id: moduleId,
        exports: {}
    };
    // 根据moduleId调用__webpack_modules__对象中对应的模块方法
    __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
    return module.exports;
}

下面执行181对应的方法如下,其中三个参数对应的实参:

在这里插入图片描述

{
    ...
    181:
    ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
                    "use strict";
                    __webpack_require__.r(__webpack_exports__);
	...

这一步骤给 __webpack_exports__ 对象添加属性,并赋值如下:

在这里插入图片描述在这里插入图片描述
紧接着调用 d 方法 如下:

在这里插入图片描述在这里插入图片描述

调用 o 方法,如下:

if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
    Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
}

o 方法:

在这里插入图片描述

__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))

Object.prototype.hasOwnProperty.call() 用来判断一个属性是定义在对象本身而不是继承自原型链。

在这里插入图片描述
这种情况下,__webpack_require__.o(definition, key) 的结果为true,而__webpack_require__.o(exports, key) 的结果为false。很明显,definition 当参数传进来的时候给的 default ,而 exports 在前面定义的只有 __esModule属性和 Symbol(Symbol.toStringTag),所以if后的条件成立,执行if的代码块,如下:

在这里插入图片描述
执行完后给 exports 对象绑定了get属性,如下:

在这里插入图片描述

接下来回到模块181,并调用模块379如下:

在这里插入图片描述

/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(379);

这一步到这里实际上什么都没有做,它只是给 module.exports 赋值了一个方法,但是并没有执行。如下:

在这里插入图片描述
紧接着:

在这里插入图片描述

var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = __webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);

调用n方法,参数是上一步中初始化的模块379。如下:

(() => {
		__webpack_require__.n = (module) => {
		var getter = module && module.__esModule ?
				() => (module['default']) :
				() => (module);
		__webpack_require__.d(getter, { a: getter });
		return getter;
	};
})();

给module设置getter属性,如下:

在这里插入图片描述
并赋值给_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default。如下几种同理:

在这里插入图片描述
下一步看一看 css_loader 的模块,如下:

var _node_modules_css_loader_dist_cjs_js_index_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(313);

实现过程类似。

直到 __webpack_require__(181) 这个方法执行完进入下一步之前所有的内容都是对于 css 的处理,其前提是以webpack 的模块调用过程为基础。

下面的关键就是 这个 Loader 是在什么情况下, 运行的,它和 webpack.config.js 中的配置是什么时候关联上的。

在这其中的loader-runner是干什么用的?

在这里插入图片描述在这里插入图片描述
得到的是一个RawSource对象。

这是解析器解析步骤的一个重要环节:

在这里插入图片描述在这里插入图片描述
这一步比较重要,它涉及到acorn,将原有的source对应的脚本转换成AST格式。

在这里插入图片描述
需要了解acorn的使用方式 https://blog.csdn.net/u012222078/article/details/70185068。

content的内容全部加载输出parser完成之后,进入到renderMain的阶段,如下:

在这里插入图片描述
这里涉及到一个RuntimeTemplate.js的内容,暂且不知道它具体的用处是什么。这里看一看针对上述的输出内容,看它的每一行最终的结果是怎么转换输出的。好像离终点越来越近了。

加载,解析,编译,渲染,输出。

现在这一步到了模板渲染最终结果的阶段了。

但是前面的加载器处理的过程,还需要进一步细化。当前只是知道了,它如何进入加载器。怎么找到加载器,加载器做了哪些操作还需要进一步抽象明确。

在这里插入图片描述
这儿就是输出的最终的渲染结果的部分。从这再往回倒应该就相对更清晰。

详细看这个streamChunk方法的五个参数:
在这里插入图片描述
在streamChunk方法中得到的结果对应source和code,然后用于resultSource的后续处理。

其中当前上下文中:

  • source:

在这里插入图片描述
这里的source的类型是ConcatSource的类型,在ConcatSource类下可以看到streamChunk的方法,所以这里第一个if判断结果为真,执行if条件下的代码块。ConcatSource中的Concat直译是“连接”的意思。比如在JavaScript中的数组就有concat方法,用于两个数组的连接组合。这里的ConcatSource是对不同种类型的Source的连接。这里的ConcatSource会根据类型去关联CachedSource和RawSources的streamChunk。

	streamChunks(options, onChunk, onSource, onName) {
		if (!this._isOptimized) this._optimize(); //把字符串部分变更为RawSources类型,其中子节点的顺序保持原样,CachedSource部分不做修改,直接push到newChildren中
		if (this._children.length === 1)
			return this._children[0].streamChunks(options, onChunk, onSource, onName);
		let currentLineOffset = 0;
		let currentColumnOffset = 0;
		let sourceMapping = new Map();
		let nameMapping = new Map();
		const finalSource = !!(options && options.finalSource);
		let code = "";
		let needToCloseMapping = false;
		for (const item of this._children) {
			const sourceIndexMapping = [];
			const nameIndexMapping = [];
			let lastMappingLine = 0;
            //这里嵌套了一层streamChunks,可是这里调用的不是文件中的streamChunk,而是引入的 const streamChunks = require("./helpers/streamChunks"); 
            //generatedLine:生成的行
            //generatedColumn:生成的列
            //source:解析的内容,源代码
			const { generatedLine, generatedColumn, source } = streamChunks(  
				item,
				options,
				// eslint-disable-next-line no-loop-func
				(
					chunk,
					generatedLine,
					generatedColumn,
					sourceIndex,
					originalLine,
					originalColumn,
					nameIndex
				) => {
					const line = generatedLine + currentLineOffset;
					const column =
						generatedLine === 1
							? generatedColumn + currentColumnOffset
							: generatedColumn;
					if (needToCloseMapping) {
						if (generatedLine !== 1 || generatedColumn !== 0) {
							onChunk(
								undefined,
								currentLineOffset + 1,
								currentColumnOffset,
								-1,
								-1,
								-1,
								-1
							);
						}
						needToCloseMapping = false;
					}
					const resultSourceIndex =
						sourceIndex < 0 || sourceIndex >= sourceIndexMapping.length
							? -1
							: sourceIndexMapping[sourceIndex];
					const resultNameIndex =
						nameIndex < 0 || nameIndex >= nameIndexMapping.length
							? -1
							: nameIndexMapping[nameIndex];
					lastMappingLine = resultSourceIndex < 0 ? 0 : generatedLine;
					if (finalSource) {
						if (chunk !== undefined) code += chunk;
						if (resultSourceIndex >= 0) {
							onChunk(
								undefined,
								line,
								column,
								resultSourceIndex,
								originalLine,
								originalColumn,
								resultNameIndex
							);
						}
					} else {
						if (resultSourceIndex < 0) {
							onChunk(chunk, line, column, -1, -1, -1, -1);
						} else {
							onChunk(
								chunk,
								line,
								column,
								resultSourceIndex,
								originalLine,
								originalColumn,
								resultNameIndex
							);
						}
					}
				},
				(i, source, sourceContent) => {
					let globalIndex = sourceMapping.get(source);
					if (globalIndex === undefined) {
						sourceMapping.set(source, (globalIndex = sourceMapping.size));
						onSource(globalIndex, source, sourceContent);
					}
					sourceIndexMapping[i] = globalIndex;
				},
				(i, name) => {
					let globalIndex = nameMapping.get(name);
					if (globalIndex === undefined) {
						nameMapping.set(name, (globalIndex = nameMapping.size));
						onName(globalIndex, name);
					}
					nameIndexMapping[i] = globalIndex;
				}
			);
			if (source !== undefined) code += source;
			if (needToCloseMapping) {
				if (generatedLine !== 1 || generatedColumn !== 0) {
					onChunk(
						undefined,
						currentLineOffset + 1,
						currentColumnOffset,
						-1,
						-1,
						-1,
						-1
					);
					needToCloseMapping = false;
				}
			}
			if (generatedLine > 1) { //如果生成的行数大于一
				currentColumnOffset = generatedColumn; //当前的column偏移等于生成的列的数量【ME:这里还不太明白怎么回事】
			} else {
				currentColumnOffset += generatedColumn;
			}
			needToCloseMapping =
				needToCloseMapping ||
				(finalSource && lastMappingLine === generatedLine);
			currentLineOffset += generatedLine - 1;
		}
		return {
			generatedLine: currentLineOffset + 1,
			generatedColumn: currentColumnOffset,
			source: finalSource ? code : undefined
		};
	}
  • options

在这里插入图片描述

  • onChunk

在这里插入图片描述

  • onSource

在这里插入图片描述

  • onName

在这里插入图片描述在这里插入图片描述
需要确认的是这个方法的详细逻辑,它实际上是根据module去获取对应的运行时结果,关键在于codeGenerationResults对应的get方法的理解:

在这里插入图片描述
从下图可以看到,module对应的内容:
在这里插入图片描述
在渲染模块renderModule的时候会用到 this.map ,如下:
在这里插入图片描述
而这个this.map是在什么时候赋值的呢?如下:

在这里插入图片描述
调用它的地方位于Compilation,如下:

在这里插入图片描述
那么下面一个问题就是这里的Module[1003:…]是什么时候添加到 CodeGenerationResults 的 this.map 中的,使用如下方式:

在这里插入图片描述
这个module来自于:

在这里插入图片描述module来自于 _runCodeGenerationJobs

在这里插入图片描述
需要明确这个方法的过程。到这一步就离转换的起点更近了。

在这里插入图片描述
这里对于 asyncLib.eachLimit的理解比较重要,它是neo-async的内容,其中第一个参数 jobs 是任务数组,第二个参数是 任务并行执行的数量,第三个参数是对应每个任务的回调函数。

所以在这个基础上就能理解,对应于job当中的module,实际上是来自于jobs对应的处理后调用回调函数传回来的参数。那么这种情况下就要明确jobs的内容。

而jobs来自于_runCodeGenerationJobs的形参。如下:

在这里插入图片描述
它的调用位置在:

在这里插入图片描述
然后进一步查看这个jobs的创建过程。从这个方法中可以看到 jobs 是由 this.modules 遍历后处理得到的。这里的this.modules 是Set对象。JavaScript中Set对象是唯一值的集合,每个值在Set中只能出现一次,一个Set可以容纳任何数据类型的任何值。

所以接着要看这个 this.modules 是什么情况下 add 的元素。

在这里插入图片描述

到这已经触及到了工作中经常说的webpack中将一切视为模块进行打包的理念了。下一步要搞清楚的是这里的模块是什么模块,怎么生成的。

在这里插入图片描述
一方面需要确认addModule与_addModule之间的关系,另一方面需要进一步确认addModule的调用位置和module的生成位置,如下:

在这里插入图片描述
下面详细分析这个this.factorizeModule的实现细节。

this.factoryModule,它对应于 Compilation.prototype.factorizeModule :

//这里的factorize直译为“分解”的意思
Compilation.prototype.factorizeModule = (
	function (options, callback) {
		this.factorizeQueue.add(options, callback); 
	}
);

把参数送给了this.factorizeQueue的add方法。factorizeQueue是一个AsyncQueue,AsyncQueue是在webpack中定义的一个异步队列的类型。这一个过程就很关键,理解起来也比较晦涩。

在AsyncQueue的构造函数中定义了4个钩子。如下:

在这里插入图片描述
当上面执行 this.factorizeQueue.add(options, callback); 方法的时候,就在钩子上调用了 beforeAdd。在add方法中执行了 this.hooks.beforeAdd.callAsync,如下:

在这里插入图片描述
这里需要搞清的是callAsync发生了什么事情。

但是因为没有通过tap订阅消息,所以这里直接执行回调函数。

查看key和newEntry,如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

最终定位到 module 的生成位置如下:

在这里插入图片描述
如下:

在这里插入图片描述在这里插入图片描述

从这就能看到对应于Module的唯一身份识别码,起始位1000。

还有一个关键的地方要注意的是loader-runner

在这里插入图片描述
下面大概捋一捋思路:从createData到Module,增加了很多属性。

在这里插入图片描述
在这里插入图片描述
这里用的get,实际上它对应的是add方法,

在这里插入图片描述
在这个方法里看一看到,它把三个参数也就是 module、runtime和result 三个合成了一个,实际上最后输出的内容,是存在result里的。

在这里插入图片描述
result生成的位置如下:

在这里插入图片描述对应结果中的181找到踪迹了,如下:

在这里插入图片描述
实际上文件的内容在一开始的时候就已经读成字节流了,如下:

在这里插入图片描述
在这里插入图片描述
这里的 this._source 在 codeGenerator的时候被获取:

在这里插入图片描述
在这里插入图片描述
现在基本流程基本上清晰了,需要进一步定位的是 loader 也就是 style-loader 和 css-loader 这两个 loader 实际应用的点 在哪儿。

在这里插入图片描述
解析请求数组:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这样这个过程就关联上了。

知道了什么时候进行的关联,下一步要明确,什么时候进行的转换,如何进行的loader的转换。这个实际上依托于load-runner。

在这里插入图片描述
在这里插入图片描述
所以接下要看看 load-runner是个什么鬼东西。针对loader-runner源码,要明确测试的流程和使用方法。


网站公告

今日签到

点亮在社区的每一天
去签到