首页 > 其他分享 >webpack概念

webpack概念

时间:2024-07-02 11:42:20浏览次数:21  
标签:hash 编译 chunk Webpack 概念 webpack 模块

总体

  1. 简单来说:
    Webpack 通过内部的 事件流机制 ,保证了插件的有序性
    Webpack 底层利用了 发布订阅模式,在运行过程中会广播事件
    Webpack 插件只需要监听它所关心的事件,在特定的时机对资源做处理
  2. 站在代码逻辑的角度:
    Webpack 在编译过代码程中,会触发一系列 Tapable 钩子事件
    插件需要找到相应的钩子,在上面添加自己的任务(注册事件)
    当 Webpack 构建时,插件注册的事件,会随着钩子的触发而执行

打包过程

  1. 版本一:
  • Webpack 的编译流程分为以下几个阶段
    初始化阶段(initialize):在这个阶段,Webpack 会读取配置文件,并初始化 Compiler 和 Compilation 对象。
    编译阶段(compile):在这个阶段,Webpack 会从入口文件开始,递归地分析模块之间的依赖关系,生成模块图。
    构建阶段(make):在这个阶段,Webpack 会根据模块图,将每个模块转换成一个或多个 Chunk,并生成对应的代码块。
    输出阶段(emit):在这个阶段,Webpack 会将生成的 Chunk 和代码块输出到文件系统中。
    完成阶段(done):在这个阶段,Webpack 编译完成,输出信息到控制台。
  1. 版本二:
  • 一次完整的 Webpack 打包,大致是这样的过程:
    将 cli 命令行参数与 Webpack 配置文件合并、解析得到参数对象 options,用于激活 webpack 的loader和插件
    把参数对象 options 传给 Webpack, 会创建生成 Compiler 对象,并初始化基础插件
    执行 Compiler 的 run 方法开始编译。每次执行 run 编译都会生成一个 Compilation 对象,也就是说,Compilation 对象负责一次编译过程
    触发 Compiler 的 make 方法分析入口文件,调用 compilation 的 buildModule 方法创建主模块对象
    生成入口文件 AST(抽象语法树),通过 AST 分析和递归加载依赖模块
    所有模块分析完成后,执行 compilation 的 seal 方法对每个 chunk 进行整理、优化、封装
    最后执行 Compiler 的 emitAssets 方法,把生成的文件输出到 output 的目录中
  1. 版本三:
    初始化
    webpack会将cli参数、配置文件、默认配置进行融合,形成一个最终的配置对象
    对配置的处理过程是依托yargs的三方包去合并配置
    可以简单的理解为,初始化阶段主要用于产生一个最终的配置
    构建
    chunk从入口开始分析依赖关系(形成一个chunk)
    为什么在读取内容之后要做语法分析?因为要知道该模块依赖谁,会转换成AST,对树形结构的遍历,分析里面的依赖关系,然后会把依赖记录记录在一个数组中,叫dependencies。

产生chunk assets
在经过第二步完成后,chunk中会产生一个模块列表,列表中包含了模块id和模块转换后的代码。
接下来webpack会根据配置,为chunk生成一个资源列表,即chunk assets。资源列表可以理解为生成到最终文件的文件名和文件夹。


chunk hash是根据所有chunk assets的内容生成的一个hash字符串
hash是一种算法,具体有很多分类,特点是将一个任意长度的字符串转化为一个固定长度的字符串,而且可以保证原始内容不变,产生的hash串不变。

合并chunk assets
将多个chunk的assets合并在一起,并产生一个总的hash

输出
emit阶段
webpack通过node中的fs模块,创建相应的文件,根据编译产生的总的assets,生成相应的文件。

总过程

术语

module:模块,分割的代码但愿,webpack中的模块可以是任何内容的文件,不限于js
chunk:webpack内部构件模块的块,一个chunk中包含多个模块,这些模块是从入口模块通过依赖分析得来的。
bundle:chunk构建好模块后会生成chunk的资源清单,清单中的每一项就是一个bundle,可以认为bundle就是最终生成的文件
hash:最终的资源清单所有内容联合生成的hash值
chunkhash:chunk生成的资源清单内容联合生成的hash值
chunkname:chunk的名称,默认main
id:通常指chunk的唯一编号,如果在开发环境下构建,和chunkname相同;如果是生产环境下构建,则使用一个从0开始的数字进行编号。

