webpack 打包原理及流程解析,超详细!

这篇具有很好参考价值的文章主要介绍了webpack 打包原理及流程解析,超详细!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 什么是webpack?

友情提示:
a.前面会稍微有些枯燥,文字居多(建议还是过一遍),后面就劲爆了!!!

b.本文干货满满,非常详细,整理资料到发布文章耗时5个小时+,请大家耐心看

webpack打包分析,前端性能优化实践方案,webpack,前端,node.js

  • 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
  • webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。
  • 插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。
  • webpack 通过 Tapable 来组织这条复杂的生产线。 webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。 webpack 的事件流机制保证了插件的有序性,使得整个系统扩展性很好。
    webpack打包分析,前端性能优化实践方案,webpack,前端,node.js
  • 官方的说法看不太懂的,🙈🙈可以看这个:
  • 在目前的项目中,我们会有很多依赖包,webpack负责将浏览器不能识别的文件类型、语法等转化为可识别的前端三剑客(html,css,js),并在这个过程中充当组织者与优化者的角色。

2. 关键术语解析

2.1 bundle

  • Bundle(捆绑包)是指将所有相关的模块和资源打包在一起形成的单个文件。它是应用程序的最终输出,可以在浏览器中加载和执行。
  • 捆绑包通常由Webpack根据入口点(entry)和它们的依赖关系自动创建。当你运行Webpack构建时,它会根据配置将所有模块和资源打包成一个或多个捆绑包。

2.2 Chunk

  • Chunk(代码块)是Webpack在打包过程中生成的中间文件,它代表着一个模块的集合

  • Webpack 根据代码的拓扑结构和配置将模块组织成不同的代码块。每个代码块可以是一个独立的文件,也可以与其他代码块组合成一个捆绑包。

  • Webpack使用代码分割(code splitting)技术将应用程序代码拆分成更小的代码块,以便在需要时进行按需加载。这有助于减小初始加载的文件大小,提高应用程序的性能。

  • 在Webpack中,捆绑包和代码块之间存在一对多的关系。一个捆绑包可以包含多个代码块,而一个代码块也可以属于多个不同的捆绑包。这取决于Webpack配置中的拆分点(split points)和代码块的依赖关系。

  • 总结起来,bundle 是Webpack打包过程的最终输出文件,而chunk是Webpack在打包过程中生成的中间文件,用于组织和按需加载模块

3. webpack核心概念

3.1 Entry

  • 入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
  • 进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
  • 每个依赖项随即被处理,最后输出到称之为 bundles 的文件中。

3.2 Output

  • output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。
  • 基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。

3.3 Module

  • 模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。

3.4 Chunk

  • 代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。

3.5 Loader

  • loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。
  • loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。
  • 本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。

3.6 Plugin

  • loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。
  • 插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。

4. webpack 构建流程

Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程
webpack打包分析,前端性能优化实践方案,webpack,前端,node.js

  • 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。
  • 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译。
  • 确定入口:根据配置中的 entry 找出所有的入口文件。
  • 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
  • 完成模块编译:在经过第 4 步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系。
  • 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。
  • 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统
  • 在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。

5. webpack应用案例

5.1 前置条件

  • 首先检查node版本,建议使用 16.16.x 及以上版本(因为玩的是webpack 4.0+ 的版本)
  • 全局安装 => npm install webpack -g
  • 当然,也可以带版本号,如 webpack@4.4.0
  • 这里使用的是最新的(不带版本号默认安装最新版本)
  • 当然,也可以局部安装(全局可能会影响你的其它项目),5.2 步骤将会做的是局部安装

5.2 初始化项目

  • 整个空文件夹,执行npm init,然后一路回车,把回车摁烂!!!
  • 当然你也可以搞一些个性化配置,文件名,版本,描述,入口文件等等。
    webpack打包分析,前端性能优化实践方案,webpack,前端,node.js
  • 局部安装webpack:npm i webpack webpack-cli -D
  • 然后你会看到 package.json 这个鸟样:
    webpack打包分析,前端性能优化实践方案,webpack,前端,node.js

5.3 新建 webpack.config.js 配置文件(根目录)

const path = require('path');
module.exports = {    
    // 入口
    entry: path.resolve(__dirname, 'src/index.js'),    
    // 出口
    output: {        
        path: path.resolve(__dirname, 'dist'),        
        filename: 'bundle.js',        
        publicPath: './'    
    }
}
  • publicPath:指定基础路径,开发环境一般是项目的根路径,上线之后一般是CDN的路径。
  • __dirname:表示项目所在目录的根路径。

5.4 src/index.js 与 test.js

  • 新建入口文件src/index.js,随便整点代码:
