Tree-Shaking 作用和实现原理

news2024/12/24 13:56:11

一、什么是Tree-shaking

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

在前端开发中,特别是在使用模块化工具(如Webpack、Rollup等)构建应用程序时,通常会引入许多库和模块。然而,应用程序可能只使用了这些库的一小部分功能,导致最终生成的代码包含了大量未被使用的代码。Tree-shaking通过静态分析代码来确定哪些代码是可到达的并且被使用的,然后去除那些未被使用的部分。这样一来,可以显著减小最终部署的代码大小,提高应用程序的性能。

Tree Shaking 较早前由 Rich Harris 在 Rollup 中率先实现,Webpack 自 2.0 版本开始接入,已经成为一种应用广泛的性能优化手段。

上图形象的解释了Tree-shaking 的本意,本文所说的前端中的tree-shaking可以理解为通过具"摇"我们的JS文件,实际开发中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 tree-shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的。

在 Webpack 中,启动 Tree Shaking 功能必须同时满足三个条件:

  • 使用 ESM 规范编写模块代码
  • 配置 optimization.usedExportstrue,启动标记功能
  • 启动代码优化功能,可以通过如下方式实现:
    • 配置 mode = production
    • 配置 optimization.minimize = true
    • 提供 optimization.minimizer 数组
// webpack.config.js
module.exports = {
  entry: "./src/index",
  mode: "production",
  devtool: false,
  optimization: {
    usedExports: true // 启用tree-shaking
  }
}

示例代码

// bar.js
const bar = 'bar'
const foo = 'foo'

export {
   bar,
   foo
}

// index.js
import { bar } from './bar'  // 引入bar.js
console.log(bar)

示例中bar.js 模块导出了 bar 、foo 但只有 bar 导出值被其它模块使用,经过 Tree Shaking 处理后,foo 变量会被视作无用代码删除。

Tree Shaking 只支持 ESM (ES6 Module)的引入方式,不支持 Common JS 的引入方式。

  • ESM:export + import
  • Common JS:module.exports + require
// 导入所有内容(不会触发 tree-shaking)
import lodash from 'lodash'
 
// 导入命名导出 (会触发 tree-shaking)
import { debounce } from 'lodash'

注意:如果想要做到 tree shaking,那么在引入模块时就应该避免全部引入。应该采用按需引入,才可以触发 tree shaking 机制。

二、实现原理

Tree Shaking在去除代码冗余的过程中,程序会从入口文件出发扫描所有的模块依赖,以及模块的子依赖,然后将它们链接起来形成一个“抽象语法树”(AST)。随后,运行所有代码,查看哪些代码是用到过的,做好标记。最后,再将“抽象语法树”中没有用到的代码“摇落”。经历这样一个过程后,就去除了没有用到的代码。

Webpack 中,Tree-shaking 的实现一是先「标记」出模块导出值中哪些没有被用过,二是使用 Terser 删掉这些没被用到的导出语句。标记过程大致可划分为三个步骤:

  • Make 阶段,收集模块导出变量并记录到模块依赖关系图 ModuleGraph 变量中
  • Seal 阶段,遍历 ModuleGraph 标记模块导出变量有没有被使用
  • 生成产物时,若变量没有被其它模块使用则删除对应的导出语句

标记功能需要配置 optimization.usedExports = true 开启

在ES Module中,我们可以将模块的加载分为两个阶段:静态分析和编译执行;

所谓静态分析,即在代码执行前就能对整体代码依赖调用关系等进行分析读取;

下面我们看下ES Module的特性:

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

三、sideEffects 副作用

webpack 2 正式版本内置支持 ES2015 模块(也叫做 harmony modules)和未使用模块检测能力。新的 webpack 4 正式版本扩展了此检测能力,通过 package.json 的 "sideEffects" 属性作为标记,向 compiler 提供提示,表明项目中的哪些文件是 "pure(纯正 ES2015 模块)",由此可以安全地删除文件中未使用的部分。

Webpack 中有一个 sideEffects 配置,用于标识哪些模块是无副作用的,可以被 Tree-shaking 移除。如果你的模块包含副作用,但你明确知道这些副作用是无害的,可以通过配置 sideEffects 来告诉 Webpack 哪些模块可以被 Tree-shaking 移除。

