【读书笔记】《深入浅出Webpack》

Webpack版本

分析版本为3.6.0
4.0为最近升级的版本,与之前版本变化较大,编译输出的文件与3.0版本会不一致,目前项目中使用的版本3.0版本,所以基于3.0版本进行分析学习。

Webpack构建流程

  • 初始化:启动构建,读取与合并配置参数,加载Plugin,实例化Complier
  • 编译:从Entry发出,针对每个Module串行调用对应的Loader去转换文件内容,再找到该Module依赖的Module,递归进行编译处理。
  • 输出:对编译后对Module组合成Chunk,把Chunk转换成文件,输出到文件系统。

输出文件分析

原输出文件结构:

简化后的文件结构:

(function(modules) {// 模拟 require 语句function __webpack_require__() {}// 执行存放所有模块数组中的第0个模块__webpack_require__(0);
})([/*存放所有模块的数组*/])

分割代码时输出

当使用按需加载加载文件时,Webpack的输出文件会发生变化。

// 异步加载 show.js
import('./show').then((show) => {// 执行 show 函数show('Webpack');
});

重新构建后会输出两个文件,分别是执行入口文件bundle.js和异步加载文件0.bundle.js
异步加载文件默认输入的文件名为 [id].js,可以在Webpack配置文件的output项中配置输出文件名
其中0.bundle.js内容如下:

// 加载在本文件(0.bundle.js)中包含的模块
webpackJsonp(// 在其它文件中存放着的模块的 ID[0],// 本文件所包含的模块[// show.js 所对应的模块(function (module, exports) {function show(content) {window.document.getElementById('app').innerText = 'Hello,' + content;}module.exports = show;})]
);

bundle.js内容如下:

