Webpack详解

Webpack

   Webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。它允许开发者将项目中的资源(如 JavaScript、CSS、图片等)视为模块,通过分析和处理这些模块之间的依赖关系,将它们打包成一个或多个 bundle(捆绑包),这些 bundle 可以在浏览器中加载和执行。Webpack 提高了开发效率,简化了前端项目的构建流程,是现代前端开发不可或缺的工具之一。

Why Webpack?

Webpack通过提供模块化开发、依赖管理、资源优化、开发便捷性、易于集成、构建流程标准化和支持多种目标等特性,极大地提高了前端开发的效率和项目的可维护性。

使用Webpack有多个重要原因,这些原因主要涉及到前端开发中的效率、模块化、依赖管理、资源优化等方面。以下是使用Webpack的几个关键理由:

  1. 模块化开发
    Webpack支持ES6模块化语法以及CommonJS、AMD等模块化标准,使得开发者能够以模块化的方式组织代码。这有助于代码的可维护性、可重用性和可扩展性。通过将代码分割成多个模块,开发者可以更容易地理解和维护大型项目。

  2. 依赖管理
    Webpack能够自动分析项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的扩展语言(如SCSS, TypeScript等),并将其转换和打包为合适的格式供浏览器使用。它还能智能地处理模块之间的依赖关系,确保它们按照正确的顺序加载和执行。

  3. 资源优化
    Webpack提供了丰富的loader和plugin,可以对项目中的资源进行各种优化处理。例如,通过Babel loader可以将ES6代码转换为兼容当前浏览器的ES5代码;通过CSS loader和style loader可以将CSS文件注入到DOM中;通过UglifyJSPlugin可以对打包后的文件进行压缩,减少文件体积,加快加载速度。

  4. 开发便捷性
    Webpack提供了开发服务器(webpack-dev-server)和热模块替换(HMR)等功能,使得开发者在开发过程中能够实时预览更改,而无需手动刷新浏览器。这大大提高了开发效率,减少了重复性工作。

  5. 易于集成
    Webpack易于与其他工具和库集成,如React、Vue、Angular等前端框架,以及ESLint、Prettier等代码质量工具。这使得开发者可以在一个统一的构建系统中完成项目的构建、测试、部署等流程。

  6. 构建流程标准化
    使用Webpack可以标准化项目的构建流程,无论是小型项目还是大型项目,都可以通过配置文件来定义项目的构建规则。这使得团队成员能够更容易地理解和参与项目的构建过程,提高了团队协作的效率。

  7. 支持多种目标
    Webpack不仅可以用于构建浏览器端的应用,还可以通过适当的配置和插件,支持Node.js环境下的服务器端渲染(SSR)、Electron桌面应用等多种目标。这使得Webpack成为了一个非常灵活和强大的构建工具。

工作原理

Webpack 的工作原理可以概括为以下几个主要步骤:

  1. 初始化参数:Webpack 从配置文件(如 webpack.config.js)和命令行参数中读取和合并配置,确定最终的打包参数。

  2. 开始编译:使用上一步得到的参数初始化 Compiler 对象,并加载所有配置的插件。Compiler 对象执行 run 方法,开始执行编译过程。

  3. 确定入口:根据配置文件中的 entry 字段找出所有的入口文件。这些入口文件是 Webpack 打包的起点。

  4. 编译模块:从入口文件开始,Webpack 会递归地分析每个模块的依赖,并使用配置的 Loader 对这些模块进行翻译和转换。Loader 是一种转换器,可以将各种资源(如 CSS、图片等)转换为 Webpack 能够处理的模块。

  5. 完成模块编译:在所有的模块都被 Loader 转换后,Webpack 会得到每个模块的最终内容和它们之间的依赖关系图。

  6. 输出资源:Webpack 根据入口和模块之间的依赖关系,将模块组合成一个个包含多个模块的 Chunk(代码块)。每个 Chunk 可以是一个独立的文件,也可以被组合成最终的 bundle。然后,Webpack 将这些 Chunk 转换成单独的文件,并加入到输出列表中。

  7. 输出完成:最后,Webpack 根据配置确定输出的路径和文件名,将文件内容写入到文件系统中。

 简单的说就是分析代码,找到“require”、“exports”、“define”等关键词,并替换成对应模块的引用。 在一个配置文件中,指明对某些文件进行编译、压缩、组合等任务。把你的项目当成一个整体,通过一个给定的主文件 (index.js),webpack将从这个文件开始找到你的项目的所有的依赖文件,使用loaders处理他们,最后打包为一个浏览器可以识别的js文件。