// package.json
{
  "sideEffects": ["*.css", "*.scss"]
}

四、哪些框架可以使用Tree-shaking

  • Webpack

    Webpack 是一个强大的 JavaScript 模块打包工具,支持 Tree-shaking。在 Webpack 2 及以上版本中,配置 mode 为 'production',Webpack 默认启用 Tree-shaking。同时确保你的项目使用了 ES6 模块系统,以便 Webpack 能够更好地进行静态分析。
  • Rollup

    Rollup 是专注于 ES6 模块的打包工具,天生支持 Tree-shaking。Rollup 的设计目标之一就是生成更小、更高效的代码,因此它是一个非常适合 Tree-shaking 的选择。
  • Parcel

    Parcel 是一个零配置的打包工具,它通过自动检测和处理模块间的依赖关系,实现了快速且有效的 Tree-shaking。Parcel 可以用于快速搭建项目,而无需复杂的配置。
  • Snowpack

    Snowpack 是一个现代的构建工具,专注于提供快速的开发体验。它支持 ES6 模块和 Tree-shaking,并在开发环境中实现了即时开发(Instant Development)的特性。
  • Vite

    Vite 是一个基于 Vue.js 的新型构建工具,它利用原生 ES 模块导入的特性,支持 Tree-shaking,并在开发环境中实现了快速的冷启动。
  • ESBuild

    ESBuild 是一个极快的 JavaScript 构建工具,它具有强大的 Tree-shaking 功能。ESBuild 以速度为特点,能够在短时间内完成快速的构建。

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

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

相关文章

vue element MessageBox.prompt this.$prompt组件禁止显示右上角关闭按钮,取消按钮,及点击遮罩层关闭

