带你一步步分析webpack是如何执行打包产物的

news/2024/5/2 9:16:27/文章来源:https://blog.csdn.net/qq_35094120/article/details/127144663

引入关系如图所示:
在这里插入图片描述
圈出来文件d是异步导入的文件。
wepback版本如图所示:
在这里插入图片描述
执行打包命令,产物如下图:
在这里插入图片描述
会生成两个js文件,一个是入口文件打包的testxx.js,还有一个是异步文件d生成的src_d_js.js。
打包后的内容如下所示,先贴代码,后面再分析:


(() => { // webpackBootstrap"use strict";var __webpack_modules__ = ({"./src/c.js":((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"a\": () => (/* binding */ a),\n/* harmony export */   \"b\": () => (/* binding */ b)\n/* harmony export */ });\nconst a = function () {\n  console.log(1);\n}\n\nconst b = function () {\n  console.log(2);\n}\n\na()\nb()\n\n__webpack_require__.e(/*! import() */ \"src_d_js\").then(__webpack_require__.bind(__webpack_require__, /*! ./d */ \"./src/d.js\")).then(res => {\n  console.log(res);\n})\n\n\n//# sourceURL=webpack://test-webpack/./src/c.js?");}),"./src/index.js":((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _c__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./c */ \"./src/c.js\");\n\r\n(0,_c__WEBPACK_IMPORTED_MODULE_0__.a)()\n\n//# sourceURL=webpack://test-webpack/./src/index.js?");})});/************************************************************************/// The module cachevar __webpack_module_cache__ = {};// The require functionfunction __webpack_require__(moduleId) {// Check if module is in cachevar 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] = {// no module.id needed// no module.loaded neededexports: {}};// Execute the module function__webpack_modules__[moduleId](module, module.exports, __webpack_require__);// Return the exports of the modulereturn module.exports;}// expose the modules object (__webpack_modules__)__webpack_require__.m = __webpack_modules__;/************************************************************************//* 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/ensure chunk */(() => {__webpack_require__.f = {};// This file contains only the entry chunk.// The chunk loading function for additional chunks__webpack_require__.e = (chunkId) => {return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {__webpack_require__.f[key](chunkId, promises);return promises;}, []));};})();/* webpack/runtime/get javascript chunk filename */(() => {// This function allow to reference async chunks__webpack_require__.u = (chunkId) => {// return url for filenames based on templatereturn "" + chunkId + ".js";};})();/* webpack/runtime/global */(() => {__webpack_require__.g = (function () {if (typeof globalThis === 'object') return globalThis;try {return this || new Function('return this')();} catch (e) {if (typeof window === 'object') return window;}})();})();/* webpack/runtime/hasOwnProperty shorthand */(() => {__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))})();/* webpack/runtime/load script */(() => {var inProgress = {};var dataWebpackPrefix = "test-webpack:";// loadScript function to load a script via script tag__webpack_require__.l = (url, done, key, chunkId) => {if (inProgress[url]) { inProgress[url].push(done); return; }var script, needAttach;if (key !== undefined) {var scripts = document.getElementsByTagName("script");for (var i = 0; i < scripts.length; i++) {var s = scripts[i];if (s.getAttribute("src") == url || s.getAttribute("data-webpack") == dataWebpackPrefix + key) { script = s; break; }}}if (!script) {needAttach = true;script = document.createElement('script');script.charset = 'utf-8';script.timeout = 120;if (__webpack_require__.nc) {script.setAttribute("nonce", __webpack_require__.nc);}script.setAttribute("data-webpack", dataWebpackPrefix + key);script.src = url;}inProgress[url] = [done];var onScriptComplete = (prev, event) => {// avoid mem leaks in IE.script.onerror = script.onload = null;clearTimeout(timeout);var doneFns = inProgress[url];delete inProgress[url];script.parentNode && script.parentNode.removeChild(script);doneFns && doneFns.forEach((fn) => (fn(event)));if (prev) return prev(event);};var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);script.onerror = onScriptComplete.bind(null, script.onerror);script.onload = onScriptComplete.bind(null, script.onload);needAttach && document.head.appendChild(script);};})();/* 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/publicPath */(() => {var scriptUrl;if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";var document = __webpack_require__.g.document;if (!scriptUrl && document) {if (document.currentScript)scriptUrl = document.currentScript.srcif (!scriptUrl) {var scripts = document.getElementsByTagName("script");if (scripts.length) scriptUrl = scripts[scripts.length - 1].src}}// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration// or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/");__webpack_require__.p = scriptUrl;})();/* webpack/runtime/jsonp chunk loading */(() => {// no baseURI// object to store loaded and loading chunks// undefined = chunk not loaded, null = chunk preloaded/prefetched// [resolve, reject, Promise] = chunk loading, 0 = chunk loadedvar installedChunks = {"testxx": 0};__webpack_require__.f.j = (chunkId, promises) => {// JSONP chunk loading for javascriptvar installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;if (installedChunkData !== 0) { // 0 means "already installed".// a Promise means "currently loading".if (installedChunkData) {promises.push(installedChunkData[2]);} else {if (true) { // all chunks have JS// setup Promise in chunk cachevar promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));promises.push(installedChunkData[2] = promise);// start chunk loadingvar url = __webpack_require__.p + __webpack_require__.u(chunkId);// create error before stack unwound to get useful stacktrace latervar error = new Error();var loadingEnded = (event) => {if (__webpack_require__.o(installedChunks, chunkId)) {installedChunkData = installedChunks[chunkId];if (installedChunkData !== 0) installedChunks[chunkId] = undefined;if (installedChunkData) {var errorType = event && (event.type === 'load' ? 'missing' : event.type);var realSrc = event && event.target && event.target.src;error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';error.name = 'ChunkLoadError';error.type = errorType;error.request = realSrc;installedChunkData[1](error);}}};__webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);} else installedChunks[chunkId] = 0;}}};// install a JSONP callback for chunk loadingvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {var [chunkIds, moreModules, runtime] = data;// add "moreModules" to the modules object,// then flag all "chunkIds" as loaded and fire callbackvar moduleId, chunkId, i = 0;if (chunkIds.some((id) => (installedChunks[id] !== 0))) {for (moduleId in moreModules) {if (__webpack_require__.o(moreModules, moduleId)) {__webpack_require__.m[moduleId] = moreModules[moduleId];}}if (runtime) var result = runtime(__webpack_require__);}if (parentChunkLoadingFunction) parentChunkLoadingFunction(data);for (; i < chunkIds.length; i++) {chunkId = chunkIds[i];if (__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {installedChunks[chunkId][0]();}installedChunks[chunkId] = 0;}}var chunkLoadingGlobal = self["webpackChunktest_webpack"] = self["webpackChunktest_webpack"] || [];chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));})();// startup// Load entry module and return exports// This entry module can't be inlined because the eval devtool is used.var __webpack_exports__ = __webpack_require__("./src/index.js");})();

1.加载入口文件
在这里插入图片描述
在这里插入图片描述
index.js文件会引入c.js文件并执行a方法
在这里插入图片描述
会先执行
在这里插入图片描述
先执行__webpack_require__.r方法,定义了一些属性:
在这里插入图片描述
然后执行__webpack_require__导入c.js:
在这里插入图片描述
然后执行下面的方法:

__webpack_modules__[moduleId](module, module.exports, __webpack_require__);

继续执行下面c.js里面的方法:

 ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {__webpack_require__.r(__webpack_exports__);__webpack_require__.d(__webpack_exports__, { "a": () => (a), "b": () => (b)});const a = function () {console.log(1);}const b = function () {console.log(2);}a()b()__webpack_require__.e("src_d_js").then(()=>{return __webpack_require__.bind(__webpack_require__,"./src/d.js")}).then(res => { console.log(res);})})

该函数会先执行.d方法,该方法已定义,但是是没添加到exports上,则会添加到exports:
在这里插入图片描述
然后执行:

__webpack_require__.e(/*! import() */ "src_d_js")

在这里插入图片描述
在这个方法中主要是执行__webpack_require.f.j方法:

__webpack_require__.f.j = (chunkId, promises) => {// 判断是否加载过var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;if (installedChunkData !== 0) { // 0 means "already installed".// a Promise means "currently loading".if (installedChunkData) {promises.push(installedChunkData[2]);} else {if (true) { // all chunks have JS// setup Promise in chunk cachevar promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));promises.push(installedChunkData[2] = promise);// start chunk loadingvar url = __webpack_require__.p + __webpack_require__.u(chunkId);// create error before stack unwound to get useful stacktrace latervar error = new Error();var loadingEnded = (event) => {if (__webpack_require__.o(installedChunks, chunkId)) {installedChunkData = installedChunks[chunkId];if (installedChunkData !== 0) installedChunks[chunkId] = undefined;if (installedChunkData) {var errorType = event && (event.type === 'load' ? 'missing' : event.type);var realSrc = event && event.target && event.target.src;error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';error.name = 'ChunkLoadError';error.type = errorType;error.request = realSrc;installedChunkData[1](error);}}};__webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);} else installedChunks[chunkId] = 0;}}};

webpack_require.f.j方法主要是将设置一个promise,并将resolve,reject和本身放入installedChunkData,promises一开始是空列表,然后放入promise。随后调用__webpack_require__.l方法,并将要加载的文件url、加载完成事件等作为参数传入:

__webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);

接下来调用__webpack_require__.l方法:
在这里插入图片描述
该方法会根据url判断是否已经加载该script,如果没有就会去加载:
在这里插入图片描述
超时时间原本是120ms,本人调试就延迟了时间,这里会创建script并设置url为要加载的文件。
在这里插入图片描述
然后会监听该script的onload事件,当加载完毕会调用onScriptComplete函数。在调用该函数加载完毕之前会继续执行下图代码返回promises,该promises就是一开始installedChunks列表里放的[resolve,reject]。
在这里插入图片描述那么这个resolve什么时候执行呢?我们接着往下看,此时该文件已加载:
在这里插入图片描述

在这里插入图片描述
加载完成后就会执行onload函数的回调:onScriptComplete函数。在这里插入图片描述
如果已经超时的话就好执行setTimeout函数,相当于加载失败直接回调了:

在这里插入图片描述
此时event就是:
在这里插入图片描述
如果没有超时则会加载script的内容,此时内容如下:
在这里插入图片描述
就是d.js模块的内容:
在这里插入图片描述

"use strict";
(self["webpackChunktest_webpack"] = self["webpackChunktest_webpack"] || []).push([["src_d_js"], {"./src/d.js":((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"a\": () => (/* binding */ a),\n/* harmony export */   \"b\": () => (/* binding */ b)\n/* harmony export */ });\nconst a = function () {\n  console.log(1);\n}\n\nconst b = function () {\n  console.log(2);\n}\n\na()\nb()\n\n//# sourceURL=webpack://test-webpack/./src/d.js?");/***/})}]);