Hash

var hash = crypto.createHash('sha256')
                            // Use update to add data
                            .update('I love GeeksForGeeks')
  
                            // Use digest to get the hash value
                            .digest('hex');

.createHash创建一个hash实例,参数是使用何种加密算法
.update添加加密内容
.digest获得hash值,参数返回输出的类型。

如何提升 webpack 编译时期计算 hash 的速度

  1. 使用缓存:可以使用缓存来避免重复计算,提高编译速度。可以使用 Webpack 自带的缓存,也可以使用第三方插件如 hard-source-webpack-plugin。
  2. 减少文件数量:可以通过减少需要编译的文件数量来提高编译速度。可以通过忽略不必要的文件或使用 include 和 exclude 配置选项来实现。
  3. 使用更快的 hash 算法:可以使用更快的 hash 算法来提高计算速度。可以在 Webpack 配置中设置 output.hashFunction 和 output.hashDigest 来选择不同的 hash 算法和输出格式。
  4. 升级 Webpack 版本:新版本的 Webpack 可能会有更好的性能和优化。
  5. 使用多线程编译:可以使用多线程编译来提高编译速度。可以使用 thread-loader 或 happypack 来实现。

是否可以将版本号放在文件名中?

const package = require('./package.json')

const config = {
  output: {
    filename: `${package.version}.{hash}.js`
  }
}

不可以,因为每次版本号的改变,这将「导致所有缓存都失效」,而每次版本升级时,并不一定所有资源内容都会进行变更。

hash 是如何生成的

基于模块内容以及一系列元信息生成摘要信息

_initBuildHash(compilation) {
  const hash = createHash(compilation.outputOptions.hashFunction);
  if (this._source) {
    hash.update("source");
    this._source.updateHash(hash);
  }
  hash.update("meta");
  hash.update(JSON.stringify(this.buildMeta));
  this.buildInfo.hash = /** @type {string} */ (hash.digest("hex"));
}

SplitChunksPlugin和CommonChunksPlugin

  1. SplitChunksPlugin 插件是用来提取公共模块的,它的原理是将多个入口 chunk 中相同的模块提取出来,形成一个单独的 chunk。这样可以避免代码重复,减小打包后的文件体积,同时也可以利用浏览器的缓存机制,提高页面加载速度。
  2. SplitChunksPlugin 插件只能处理异步模块(即通过 import() 或动态导入语法加载的模块)。如果需要处理同步模块,可以使用另一个插件:CommonsChunkPlugin。
  3. 在 Webpack 4 中,CommonsChunkPlugin 插件已经被废弃,取而代之的是 optimization.splitChunks 配置选项。该选项使用了更先进的算法来提取公共模块

常见的插件

tree-shaking

tree-shaking 是通过静态代码分析来实现的。它的原理是基于 ES6 模块化规范中的静态特性,即模块的导入和导出关系是确定的,可以在编译时确定。
当 Webpack 进行打包时,会从入口模块开始,递归地分析模块之间的依赖关系,生成模块图。在这个过程中,Webpack 会标记每个模块中导出的变量和函数,并且会记录它们被哪些模块导入和使用。
在生成代码时,Webpack 会根据这些信息,将没有被使用的变量和函数从打包结果中删除。这个过程就是 tree-shaking。
需要注意的是,tree-shaking 只能删除没有被使用的代码,而不能删除被使用的但没有被导出的代码。

  1. tree-shaking生效前提:
    使用 ES6 模块化规范进行开发。
    在配置文件中开启 optimization.usedExports 选项。
    在生产环境中使用 UglifyJS 等工具进行代码压缩。
    只能处理静态的 import 和 export 语句,无法处理动态的导入语句(例如 import())。