vue element MessageBox.prompt this.$prompt组件禁止或取消显示右上角关闭按钮,取消按钮,及点击遮罩层关闭 实现效果: 实现代码 MessageBox.prompt(请先完成手机号绑定, 系统提示, {confirmButtonText: 提 交,showClose: false,closeOnClic…

解决TCP粘包问题

粘包问题已经在上一篇博客中写到具体可以看----------- 以下是利用分包解决粘包问题的步骤: 消息长度前缀: 在每个数据包前加入消息长度信息。 定义协议格式: 明确定义通信协议的格式,包括消息头和消息体。 封包: 将…

Tensorflow2 GPU版本-极简安装方式

Tensorflow2 GPU版本-极简安装方式: 1、配置conda环境加速 https://wtl4it.blog.csdn.net/article/details/135723095https://wtl4it.blog.csdn.net/article/details/135723095 2、tensorflow-gpu安装 conda create -n STZZWANG_TF2 tensorflow-gpu2.0

kali安装LAMP和DVWA

LANMP简介 LANMP是指一组通常用来搭建动态网站或者服务器的开源软件,本身都是各自独立的程序,但是因为常被放在一起使用,拥有了越来越高的兼容度,共同组成了一个强大的Web应用程序平台。 L:指Linux,一类Unix计算机操作…

4G物联网LED智慧路灯杆显示屏产品介绍

4GLED显示屏是一种具有4G网络连接功能的LED显示屏。它可以通过4G网络连接到互联网,实现远程管理和控制,方便进行内容更新和管理。同时,4GLED显示屏具有高亮度、高清晰度和高对比度的特点,可以提供清晰明亮的图像和视频展示效果。它…

jdk17新特性——文本块(即多行的字符串)增强

目录 一、文本块(即多行的字符串)概述二、文本块(即多行的字符串)示例2.1、jdk17之前 多行字符串处理方式2.2、jdk17及以后版本 多行字符串处理方式2.3、注意事项 三、文本块(即多行的字符串)转义字符示例3.1、jdk17及以后版本 多行字符串的转义字符处理方式示例一3.2、jdk17及…

基于GPT3.5逆向 和 本地Bert-Vits2-2.3 的语音智能助手

文章目录 一、效果演示二、操作步骤三、架构解析 一、效果演示 各位读者你们好,我最近在研究一个语音助手的项目,是基于GPT3.5网页版的逆向和本地BertVits2-2.3 文字转语音,能实现的事情感觉还挺多,目前实现【无需翻墙&#xff0…

数据结构之线性表(一般的线性表)

前言 接下来就开始正式进入数据结构环节了,我们先从线性表开始。 线性表 线性表(linear list)也叫线性存储结构,即数据元素的逻辑结构为线性的数据表,它是数据结构中最简单和最常用的一种存储结构,专门存…

springboot快速开始

创建和配置 下面是创建和配置项目, 可以看看, 但是本文重点是怎么开web接口和连接数据库, 所以可以直接从gitee上下载我配好的 gitee 创建项目 java配置 idea里可以下载java maven maven用来帮你管理项目需要的包(库), 不过要下载快需要配镜像, 请查阅网络资料 添加依赖…

缓存高并发问题

Redis 做缓存虽减轻了 DBMS 的压力,减小了 RT,但在高并发情况下也是可能会出现各种问题的。 缓存穿透 当用户访问的数据既不在缓存也不在数据库中时,就会导致每个用户查询都会“穿透”缓存“直抵”数据库。这种情况就称为缓存穿透。当高度发…

处理Eclipse验证读条问题

打开Eclipse后下方一直读条加载验证,强迫症受不了。 依靠互联网自动加载失败,手动放入缺失的文件,我这里是mybatis的一个dtd文件缺失。 打开Eclipse-XML下的catalog,选择缺失的文件,保存。 可能需要重启Eclise

代码随想录刷题题Day41

刷题的第四十一天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀 刷题语言:C Day41 任务 ● 583. 两个字符串的删除操作 ● 72. 编辑距离 ● 编辑距离总结篇 1 两个字符串的删除操作 583. 两个字符串的删除…

详解线性分组码(linear code)

目录 一. 介绍 二. 线性分组码 三. 生成矩阵 四. 对偶编码 五. 校验矩阵 六. 陪集编码 七. 小结 一. 介绍 Low-density parity-check,简称LDPC码,翻译为低密度奇偶校验码。 我们所熟悉的LDPC码就是一个典型的线性分组码(linear bloc…

HarmonyOS(十三)——详解自定义组件的生命周期

前言 自定义组件的生命周期回调函数用于通知用户该自定义组件的生命周期,这些回调函数是私有的,在运行时由开发框架在特定的时间进行调用,不能从应用程序中手动调用这些回调函数。 下图展示的是被Entry装饰的组件生命周期: 今…

大数据学习之Flink算子、了解DataStream API(基础篇一)

DataStream API (基础篇) 注: 本文只涉及DataStream 原因:随着大数据和流式计算需求的增长,处理实时数据流变得越来越重要。因此,DataStream由于其处理实时数据流的特性和能力,逐渐替代了DataSe…

macOS跨进程通信: Unix Domain Socket 创建实例

macOS跨进程通信: Unix Domain Socket 创建实例 一: 简介 Socket 是 网络传输的抽象概念。 一般我们常用的有Tcp Socket和 UDP Scoket, 和类Unix 系统(包括Mac)独有的 Unix Domain Socket(UDX)。 Tcp So…

基于SpringBoot Vue家政服务预约平台系统

大家好✌!我是Dwzun。很高兴你能来阅读我,我会陆续更新Java后端、前端、数据库、项目案例等相关知识点总结,还为大家分享优质的实战项目,本人在Java项目开发领域有多年的经验,陆续会更新更多优质的Java实战项目&#x…

Midjourney 提示词入门 | 提示词格式 特点如何写好自己的提示词?进阶技巧

文章目录 1 Prompt格式2 文本提示词的基本要求3 好的文本提示词的特点 上一节我们初步了解了Midjourney的使用 那么在使用过程中最重要的是通过Prompt告知Midjourney怎么画 因而高效写Prompt非常重要~ 先来了解一下Prompt基本格式 1 Prompt格式 /imagine Text_prompt如下图…

【数据结构与算法】4.自主实现单链表的增删查改

📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏小杨水平有限,欢迎各位大佬指点&…

开始学习Vue2(脚手架,组件化开发)

一、单页面应用程序 单页面应用程序(英文名:Single Page Application)简 称 SPA,顾名思义,指的是一个 Web 网站中只有唯一的 一个 HTML 页面,所有的功能与交互都在这唯一的一个页面内完成。 二、vue-cli …