该模块可以看出会先执行webpackChunktest_webpack方法,那么该方法又从哪里来的呢?其实在一开始就定义了该函数:
在这里插入图片描述
并且设置覆盖了push方法为webpackJsonpCallback。该函数的作用是在modules记录该模块,并且执行resolve回调。如果该模块id在installedChunks里面(执行过__webpack_require__.f.j方法就会在该数组里面,相当于import),此时就会执行第一个函数,该函数就是promise的resolve。
在这里插入图片描述
此时会执行zhen方法,于是执行__webpack_require方法:
在这里插入图片描述
于是又到了我们熟悉的内容,上面已经分析过了,此时不再赘述。
在这里插入图片描述
执行完上面的模块,就会执行第二个then方法:
在这里插入图片描述
然后还有最后一个onload回调,由于script是宏任务,所以会执行完所有的微任务,再执行onload回调。
在这里插入图片描述
onload回调会移除该script和超时定时器。然后执行fn(event),fn是loadingEnded,event是script.onload或script.onerror。正常执行完后会在webpackJsonpCallback里将installedChunks[chunkId] = 0,而installedChunkData会获取installedChunks[chunkId]的值。如果installedChunkData不是0说明没有执行webpackJsonpCallback,而webpackJsonpCallback的执行条件是已经script下载了内容才会执行。
在这里插入图片描述
全篇至此结束,还有些细节可能还没分析,有时间会再出文章解释说明,请各位读者持续关注。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_206630.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS学习298~355(品优购+Web服务器)