(function (modules) {/**** webpackJsonp 用于从异步加载的文件中安装模块。* 把 webpackJsonp 挂载到全局是为了方便在其它文件中调用。** @param chunkIds 异步加载的文件中存放的需要安装的模块对应的 Chunk ID* @param moreModules 异步加载的文件中存放的需要安装的模块列表* @param executeModules 在异步加载的文件中存放的需要安装的模块都安装成功后,需要执行的模块对应的 index*/window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {// 把 moreModules 添加到 modules 对象中// 把所有 chunkIds 对应的模块都标记成已经加载成功 var moduleId, chunkId, i = 0, resolves = [], result;for (; i < chunkIds.length; i++) {chunkId = chunkIds[i];if (installedChunks[chunkId]) {resolves.push(installedChunks[chunkId][0]);}installedChunks[chunkId] = 0;}for (moduleId in moreModules) {if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {modules[moduleId] = moreModules[moduleId];}}while (resolves.length) {resolves.shift()();}};// 缓存已经安装的模块var installedModules = {};// 存储每个 Chunk 的加载状态;// 键为 Chunk 的 ID,值为0代表已经加载成功var installedChunks = {1: 0};// 模拟 require 语句,和上面介绍的一致function __webpack_require__(moduleId) {// ... 省略和上面一样的内容}/*** 用于加载被分割出去的,需要异步加载的 Chunk 对应的文件* @param chunkId 需要异步加载的 Chunk 对应的 ID* @returns {Promise}*/__webpack_require__.e = function requireEnsure(chunkId) {// 从上面定义的 installedChunks 中获取 chunkId 对应的 Chunk 的加载状态var installedChunkData = installedChunks[chunkId];// 如果加载状态为0表示该 Chunk 已经加载成功了,直接返回 resolve Promiseif (installedChunkData === 0) {return new Promise(function (resolve) {resolve();});}// installedChunkData 不为空且不为0表示该 Chunk 正在网络加载中if (installedChunkData) {// 返回存放在 installedChunkData 数组中的 Promise 对象return installedChunkData[2];}// installedChunkData 为空,表示该 Chunk 还没有加载过,去加载该 Chunk 对应的文件var promise = new Promise(function (resolve, reject) {installedChunkData = installedChunks[chunkId] = [resolve, reject];});installedChunkData[2] = promise;// 通过 DOM 操作,往 HTML head 中插入一个 script 标签去异步加载 Chunk 对应的 JavaScript 文件var head = document.getElementsByTagName('head')[0];var script = document.createElement('script');script.type = 'text/javascript';script.charset = 'utf-8';script.async = true;script.timeout = 120000;// 文件的路径为配置的 publicPath、chunkId 拼接而成script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";// 设置异步加载的最长超时时间var timeout = setTimeout(onScriptComplete, 120000);script.onerror = script.onload = onScriptComplete;// 在 script 加载和执行完成时回调function onScriptComplete() {// 防止内存泄露script.onerror = script.onload = null;clearTimeout(timeout);// 去检查 chunkId 对应的 Chunk 是否安装成功,安装成功时才会存在于 installedChunks 中var chunk = installedChunks[chunkId];if (chunk !== 0) {if (chunk) {chunk[1](new Error('Loading chunk ' + chunkId + ' failed.'));}installedChunks[chunkId] = undefined;}};head.appendChild(script);return promise;};// 加载并执行入口模块,和上面介绍的一致return __webpack_require__(__webpack_require__.s = 0);
})
(// 存放所有没有经过异步加载的,随着执行入口文件加载的模块[// main.js 对应的模块(function (module, exports, __webpack_require__) {// 通过 __webpack_require__.e 去异步加载 show.js 对应的 Chunk__webpack_require__.e(0).then(__webpack_require__.bind(null, 1)).then((show) => {// 执行 show 函数show('Webpack');});})]
);

这里的 bundle.js 和上面所讲的 bundle.js 非常相似,区别在于:

  • 多了一个 webpack_require.e 用于加载被分割出去的,需要异步加载的 Chunk 对应的文件;
  • 多了一个 webpackJsonp 函数用于从异步加载的文件中安装模块。

参考

深入浅出WebPack

转载于:https://www.cnblogs.com/GeniusLyzh/p/8823749.html

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

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

相关文章

《JAVA与模式》之桥梁模式

在阎宏博士的《JAVA与模式》一书中开头是这样描述桥梁&#xff08;Bridge&#xff09;模式的&#xff1a; 桥梁模式是对象的结构模式。又称为柄体(Handle and Body)模式或接口(Interface)模式。桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation)脱耦&#xff0…

LABLEME UPDATE DAMOD

Labelme的改进——海量图片的自动标注 深度学习一般需要对大量的图片进行标注&#xff0c;但是手动标注耗时耗力&#xff0c;所以模仿labelme软件的功能&#xff0c;使用程序对大批量的图片进行自动标注&#xff0c;大大减少手动操作。下面介绍如何实现对大批量的图片进行标…

Java基础教程:面向对象编程[2]

Java基础教程&#xff1a;面向对象编程[2] 内容大纲 访问修饰符 四种访问修饰符 Java中&#xff0c;可以使用访问控制符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。 default (即缺省&#xff0c;什么也不写&#xff09;: 在同一包内可见&#xff…

【javascript】异步编年史,从“纯回调”到Promise

异步和分块——程序的分块执行 一开始学习javascript的时候&#xff0c; 我对异步的概念一脸懵逼&#xff0c; 因为当时百度了很多文章&#xff0c;但很多各种文章不负责任的把笼统的描述混杂在一起&#xff0c;让我对这个 JS中的重要概念难以理解&#xff0c; “异步是非阻塞的…

Shell编程之if语法练习(LNMP)全过程

大家好&#xff0c;我是延凯&#xff0c;本人原来在CSDN写作已经快一年了 都是相关Linux运维这方面的技术知识&#xff0c;现在搬到博客园也是我一直想的&#xff0c;本博客主要写Python&#xff0c;docker&#xff0c;shell等偏向开发云计算等知识点&#xff0c;谢谢各位&…

基于UNet和camvid数据集的道路分割

基于UNet和camvid数据集的道路分割h(1.3.0)&#xff1a; 背景 语义分割是深度学习中的一个非常重要的研究方向&#xff0c;并且UNet是语义分割中一个非常经典的模型。在本次博客中&#xff0c;我尝试用UNet对camvid dataset数据集进行道路分割&#xff0c;大致期望的效果如下&…

二分法查找和普通查找

一、普通查找 对于数组和一个需要查找的元素来说&#xff0c;普通查找的原理很简单&#xff0c;即为从数组的第一个元素到最后一个元素进行遍历&#xff0c;如果第i个元素的值等于我们需要查找的值&#xff0c;那么返回找到的角标i&#xff0c;否则返回-1表示没有查找到。这里以…

Linux下安装zookeeper集群(奇数个)

1、 解压zookeeper压缩包 2、 data里创建“myid”文件&#xff08;命令touch myid&#xff09;&#xff0c;内容是1&#xff08;命令 echo 1 >> myid&#xff09; 3、 zoo.cnf里配置dataDir、clientport、server.nIP:端口1&#xff08;2881&#xff09;&#xff1a;端…

立体标定

立体标定应用标定数据转换成深度图标定 由于摄像头目前是我们手动进行定位的&#xff0c;我们现在还不知道两张图像与世界坐标之间的耦合关系&#xff0c;所以下一步要进行的是标定&#xff0c;用来确定分别获取两个摄像头的内部参数&#xff0c;并且根据两个摄像头在同一个世…

if _name_ == _main_

1.作用 py文件有2种使用方法&#xff0c;第1是自己本脚本自己独立执行&#xff1b;第2是被import到其他文件脚本中执行. if _name_ " _main_" 该语句控制其他下一步的脚本是否执行。如果是自己本脚本独立执行&#xff0c;那就运行该if条件下的脚本&#xff1b;如果…

LLVM完整参考安装

文章目录 一、直接下载编译好的,见图片命令二、下载源代码自己编译安装 下面提供下载并mv完全的文件包三、安装LLVM编译器一、直接下载编译好的,见图片命令 这里使用llvm官网编译好的包, 直接解压即可用LLVM下载官网点击这里下载llvm-6.0.1 下载完成后解压tar -vxf clangllv…

微软正式释出基于 Chromium 的 Edge 预览版本

百度智能云域名服务&#xff0c;.com新用户首购仅需25元 微软基于 Chromium 的全新版本 Edge 一直吸引着开发者与用户的目光&#xff0c;当地时间 8 日&#xff0c;官方终于释出了第一个 Dev 和 Canary 频道构建版本。 Dev 与 Canary build 都是开发者预览版&#xff0c;同属…

下载和安装R、RStudio !

现如今&#xff0c;R语言是统计领域广泛使用的工具&#xff0c;是属于GNU系统的一个自由、免费、源代码开放的软件&#xff0c;是用于统计计算和统计绘图的优秀工具。而RStudio是R的集成开发环境&#xff0c;用它进行R编程的学习和实践会更加轻松和方便。下面就教大家如何下载并…

豆瓣首页话题输入框的实现

在做问答的时候&#xff0c;遇到一个需求&#xff0c;用户的问题需要限制字数&#xff0c;不仅显示计算的超出字数&#xff0c;还需在超出的内容上加一些提醒的效果&#xff0c;例如豆瓣首页的话题输入框&#xff0c;抽时间研究了下&#xff0c;需要考虑下面几个问题&#xff1…

pytorch 吸烟检测yolov5s

YOLOV5s 吸烟目标检测 参考学习 文章目录 本原创项目长期更新&#xff0c;旨在完成校园异常行为实时精检测&#xff0c;作到集成N次开发优化&#xff08;不止局限于调包&#xff09;为止&#xff0c;近期将不断更新如下模型数据标注文件教程。关注博主&#xff0c;Star 一下g…

JQuery的ajax函数执行失败,alert函数弹框一闪而过

先查看<form>标签是否有action属性&#xff0c;如果没有&#xff0c;并且最后<button>标签的type属性为submit‘时&#xff0c;默认提交位置就是当前页面 如果在页面右键检查&#xff0c;点击网络&#xff0c;会在开头发现这样的post包&#xff1a; 在右侧消息头处…

C#中Request.ServerVariables详细说明及代理

Request.ServerVariables("Url") 返回服务器地址Request.ServerVariables("Path_Info") 客户端提供的路径信息Request.ServerVariables("Appl_Physical_Path") 与应用程序元数据库路径相应的物理路径Request.ServerVariables("Path_Transla…

coco与voc相互转化

把LabelImg标注的YOLO格式标签转化为VOC格式标签 和 把VOC格式标签转化为YOLO格式标签 点亮&#xff5e;黑夜 2020-07-07 11:08:24 3537 已收藏 90 分类专栏&#xff1a; 19—目标检测 文章标签&#xff1a; voc yolo 版权 把LabelImg标注的YOLO格式标签转化为VOC格式标签 和…

angular中封装fancyBox(图片预览)

首先在官网下载最新版的fancyBox(一定要去最新网站&#xff0c;以前依赖的jquery版本偏低)&#xff0c;附上链接&#xff1a;http://fancyapps.com/fancybox/3/ 然后在项目中引用jquery&#xff0c;然后在引用jquery.fancybox.min.css和jquery.fancybox.min.js。 如果需要动画和…

十二省联考题解 - JLOI2019 题解

十二省联考题解 - JLOI2019 题解 两个T3的难度较大 平均代码量远大于去年省选 套路题考查居多 A 难度等级 1 $n^2$暴力可以拿到$60$分的优秀成绩 然后可以想到把区间异或转化为前缀两点异或 可以想到使用二分答案的方法可持久化Trie解决&#xff0c;但是时间复杂度为$n\log^2 (…