const test = require('./test');
const a = 12
const b = 12
function add(x, y) {  
    return x + y
}
const c = add(a,b)
console.log(c)
test();
  • src/test.js,非主入口文件用来测试打包的
function  test(){
    console.log(2);
}

module.exports = test;

5.5 测试打包

  • package.json 下的 scripts 中添加打包命令:
"build": "webpack --mode development"
  • 这里说明一下,不加 –mode development,默认打包是生产环境,打包出来的代码会默认压缩,看不得,辣眼睛
  • 运行 npm run build,进行打包。
  • 如果不出意外的话,控制台就成功的打包了两个js文件,同时目录中会生成 dist 文件夹(出意外的话看下上面的步骤)
    webpack打包分析,前端性能优化实践方案,webpack,前端,node.js

6. 打包分析

  • 刚刚的步骤是一个非常简单的打包示例,打包后你会发现两个js文件变成了一个
  • 试运行一下,也是没问题的,如下
    webpack打包分析,前端性能优化实践方案,webpack,前端,node.js

6.1 源码分析

  • 源码实际上很好懂,代码量也不多,不妨来解读一下:
/*
 * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./src/index.js":
/*!**********************!*\
  !*** ./src/index.js ***!
  \**********************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {

eval("const test = __webpack_require__(/*! ./test */ \"./src/test.js\");\r\nconst a = 12\r\nconst b = 12\r\nfunction add(x, y) {  \r\n    return x + y\r\n}\r\nconst c = add(a,b)\r\nconsole.log(c)\r\ntest();\n\n//# sourceURL=webpack://blog/./src/index.js?");

/***/ }),

/***/ "./src/test.js":
/*!*********************!*\
  !*** ./src/test.js ***!
  \*********************/
/***/ ((module) => {

eval("function  test(){\r\n    console.log(2);\r\n}\r\n\r\nmodule.exports = test;\r\n\n\n//# sourceURL=webpack://blog/./src/test.js?");

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// 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] = {
/******/ 			// no module.id needed
/******/ 			// 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;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// 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");
/******/ 	
/******/ })()
;
  • 可以看到最简单的场景下 webpack 实现的模块加载系统非常简洁,仅仅只有60多行代码
  • 打包后的代码其实是一个立即执行函数,在Webpack打包过程中,每个模块都会被转换为一个独立的函数,并通过__webpack_modules__对象进行注册和管理。这个对象以文件路径为 key,以文件内容为 value,它包含了所有打包后的模块。
  • 当模块被引用或加载时,Webpack会使用__webpack_modules__来查找和执行相应的模块函数。通过使用__webpack_modules__,Webpack可以管理模块之间的依赖关系,并在需要时按需加载和执行模块。
  • 接着定义了一个模块加载函数 webpack_require()它接收的参数是 moduleId,其实就是文件路径。
  • 它的执行过程如下:
    • 判断模块是否有缓存,如果有则返回缓存模块的 export 对象,即 module.exports。
    • 新建一个模块 module,并放入缓存。
    • 执行文件路径对应的模块函数。
    • 执行完模块后,返回该模块的 exports 对象。
  • 其中 module、module.exports 的作用和 CommonJS 中的 module、module.exports 的作用是一样的,而 webpack_require 相当于 CommonJS 中的 require。
  • 在立即函数的最后,使用了 webpack_require() 加载入口模块。并传入了入口模块的路径 ./src/index.js。
  • 我们再来分析一下入口模块的内容:
((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
	eval("const test = __webpack_require__(/*! ./test */ \"./src/test.js\");\r\nconst a = 12\r\nconst b = 12\r\nfunction add(x, y) {  \r\n    return x + y\r\n}\r\nconst c = add(a,b)\r\nconsole.log(c)\r\ntest();\n\n//# sourceURL=webpack://blog/./src/index.js?");
})
  • 入口模块函数的参数正好是刚才所说的那三个参数(module、module.exports 、require),而 eval 函数的内容美化一下后和下面内容一样:
const test = __webpack_require__(/*! ./test */ "./src/test.js");

function test(){
    console.log(2);
}

test();

  • 将打包后的模块代码和原模块的代码进行对比,可以发现仅有一个地方发生了变化,那就是 require 变成了 webpack_require。
  • 从刚才的分析可知,webpack_require() 加载模块后,会先执行模块对应的函数,然后返回该模块的 exports 对象。
  • 而 test.js 的导出对象 module.exports 就是 test() 函数。所以入口模块能通过 webpack_require() 引入 test() 函数并执行
  • 到目前为止可以发现 webpack 自定义的模块规范完美适配 CommonJS 规范。

1. 希望本文能对大家有所帮助,如有错误,敬请指出