1 品优购项目规划 1.1 网站制作流程 我们主要做前台页面设计 1.2 品优购项目整体介绍 项目名称: 品优购项目描述:品优购是一个电商网站,我们要完成PC端首页、列表页、注册页面的制作 1.3 品优购项目的学习目的 电商类网站比较综合,里面需要大量的布局技术,包括布局方式、…

数据结构-复杂度(深入学习版+Java版)

文章目录一、复杂度经典例子分析1、计算时间复杂度分析题1&#xff1a;O(NM)&#xff0c;循环题2&#xff1a;O(N^2)&#xff0c;冒泡排序题3&#xff1a;O(logN)&#xff0c;二分查找题4&#xff1a;O(N)&#xff0c;阶乘递归题5&#xff1a;O(2^N)&#xff0c;斐波那契递归(满…

ffmpeg、ffplay、ffprobe 常用命令详解(音视频必备)

前言&#xff1a; &#x1f604;作者简介&#xff1a;小曾同学.com,小伙伴们也可以叫我小曾&#xff0c;一个致力于测试开发的博主⛽️ 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;…

回溯算法 - 二叉树中和为某一值的路径 字符串的排列

目录 1.二叉树中和为某一值的路径 1.1 题目描述 1.2 回溯算法的一般步骤 1.3 解题思路 1.4 代码实现 2. 字符串的排列 2.1 题目描述 2.2 解题思路 2.3 代码实现 1.二叉树中和为某一值的路径 1.1 题目描述 输入一颗二叉树的根节点root和一个整数expectNumber&#xff…