Webpack 编译速度优化

  1. 使用持久化缓存:Webpack 4 引入了持久化缓存,可以将缓存数据保存到磁盘上,从而避免在每次重新启动 Webpack 时都需要重新生成缓存。可以通过在 webpack.config.js 中配置 cache.type 和 cache.cacheDirectory 来启用持久化缓存。
  2. 使用多进程并行编译:Webpack 5 引入了多进程并行编译的功能,可以在多个进程中同时编译不同的模块,从而提高编译速度。可以通过在 webpack.config.js 中配置 parallelism 和 minimizer.parallelism 来启用多进程并行编译。
  3. 启用模块热替换(HMR):模块热替换是一种开发时的优化技巧,可以在代码修改后只重新编译修改的模块,从而提高开发效率。可以通过在 webpack.config.js 中配置 devServer.hot 和 plugins 来启用模块热替换。
  4. 使用缓存插件:Webpack 有一些插件可以帮助优化缓存,例如 hard-source-webpack-plugin 和 cache-loader。hard-source-webpack-plugin 可以在编译过程中使用硬盘缓存来加速编译,而 cache-loader 可以在每个 loader 上使用缓存来避免重复编译。
  5. 避免使用绝对路径:在 Webpack 中,使用绝对路径会导致缓存失效,因为不同的机器上的绝对路径可能不同。可以使用相对路径来避免这个问题。
  6. 避免使用动态导入语句:在 Webpack 中,使用动态导入语句会导致缓存失效,因为无法确定导入的模块和变量。可以使用静态导入语句来避免这个问题。

标签:hash,编译,chunk,Webpack,概念,webpack,模块
From: https://www.cnblogs.com/lyly96720/p/18279609

相关文章

  • 孟德尔随机化基础概念
    孟德尔随机化(MendelianRandomization,MR)是一种利用基因型信息作为工具变量评估暴露与结果之间因果关系的统计方法。一般步骤:单核苷酸多样性(singlenucleotidepolymorphism,SNP):主要是指在基因组水平上由单个核苷酸的变异所引起的DNA序列多样性选择的MR分析方法包括:逆方差加......
  • 【C语言入门】C语言入门:探索编程世界的基础概念
    ......
  • 树的基本概念
    树的基本概念树是一种重要的非线性数据结构,在计算机科学和许多实际应用中具有广泛的应用。树的基本概念包括树的定义、基本术语、树的性质和树的类型等。一、树的定义树(Tree)是n(n≥0)个节点的有限集合。对于任意一个非空树:有且仅有一个称为根(Root)的节点。当n>1时,其余节点......
  • 反射的概念和使用
    反射的概念 反射是框架设计的灵魂,就是在类运行期间把类中成员抽取为其他类的过程为什么使用反射反射就是为了解决在运行期间对某个实例一无所知的情况下调用其方法和属性获取class反射类的三种方式一、通过类名.class属性Class<泛型>命名=类名.class;二、通......
  • Spring的AOP概念详解
    AOP详解:1.介绍:面向切面编程,是一种将非业务代码与业务代码进行分离的一种思想,在实际开发中,往往有许多重复操作,例如事务提交,权限验证,保存口志等功能需要在业务代码重复调用,面向切面编程,就是将非业务代码进行抽取,然后在不修改原来代码的前提下,为我们的业务代码,添加额......
  • 【408考点之数据结构】排序的基本概念
    排序的基本概念排序是计算机科学中的一个基本操作,目的是将一组无序的数据元素按照特定的顺序排列起来。排序在数据管理、检索和分析中有着广泛的应用,能够提高数据处理的效率和准确性。1.排序的定义排序(Sorting)是指将一组记录按某个关键字或多个关键字的大小关系进行排列......
  • 法律硕士联考-刑罚的概念和目的-刑罚的目的
    ......
  • webpack内置插件
    所有的webpack内置插件都作为webpack的静态属性存在的,使用下面的方式即可创建一个插件对象constwebpack=require("webpack")newwebpack.插件名(options)DefinePlugin全局常量定义插件,使用该插件通常定义一些常量值,例如:newwebpack.DefinePlugin({PI:`Math.PI`,/......
  • 06-6.1.1 图的基本概念
    ......
  • JAVA类与对象的基础概念(JAVA基础)
    类的定义1.定义:类可以看做是一个模版,或者图纸,系统根据类的定义来造出对象2.属性:用于定义该类或该类对象包含的数据或者说静态特征3.初始化∶定义成员变量时可以对其初始化,如果不对其初始化,Java使用默认的值对其初始化4.方法:用于定义该类或该类实例的行为特征和功能实现......