基本能力

处理依赖

     方便引用第三方模块,让模块更容易复用、避免全局注入导致的冲突、避免重复加者加载不必要的模块载。

   Webpack通过读取入口文件、解析文件并生成AST、遍历AST并处理依赖、构建依赖图、打包输出等步骤来处理项目中的依赖,并最终生成可供浏览器或Node.js环境运行的bundle文件。这一过程充分利用了AST的抽象能力,使得Webpack能够准确地理解和处理复杂的项目依赖关系。

1. 初始化与配置
  • Webpack从配置文件(如webpack.config.js)中读取配置信息,包括入口文件(entry)、输出配置(output)、模块规则(module rules)等。
  • 根据配置信息,Webpack初始化一个Compiler对象,这个对象将控制整个构建过程。
2. 读取入口文件
  • Webpack从配置的入口文件开始,读取这个文件的内容。
3. 解析入口文件并生成AST
  • 使用Webpack内置的解析器或配置的loader(如babel-loader)对入口文件进行解析。
  • 解析过程中,源码会经过词法分析(Lexical Analysis)和语法分析(Syntax Analysis)两个阶段,最终生成AST。
    • 词法分析:将源代码字符串转换为一系列标记(tokens)的集合。
    • 语法分析:使用这些标记来构建AST,AST是一个树状结构,表示了源代码的语法结构。
4. 遍历AST并处理依赖
  • Webpack使用遍历器(如Babel的@babel/traverse)来遍历AST。
  • 在遍历过程中,Webpack会识别出所有的依赖声明(如importrequire语句)。
  • 对于每个依赖,Webpack会递归地执行上述步骤(读取文件、解析文件、生成AST、遍历AST并处理依赖),直到所有依赖都被处理完毕。
5. 依赖图构建
  • 通过上述递归过程,Webpack会构建一个依赖图(Dependency Graph),这个图表示了项目中所有模块之间的依赖关系。
6. 打包输出
  • 在依赖图构建完成后,Webpack会根据配置中的输出配置,将项目中的所有模块打包成一个或多个bundle文件。
  • 这些bundle文件包含了项目的所有代码,并且已经通过loader进行了必要的转换和优化。
7. 插件介入
  • 在Webpack的构建过程中,还可以通过插件(Plugins)来介入和修改构建流程。
  • 插件可以在Webpack生命周期的不同阶段执行自定义的逻辑,如打包优化、资源管理等。
模块化

前端模块化-webpack打包工具-CSDNVue入门技能树

AMD、CMD、CommonJs的优缺点,区别?_amd cmd的优劣势-CSDN博客

CommonJS模块
//moduleA.js
// 导出变量  
module.exports.name = 'Alice';  // 或者导出函数  
function sayHello() {  return 'Hello, CommonJS!';  
}  
module.exports.sayHello = sayHello;//main.JS
// 导入moduleA模块  
const moduleA = require('./moduleA');  console.log(moduleA.name); // 输出: Alice  
console.log(moduleA.sayHello()); // 输出: Hello, CommonJS!

优点

  1. 简单易用:CommonJS的模块系统相对简单,易于理解和使用。
  2. 支持服务器端:Node.js等服务器端JavaScript环境广泛支持CommonJS。
  3. 丰富的生态系统:npm等包管理工具为CommonJS模块提供了丰富的第三方库和工具。

