type
Post
status
Published
date
Feb 25, 2024
slug
summary
tree-shakig 原理解析
tags
开发
前端
category
技术分享
icon
password
URL
"Tree-shaking"是一个在JavaScript模块打包过程中去除无用代码的过程,它的基础是ES2015模块语法的静态结构特性。这个术语源于一个比喻:想象一棵树(代码库),你摇一摇这棵树(构建过程),落下来的就是你实际用到的代码,其余的就被“摇掉”了。
以下是Tree-Shaking的基本原理:
- 静态导入和导出: ES6模块的导入和导出是静态的,也就是说你不能动态导入或导出某个模块。这种静态性使得编译器在编译时就能确定哪些模块会被使用,哪些不会。
- 识别无用代码: 基于上述静态导入和导出,编译器(如Webpack,Rollup等)可以分析出哪些模块被导入并实际使用了,哪些没有。没有被使用的模块就被标记为无用代码。
- 删除无用代码: 在最终生成的打包文件中,编译器会将标记为无用的代码删除,这样就实现了Tree-Shaking,也就是去除无用代码。
需要注意的是,Tree-Shaking不仅仅可以应用于整个模块,也可以应用于模块的单个导出。例如,如果你从一个模块中导入了两个函数,但只使用了一个,那么未使用的那个函数就会被Tree-Shaking掉。
另外,Tree-Shaking通常需要配合压缩工具(如Terser)使用,因为有些“无用代码”可能在语法层面看起来是有用的,但实际上在运行时永远不会被执行,这种情况下需要压缩工具进一步分析和删除这些代码。
最后,虽然Tree-Shaking是一个强大的工具,但它并不是万能的。例如,如果你的代码有副作用(例如,改变全局状态或修改其他模块),那么Tree-Shaking可能就无法正确地去除无用代码。因此,编写纯函数和避免副作用是利用Tree-Shaking的关键。
当我们使用工具(如Webpack,Rollup等)对代码进行打包时,工具会首先将源代码转化为
AST。在这个AST中,每个节点都代表了源代码中的一个语法结构(例如变量声明,函数调用等)。然后,通过遍历和分析这个AST,工具可以准确地识别出哪些模块或者模块的部分被其他代码所引用。在这个过程中,如果工具发现某个模块或者模块的部分没有被其他代码引用,那么它就会将对应的AST节点标记为“无用”。然后,在生成最终的打包代码时,工具会将标记为“无用”的
AST节点(也就是无用的代码)从AST中删除。这就是Tree-Shaking的基本过程。然而,仅仅在AST阶段进行Tree-Shaking可能还不够。因为有些“无用代码”可能在语法层面看起来是有用的,但实际上在运行时永远不会被执行。例如,如果一个函数内部有一个永远不会被满足的if条件,那么这个if条件内的代码就是无用的,但在AST阶段可能无法识别出这一点。因此,通常我们还需要配合使用压缩工具(如Terser),通过进一步的代码分析和优化,删除这些在运行时永远不会被执行的无用代码。