华为模拟器ensp学习笔记

CSDN话题挑战赛第2期 参赛话题&#xff1a;学习笔记 目录前言1️⃣如何注册eNSP设备?2️⃣如何通过SecureCRT登录eNSP模拟设备&#xff1f;结语前言 记录华为模拟器使用中遇到的问题 1️⃣如何注册eNSP设备? 如何注册eNSP设备 重新注册AR、WLAN设备&#xff1a; 启动AR时&…

模块化:CommonJS规范

目录 CommonJS规范 模块使用环境区分 核心语法 如何使用 CommonJS&#xff1a;服务器端使用 CommonJS&#xff1a;浏览器端使用 CommonJS规范 模块使用环境区分 CommonJS规范中&#xff0c;每一个JS文件都可以作为一个模块。模块的引入&#xff0c;主要区分两个环境&…

基于Java后台(Springboot框架)+前端小程序(MINA框架)+Mysql数据库的医院预约挂号小程序系统设计与实现

项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于微信小程序医院预约挂号系统&#xff0c;前台用户使用小程序&#xff0c;后台管理使用基JavaMySql技术&#xff1b;通过后台设置医院信息、录入医院科室信息、录入医生信息、设置医生排班信息、查看预约…

(附源码)计算机毕业设计SSM毕业设计管理系统

毕设帮助&#xff0c;指导&#xff0c;本源码分享&#xff0c;调试部署(见文末) 3.3功能需求分析 本系统采用从上往下的步骤开发&#xff0c;基本功能如下&#xff1a; 本课题要求实现一套毕业设计管理系统&#xff0c;系统主要包括&#xff08;管理员&#xff0c;教师和学生&a…

python-pyecharts基础知识

资料来源&#xff1a;2022新版黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了_哔哩哔哩_bilibili 折线图 地图 动态GDP增长图 补充知识&#xff1a; json 1&#xff09;JSON是一种轻量级的数据交互格式。可以按照JSON指定的格式去…

群晖Docker套件注册Harbor私有镜像仓库,并下载运行自己发布的Docker镜像