缺点

  1. 同步加载:CommonJS模块是同步加载的,这在服务器端通常不是问题,但在浏览器端可能会导致性能问题。因此,在浏览器端使用CommonJS模块时,通常需要通过打包工具(如Webpack)进行转换和优化
  2. 浏览器兼容性:浏览器默认不支持CommonJS模块系统,需要通过工具进行转换才能在浏览器中使用。
ES6模块
// 导出变量和函数  
export let name = 'Alice';  
export function sayHello() {  console.log('Hello, ES6 Modules!');  
}  // 默认导出  
export default function createGreeting(name) {  return `Hello, ${name}!`;  
}
----------------------------------------------
// 导入具名导出的变量和函数  
import { name, sayHello } from './moduleA.js';  console.log(name); // 输出: Alice  
sayHello(); // 输出: Hello, ES6 Modules!  // 导入默认导出的函数,并重命名  
import createGreeting as greet from './moduleB.js';  console.log(greet('Bob')); // 输出: Hello, Bob!
打包
  •     各种loader与插件:loader加载各种资源、babel把ES6+转化为ES5-,eslint可以检查编译时的各种错误。

//常见loader
1. css-loader & style-loader
{  test: /\.css$/,  use: ['style-loader', 'css-loader']  
}
2. less-loader & sass-loader
{  test: /\.s[ac]ss$/i,  use: ['style-loader', 'css-loader', 'sass-loader']  
}
3.babel-loader
{  test: /\.(js|jsx)$/,  exclude: /node_modules/,  use: {  loader: 'babel-loader',  options: {  presets: ['@babel/preset-env']  }  }  
}
4.file-loader & url-loader
{  test: /\.(png|jpe?g|gif)$/i,  use: [  {  loader: 'url-loader',  options: {  limit: 8192, // 小于8KB的图片会被base64处理  outputPath: 'images/' // 输出目录  }  }  ]  
}
5. ts-loader & awesome-typescript-loader
{  test: /\.tsx?$/,  use: 'ts-loader',  exclude: /node_modules/  
}
  •    合并代码:把各个分散的模块集中打包成大文件,减少HTTP的链接的请求次数,配合uglify.js可以减少、优化代码的体积
  • 分块(好渲染)

打包中常见核心概念

摇树

  Tree-shaking 它的名字来源于通过摇晃(shake)JavaScript代码的抽象语法树(AST),是一种用于优化JavaScript代码的技术,主要用于移除未被使用的代码,使得最终生成的代码包含应用程序中实际使用的部分。

Webpack摇树VS Vite摇树 

摇树失败原因

1、代码引入没用import(ES6)

使用了CommonJS模块化规范

  • CommonJS采用require()module.exports进行模块导入导出,这种方式是动态导入且同步加载的,无法在编译时确定所依赖的模块,因此Webpack在进行摇树时可能会忽略这些模块。

必须用 import 导入,导出用 esm 或者 commonjs 都行

2、代码没开启摇树

  • 在Webpack的optimization配置中,需要设置usedExportstrue来标记无用代码。此外,还需要配合代码压缩插件(如terser-webpack-plugin)来移除这些无用代码。


3、副作用(sideEffects)

  • webpack.config.js中设置sideEffectstrue时,Webpack会检查第三方包的package.json中的sideEffects字段。如果设置不当或Webpack无法准确判断代码中是否存在副作用,则可能导致摇树失败。

  • 代码存在副作用(修改全局变量、修改外部作用域的行为)等副作用会导致Webpack无法安全地移除未使用的代码,因为这些代码可能会对外部产生影响。

4、babel配置preset-env没写module:false参数码没用import引入

  • 使用babel-loader时,如果配置了@babel/preset-env且未禁用ESM到CommonJS的转换,可能会导致Webpack拿到的是以CommonJS组织的代码,从而无法进行摇树。

Chunk

webpack的本质是把多个js模块合并到一个js中,即一个入口得到一个输出js文件(bundle.js)。但是导致的问题是,如果这个bundle.js文件很大,那么浏览器请求的时候,导致请求时间很长,首屏长时间白屏。所以优化手段就是把bundle.js文件拆分成多个小的js文件,同时请求,首屏当然就更快渲染显示。所以入口文件,chunk文件,输出文件三者的关系从原来的一个入口文件对应一个chunk最后输出一个bundle文件改变为一个入口文件对应多个chunk最后输出多个bundle文件

获得Chunk方法 

在Webpack中,一个"chunk"通常指的是构建过程中生成的一个或多个bundle(即打包后的文件)。这些chunks可以包含应用程序的代码、第三方库、懒加载的代码块等。了解如何获取或操作这些chunks对于进行代码分割、懒加载优化等场景非常有用。

1. 运行时获取chunks

在客户端(浏览器)中,Webpack提供了__webpack_require__.e函数来动态加载(即懒加载)chunks。但直接获取已加载或可用的chunks列表在运行时通常不是Webpack的直接功能,因为这取决于你的代码分割策略和懒加载逻辑。

然而,你可以通过一些间接的方式来获取关于chunks的信息,比如:

  • 通过Webpack的manifest文件:Webpack可以生成一个manifest文件,它包含了关于各个chunk的元数据(如文件名、包含的模块等)。虽然这不是直接在客户端运行时获取,但你可以在构建过程中解析这个文件来获取chunks的信息。

  • 使用Webpack的Stats对象:在构建过程中,你可以通过Webpack的stats对象来获取关于构建结果的详细信息,包括chunks的信息。这通常用于构建后分析或优化。

2. 构建时获取chunks

在Webpack的构建过程中,你可以通过Webpack的API或插件来访问和修改chunks。这通常是通过编写Webpack插件来完成的,因为Webpack插件可以访问到Webpack的编译(compilation)和构建(compilation.hooks)过程。

例如,你可以编写一个Webpack插件,监听compilation.hooks.additionalChunkAssetscompilation.hooks.optimizeChunkAssets等钩子,以获取或修改chunks。

class MyPlugin {  apply(compiler) {  compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {  const chunks = compilation.chunks;  chunks.forEach(chunk => {  console.log(`Chunk name: ${chunk.name}`);  console.log(`Chunk files: ${chunk.files}`);  // 这里可以进一步处理chunks  });  callback();  });  }  
}  module.exports = MyPlugin;

热更新

  Webpack热更新(Hot Module Replacement,简称HMR)是Webpack提供的一种在开发过程中实现模块动态替换和更新的功能,而无需刷新整个页面。这种技术能够极大地提升开发效率,允许开发者在保持应用状态的同时,实时预览修改的效果。

一、热更新的基本原理
  1. 启动Webpack开发服务器
    • 当启动Webpack开发服务器(如webpack-dev-server)时,会创建一个WebSocket或轮询连接,用于与浏览器建立通信通道。
    • 开发服务器通常将打包后的文件存储在内存中,以提高访问速度。
  2. 捕获模块变化
    • 使用Webpack的热更新插件(如HotModuleReplacementPlugin)来捕获模块的变化。
    • 当源代码文件发生变化时,Webpack会重新编译这些文件,并生成新的模块。
  3. 生成更新补丁
    • Webpack将变化的模块及其依赖模块打包成一个或多个更新补丁(update chunk)。
    • 这些补丁包含了模块的新代码和必要的元数据。
  4. 发送更新补丁
    • 通过之前建立的WebSocket或轮询连接,Webpack将更新补丁发送给浏览器。
  5. 浏览器接收并处理更新补丁
    • 浏览器接收到更新补丁后,使用热更新的运行时(Hot Module Replacement Runtime)来解析和处理这些补丁。
    • 运行时根据更新补丁对模块进行动态替换和更新,同时尽可能地保持应用的状态。
二、热更新的优势
  • 快速反馈:开发者可以在修改代码后立即看到修改效果,无需手动刷新页面。
  • 保持应用状态:在模块替换过程中,应用的状态得以保留,开发者可以继续与应用进行交互。
  • 提高开发效率:减少了调试和错误修复的时间,提升了开发效率。

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

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

相关文章

Python酷库之旅-第三方库Pandas(024)

目录 一、用法精讲 61、pandas.to_numeric函数 61-1、语法 61-2、参数 61-3、功能 61-4、返回值 61-5、说明 61-6、用法 61-6-1、数据准备 61-6-2、代码示例 61-6-3、结果输出 62、pandas.to_datetime函数 62-1、语法 62-2、参数 62-3、功能 62-4、返回值 62-…

ospf的MGRE实验

第一步:配IP [R1-GigabitEthernet0/0/0]ip address 12.0.0.1 24 [R1-GigabitEthernet0/0/1]ip address 21.0.0.1 24 [R1-LoopBack0]ip address 192.168.1.1 24 [ISP-GigabitEthernet0/0/0]ip address 12.0.0.2 24 [ISP-GigabitEthernet0/0/1]ip address 21.0.0.2 24…

Hadoop3:HDFS-存储优化之纠删码

一、集群环境 集群一共5个节点,102/103/104/105/106 二、纠删码原理 1、简介 HDFS默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。Hadoop3.x引入了纠删码,采用计算的方式&#x…

新一代大语言模型 GPT-5 对工作与生活的影响及应对策略

文章目录 📒一、引言 📒二、GPT-5 的发展背景 🚀(一)GPT-4 的表现与特点 🚀(二)GPT-5 的预期进步 📒三、GPT-5 对工作的影响 🚀(一&#xf…

交叉编译ethtool(ubuntu 2018)

参考文章:https://www.cnblogs.com/nazhen/p/16800427.html https://blog.csdn.net/weixin_43128044/article/details/137953913 1、下载相关安装包 //ethtool依赖libmul git clone http://git.netfilter.org/libmnl //ethtool源码 git clone http://git.kernel.or…

OpenGL笔记十三之Uniform向量数据传输、使用glUniform3f和glUniform3fv

OpenGL笔记十三之Uniform向量数据传输、使用glUniform3f和glUniform3fv —— 2024-07-14 晚上 bilibili赵新政老师的教程看后笔记 code review! 文章目录 OpenGL笔记十三之Uniform向量数据传输、使用glUniform3f和glUniform3fv1.glUniform3f1.1.运行1.2.vs1.3.fs1.4.shader.…

科研绘图系列:R语言雨云图(Raincloud plot)

介绍 雨云图(Raincloud plot)是一种数据可视化工具,它结合了多种数据展示方式,旨在提供对数据集的全面了解。雨云图通常包括以下几个部分: 密度图(Density plot):表示数据的分布情况,密度图的曲线可以展示数据在不同数值区间的密度。箱线图(Box plot):显示数据的中…

.NET MAUI开源架构_1.学习资源分享

最近需要开发Android的App,想预研下使用.NET开源架构.NET MAUI来开发App程序。因此网上搜索了下相关资料,现在把我查询的结果记录下,方便后面学习。 1.官方文档 1.1MAUI官方学习网站 .NET Multi-Platform App UI 文档 - .NET MAUI | Micro…

leetcode简单题27 N.119 杨辉三角II rust描述

// 直接生成杨辉三角当前行 pub fn get_row(row_index: i32) -> Vec<i32> {let mut row vec![1; (row_index 1) as usize];for i in 1..row_index as usize {for j in (1..i).rev() {row[j] row[j] row[j - 1];}}row } // 空间优化的方法 pub fn get_row2(row_ind…

在Mac上免费恢复误删除的Word文档

Microsoft Word for Mac是一个有用的文字处理应用程序&#xff0c;它与Microsoft Office套件捆绑在一起。该软件的稳定版本包括 Word 2019、2016、2011 等。 Word for Mac 与 Apple Pages 兼容;这允许在不同的操作系统版本中使用Word文档&#xff0c;而不会遇到任何麻烦。 与…

springboot websocket 知识点汇总

以下是一个详细全面的 Spring Boot 使用 WebSocket 的知识点汇总 1. 配置 WebSocket 添加依赖 进入maven官网, 搜索spring-boot-starter-websocket&#xff0c;选择版本, 然后把依赖复制到pom.xml的dependencies标签中 配置 WebSocket 创建一个配置类 WebSocketConfig&…

【机器学习】机器学习与图像分类的融合应用与性能优化新探索

文章目录 引言第一章&#xff1a;机器学习在图像分类中的应用1.1 数据预处理1.1.1 数据清洗1.1.2 数据归一化1.1.3 数据增强 1.2 模型选择1.2.1 卷积神经网络1.2.2 迁移学习1.2.3 混合模型 1.3 模型训练1.3.1 梯度下降1.3.2 随机梯度下降1.3.3 Adam优化器 1.4 模型评估与性能优…

SD-WAN组网搭建5G备份方案实现方式

SD-WAN&#xff08;Software-Defined Wide Area Network&#xff0c;软件定义广域网&#xff09;结合5G作为备份链路是现代企业网络弹性策略的一部分&#xff0c;尤其是在需要高可用性和快速故障切换的场景下。以下是实现SD-WAN组网并集成5G备份方案的一般步骤&#xff1a; 1. …

Postfix+Dovecot+Roundcube开源邮件系统搭建系列1-2:系统搭建目标+MariaDB数据库配置(MySQL)

1. 系统搭建目标 通过本系列文章&#xff0c;最终可以部署一套提供如下服务的邮件系统&#xff1a; SMTP服务&#xff1a;由Postfix提供&#xff0c;监听25、465、587端口。POP3服务&#xff1a;由Dovecot提供&#xff0c;监听110、995端口。IMAP服务&#xff1a;由Dovecot提…

2024全球和国内最常用的弱密码,有没有你的?

密码管理器NordPass分析了来自公开来源的超过4.3TB 的密码数据&#xff0c;找出了当前为止&#xff08;2024年&#xff09;最常用&#xff08;最脆弱&#xff09;的密码。 这些密码主要有下面这些特征&#xff1a; 简单且常用&#xff0c;万年弱密码&#xff0c;比如123456、a…

Qt支持LG高级汽车内容平台

Qt Group与LG 电子&#xff08;简称LG&#xff09;正携手合作&#xff0c;将Qt软件框架嵌入其基于 webOS的ACPLG车载娱乐平台&#xff0c;用于应用程序开发。该合作旨在让原始设备制造商&#xff08;OEM&#xff09;的开发者和设计师能为汽车创建更具创新性的沉浸式汽车内容流媒…

Flutter应用开发:掌握StatefulWidget的实用技巧

前言 随着移动应用的日益复杂&#xff0c;状态管理成为了 Flutter 应用开发中的一项重要挑战。 状态&#xff0c;即应用中的可变数据&#xff0c;它驱动着用户界面的渲染和交互。 在 Flutter 这样的声明式 UI 框架中&#xff0c;如何高效、可维护地管理状态&#xff0c;对于…

linux环境安装mongoDB

一、安装单体mogodb 目标&#xff1a;在Linux中部署一个单机的MongoDB&#xff0c;作为生产环境下使用。 提示&#xff1a;和Windows下操作差不多。 步骤如下&#xff1a; &#xff08;1&#xff09;先到官网下载压缩包 mongod-linux-x86_64-4.0.10.tgz 。 &#xff08;2&…

WEB前端06-BOM对象

BOM浏览器对象模型 浏览器对象模型&#xff1a;将浏览器的各个组成部分封装成对象。是用于描述浏览器中对象与对象之间层次关系的模型&#xff0c;提供了独立于页面内容、并能够与浏览器窗口进行交互的对象结构。 组成部分 Window&#xff1a;浏览器窗口对象 Navigator&…

【STC89C51单片机】定时器中断系统

中断概念 中断是一种重要的硬件机制&#xff0c;用于在处理器正在执行程序时&#xff0c;能够及时响应某些外部或内部事件。中断可以临时中止当前正在执行的指令序列&#xff0c;转而去执行专门的中断服务程序&#xff08;ISR&#xff0c;Interrupt Service Routine&#xff0…