【Webpack】TreeShaking与静态分析

news/2024/7/11 1:15:32 标签: webpack, 前端, es6

TreeShaking

Tree shaking 字面意就是“摇树”,通过摇树将树上枯黄的叶子摇落。tree shaking 的作用是把项目中没必要的代码全部抖落掉,消除被引用,删除没被调用的无用模块代码,该优化最终实现的是代码体积的减少,也属于项目性能优化的一部分。
原理是利用 ES6 的模块化语法,通过静态分析代码之间的引用关系,来判断哪些模块未被引用,进而删除对应代码。

应用 tree shaking 需要具备条件:

  • 使用 ES2015 模块语法 —— import export
  • 确保没有编译器将的 ES2015 模块语法转换为 CommonJS 的(这是现在常用的 @babel/preset-env 的默认行为 --> 在 .babelrc 文件里将将 modules 设置为 false,避免将 ES Module 模块类型转换为CommonJS)。
  • 生产环境下默认开启。(将 mode 设置为 production 时,Tree Shaking 是默认开启的。production 模式自动启用了多种优化措施,包括代码压缩、作用域提升 Scope Hoisting 和 Tree Shaking,旨在减小最终bundle的体积和改善应用的性能)
  • 可以配置 sideEffects 属性(非开启必须条件,所有文章里都把它们放一起说。。),以帮助 Webpack 识别和移除那些包含副作用的模块或文件,进一步减少 bundle 大小。
// webpack.config.js

const path = require('path');
module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};


// package.json

{
  "name": "tree-shaking-demo",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "build": "webpack"
  },
  "sideEffects": false,
  "devDependencies": {
    "webpack": "^5.0.0",
    "webpack-cli": "^4.0.0"
  }
}

sideEffect

sideEffects 属性可能会影响 Tree Shaking 的有效性。
Tree Shaking 的工作原理是分析模块的导入和导出,并移除那些未被用到的导出。但是,如果一个模块执行了一些副作用(例如,修改全局状态、立即执行的 DOM 操作等),Webpack 将默认地保守处理,不会删除该模块,即使它的导出没有被其他模块使用。这是因为 Webpack 无法确定移除该模块是否会影响程序的运行。
当你指定 sideEffects 属性时,你在告诉 Webpack 哪些文件是“纯净”的(没有副作用),因此即使这些文件的内容没有被显式导入,Webpack 在 Tree Shaking 过程中也可以安全地移除它们。

  • 设置"sideEffects": false,告诉 Webpack 项目中的所有模块都没有副作用,因此,如果某个模块的导出未被使用,Webpack 会在生产构建时把它移除。
  • 设置"sideEffects": [“./src/someSideEffectfulFile.js”],如果只有部分文件有副作用,可以通过数组具体指明。
  • 没有设置 sideEffects 属性,Webpack 会更加保守地处理模块移除,可能会导致某些实际上可以安全移除的代码被保留在最终的 bundle 中。

静态分析

Tree Shaking 实现的关键得益于 ES Module 模块的静态分析。打包工具(如Webpack)分析应用程序中所有的 import 和 export 语句,构建起依赖图,这个图展现了模块之间的依赖关系。随后,遍历这个图,标记那些被导入但未被其他模块引用的导出。这些被标记的导出即为“未使用的代码”。在最终的打包过程中,打包工具会移除那些标记为未引用的导出。在 Webpack 中,这通常发生在代码压缩(minification)阶段,使用如 Terser 这样的压缩工具来消除死代码。
在 ES Module 中,我们可以将模块的加载分为两个阶段:静态分析和编译执行;静态分析,即在代码执行前就能对整体代码依赖调用关系等进行分析读取。
ES Module 特性:

  1. 只能作为模块顶层的语句出现(而不嵌套在条件语句中)
  2. import 的模块名只能是字符串常量,导入和导出语句没有动态部分(不允许使用变量、表达式等)

ES Module 的 import 语法完美可以使用 tree shaking,因为可以在代码不运行的情况下就能分析出不需要的代码。
不同于 ES Module,CommonJS 支持动态加载模块,在加载前是无法确定模块是否有被调用,所以并不支持 tree shaking。

参考:
https://mp.weixin.qq.com/s/SbJNbSVzSPSKBe2YStn2Zw
https://webpack.docschina.org/guides/tree-shaking/
https://segmentfault.com/a/1190000040037144


http://www.niftyadmin.cn/n/5480260.html

相关文章

MySQL与Navicat相关

mysql中find_in_set的用法? FIND_IN_SET 是 MySQL 中的一个函数,用于在逗号分隔的字符串列表中查找指定值,并返回其在列表中的位置(索引),如果找不到则返回 0。其语法如下: FIND_IN_SET(searc…

《C++程序设计》阅读笔记【7-堆和拷贝构造函数】

🌈个人主页:godspeed_lucip 🔥 系列专栏:《C程序设计》阅读笔记 本文对应的PDF源文件请关注微信公众号程序员刘同学,回复C程序设计获取下载链接。 1 堆与拷贝构造函数1.1 概述1.2 分配堆对象1.3 拷贝构造函数1.3.1 默…

JavaSE:static关键字详解

引言 我们在学习Java的过程中,static属于我们最先遇到的几个关键字之一 你可能会问,我怎么没印象 public class StaticKeyword {// 我们写第一个java程序,运行Hello World的时候,main方法就用了static修饰public static void m…

【ros】结果实时在线可视化

文章目录 一、前言二、订阅与发布三、回调四、可视化 4.1、初始化参数4.2、初始化图片 4.3、画结果 4.4、可视化结果 一、前言 感知与规划控制是无人驾驶算法重要算法,在交付测试阶段也最容易引起摩擦,这也是司空见惯的现象。有时候可能是接口对齐问题…

Transformer详解和知识点总结

目录 1. 注意力机制1.1 注意力评分函数1.2 多头注意力(Multi-head self-attention) 2. Layer norm3. 模型结构4. Attention在Transformer中三种形式的应用 论文:https://arxiv.org/abs/1706.03762 李沐B站视频:https://www.bilibi…

Python中调用函数简洁方法

直接上代码 def func1():print("func1")def func2():print("func2")def func3():print("func3")def func4():print("func4")func_list [func1, func2, func3, func4]for func in func_list:func()结果如下 func1 func2 func3 func4如…

在Go语言中使用select和channel来期待确定性行为

Go开发人员在使用channel时常犯的一个错误是,对select在多个channel中的行为方式做出错误的假设。错误的假设可能会导致难以识别和重现的细微错误。假设我们要实现一个需要从两个channel接收消息的goroutine: 我们可能会决定像下面这样处理优先级: for {select {case v := &…

Netty 心跳(heartbeat)——服务源码剖析(下)(四十二)

IdleStateHandler内部的 3 个定时任务类 这 3 个定时任务分别对应 读,写,读或者写 事件。共有一个父类(AbstractldleTask)。这个父类提供了个模板方法 private abstract static class AbstractldleTask implements Runnable f private final ChannelHan…