[群晖Docker套件注册Harbor私有镜像仓库&#xff0c;并下载运行自己发布的Docker镜像] 在进行微服务开发时&#xff0c;一些基础服务组件&#xff08;Nacos、Redis、Mysql&#xff09;的运行以及越来越多的业务服务组件的开发&#xff0c;会导致开发者电脑的内存资源紧张&#…

Android:玩转Jetpack Compose之MVI架构——基类中使用页面UiState

系列文章目录 架构一&#xff08;MVP&#xff09;&#xff1a;Android:玩转RetrofitOkHttpKotlin协程 网络请求架构 架构二&#xff08;MVVM&#xff09;&#xff1a;Android:玩转网络请求架构 RetrofitKotlin协程简单使用(MVVM架构模式) 架构三&#xff08;MVI&#xff09;&a…

吴恩达machine-learning-specialization2022第1周的optional lab

1. 使用python和numpy实现一个线性回归 要求使用梯度下降法&#xff0c;可视化losslossloss随着迭代次数的变化曲线 2. 说明 2.1 拟合函数 fw,b(x(i))wx(i)bf_{w,b}(x^{(i)})wx^{(i)}bfw,b​(x(i))wx(i)b 2.2 均方误差损失函数 J(w,b)12m∑i0m−1(fw,b(x(i))−y(i))2J(w,b)…

【云原生丨Kubernetes系列15】创建 ConfigMap 资源对象

前言 前⾯我们深入学习了 Servie 的使⽤&#xff0c; Service 是 Kubernetes 系统中⾮常重要的⼀个核⼼概念&#xff0c;这节课我们来学习另外⼀个⾮常重要的资源对象&#xff1a; ConfigMap 文章目录前言引入创建引入 应用部署的一个最佳实践是将应用所需的配置信息与程序进行…

【ML13】overfitting and underfitting 过拟合与欠拟合

过拟合与欠拟合过拟合与欠拟合概念过拟合解决办法解决办法一&#xff1a;在训练集中加入更多数据解决办法二&#xff1a;优化数据集 feature selection解决方法三&#xff1a;正则化 Regularization正则化线性回归Recape of Cost Function of Linear RegressionAdd the regular…

算法刷题:可交换的连续最大和

目录前言1. 题目描述2. 题目分析3. 代码实现4. 运行测试后记前言 好久没有做题了&#xff0c;前两天做了一道题&#xff0c;感觉还比较有意思&#xff0c;来分享一下。想学习&#xff0c;但是自己实在是懒&#xff0c;懒癌怎么治&#xff1f;期待着自己彻底奋发图强那一天。 …

【Ubuntu】常用软件下载与安装汇总

前言 发现很多诸如Detectron2的开源项目官方仅提供Liunx系统的安装方式&#xff0c;于是愤而将工作机系统换成了Ubuntu20.04&#xff0c;下面记录一些常用软件的安装方式&#xff0c;以便再次换机时能快速迁移&#xff0c;后续装新的软件会持续更新。 安装yum 直接安装会报错…

潜伏在ISP网络中数月的新黑客组织“Metador”

研究人员称之为“Metador”的一个以前未知的威胁因素已经入侵电信、互联网服务提供商(ISP)和大学大约两年了。 Metador的目标是中东和非洲的组织&#xff0c;他们的目的似乎是长期坚持间谍活动。该组织使用了两种基于Windows的恶意软件&#xff0c;它们被描述为“极其复杂”&a…

JavaScript:BOM

目录 一、BOM介绍 1、BOM的构成 二、window对象常用方法 1、窗口加载事件 2、window.onresize 3、confirm()方法 4、open()方法 5、setTimeout()定时器 6、this的使用 7、JS是单线程 8、JS执行机制 9、URL 10、location对象的属性 11、document对象 12、Date对象…

(附源码)计算机毕业设计ssm办公自动化系统

毕设帮助&#xff0c;指导&#xff0c;本源码分享&#xff0c;调试部署(见文末) 3.3系统流程和逻辑 系统业务流程图&#xff0c;如图所示&#xff1a; 图3-1登录流程图 图3-2添加信息流程图 图3-3注册信息流程图 4.1 概述 办公自动化系统基于Web服务模式&#xff0c;是一个适…

实训十七:交换机单端口环路检测配置

一、实验目的 1、了解单端口环路检测的作用 2、熟悉单端口环路检测的配置 二、 应用环境 1、针对网络中存在用户自行架设的 HUB 设备可能导致的环路&#xff0c;在交换机设备上运行单端 口环路检测以防止由于 HUB 连线失误导致的网络环路。 三、 实验设备 1、 DCN-CS6200 …