2. 原创不易,还请各位客官动动发财的小手支持一波(关注、评论、点赞、收藏)
3. 拜谢各位!后续将继续奉献优质好文
4. 如果存在疑问,可以私信我(主页有V)

webpack打包分析,前端性能优化实践方案,webpack,前端,node.js文章来源地址https://www.toymoban.com/news/detail-646676.html

到了这里,关于webpack 打包原理及流程解析,超详细!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Lighthouse前端性能分析工具】超详细!!!

    我们多数性能测试,基本上针对接口的性能测试,很少涉及到前端页面的性能测试。 但影响用户体验的因素除了后端接口数据的返回,还有前端页面的渲染等等。 所以我们除了在开发的过程中注意代码的质量,同时还需要专业的网站测试工具辅助,让我们知道自己的网页还

    2024年02月09日
    浏览(42)
  • JVM逃逸分析原理解析:优化Java程序性能和内存利用效率

    在Java开发中,性能和内存利用效率一直是开发者关注的焦点。为了提高Java程序的执行效率,JVM引入了逃逸分析技术。本文将详细解析JVM逃逸分析的原理,帮助读者深入理解其工作机制。 逃逸分析是一种用于确定对象在方法的生命周期内是否逃逸出方法外部范围的技术。在

    2024年01月20日
    浏览(57)
  • vue3 webpack打包流程及安装 (1)

    --------------------------------------------------------------------------------------------------------------------------------- 报错      跟着安装报错  后来查了才知道  是因为 webpack 版本有问题 安装的时候看好 webpack的版本过高  产生的错误 需要卸掉从新安装 webpack -v  查看 版本号 ------------------

    2024年02月09日
    浏览(70)
  • 前端项目优化:减少webpack打包体积

    最近自己买个云服务器,把之前搭建的webpack-vue项目进行了部署,现在项目已经成功了。 项目地址:GitHub - wjt162286793/webpack----vue: 使用webpack配置一个脚手架,对照文档,纯手打  线上地址:IAM架构资产管理系统 不过是没有经过任何优化的,虽然项目体积和业务不是很复杂,但是实际上打

    2024年01月21日
    浏览(52)
  • 【前端】webpack打包去除console.log

    需要在打包的时候,自动地去除掉所有console.log 也可以用 if(process.env.NODE_ENV === \\\'production\\\'){} 之类的条件判断包起来,打包的时候生产环境自动去掉console.log测试环境保留

    2024年02月09日
    浏览(37)
  • webpack优化前端框架性能

    提升开发体验 提升打包构建速度 减少代码体积 优化代码运行性能 提升开发体验使用 SourceMap 问题:正常情况下,开发环境不输出dist 文件 直接保存在内存中,浏览器控制台source中可以看到, 但是报错提示行数不正确,它会以打包后的行数进行提示 解释:sourceMap 可以生成源

    2024年02月15日
    浏览(43)
  • 【前端工程化面试题】使用 webpack 来优化前端性能/ webpack的功能

    这个题目实际上就是来回答 webpack 是干啥的,你对webpack的理解,都是一个问题。 (1)对 webpack 的理解 webpack 为啥提出 + webpack 是啥 + webpack 的主要功能 前端开发通常是基于模块化的,为了提高开发效率,webpack 是一个基于模块的构建工具,是一个用于 js 应用程序的静态模块

    2024年02月20日
    浏览(51)
  • 借助webpack来优化前端性能

    随着前端的项目逐渐扩大,必然会带来的一个问题就是性能 尤其在大型复杂的项目中,前端业务可能因为一个小小的数据依赖,导致整个页面卡顿甚至奔溃 一般项目在完成后,会通过 webpack 进行打包,利用 webpack 对前端项目性能优化是一个十分重要的环节 通过 webpack 优化前

    2024年02月04日
    浏览(41)
  • 如何⽤webpack 来优化前端性能

    如何⽤webpack 来优化前端性能? ⽤webpack 优化前端性能是指优化 webpack 的输出结果,让打包的最终结果在浏览器运⾏快速⾼效。 压缩代码:删除多余的代码、注释、简化代码的写法等等⽅式。可以利⽤webpack的 UglifyJsPlugin 和 ParallelUglifyPlugin 来压缩JS⽂件, 利⽤ cssnano (css-lo

    2024年02月13日
    浏览(37)
  • 前端Vue项目webpack打包部署后源码泄露解决

    前端项目使用nuxt框架(基于Vue),采用Webpack打包,部署到服务器后,进行漏洞检测。 经Webpack打包部署到服务器后,访问并打开开发者模式,在Source下出现[name]路径,内部包含(webpack)buildin文件夹。(做漏洞分析时,会认为该内容涉及源码泄露) 1.首先考虑源码泄露的问题 打

    2024年02月03日
    浏览(85)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包