Tree-shaking 的原理是基于 ES6 模块系统的静态特性,通过静态分析和依赖关系的追踪,识别并剔除未使用的代码。
Tree shaking 是指通过静态代码分析,识别和移除 JavaScript 中未被使用的代码(未引用到的代码),以减少最终打包生成的文件体积。在 webpack 中,tree shaking 主要是通过 ES6 模块化的静态特性来实现的。
以下是 webpack 中 tree shaking 的原理:
-
ES6 模块化静态特性:ES6 模块化的特性使得模块之间的依赖关系在编译阶段就能确定,因此编译器能够在静态分析阶段识别哪些模块被实际引用,哪些模块没有被引用。
-
标记未使用代码:webpack 在对代码进行打包时,会通过静态分析标记每个模块中的导出和导入,并将未使用的模块标记为“未使用”。
-
剔除未使用代码:在标记完未使用代码后,webpack 会通过工具(如 UglifyJS)进行压缩和优化,剔除标记为未使用的代码,从而减小最终打包文件的体积。
-
依赖图优化:webpack 还会优化模块之间的依赖关系,移除没有被引用的代码路径,以进一步减少最终打包文件的大小。
总的来说,webpack 中的 tree shaking 主要依赖于 ES6 模块化的静态特性和编译器对模块之间依赖关系的静态分析,通过识别未使用的代码并剔除,来减小打包文件的体积,提高应用的性能和加载速度。
Tree-shaking 的关键在于静态特性和依赖关系的追踪。ES6 模块系统是静态的,也就是说,模块的导入和导出是在静态分析阶段就确定的,而不依赖于代码的执行。这使得工具可以精确地识别哪些代码是被使用的。
同时,依赖关系的追踪保证了代码的可达性。只有被其他模块导入的代码,或被导入模块自身使用的代码,才会被视为是被使用的。未被使用的代码会被标记并剔除,以避免冗余的打包结果。
需要注意的是,Tree-shaking 的成功与否还取决于开发者的代码编写方式。一些因素可能导致无法进行有效的剔除,例如动态导入、导入的模块有副作用等。因此,在编写代码时,开发者需要遵循一些约定和最佳实践,以提高 Tree-shaking 的效果。
webpack的tree-shaking的底层原理是什么
Webpack 的 tree-shaking 是通过静态代码分析和标记未使用代码的方式来实现的。其底层原理如下:
-
ES6 模块: Webpack 通过 ES6 模块的静态特性,即模块的导入和导出关系在编译阶段就可以确定,利用这一点来进行 tree-shaking。只要模块没有被导出,那么Webpack就会将其标记为未使用的代码。
-
Terser/UglifyJS: Webpack 在压缩代码时通常会使用 Terser 或 UglifyJS 等工具。这些压缩工具会在压缩代码的同时识别并移除未使用的代码,实现了实质上的 tree-shaking。
-
Tree-shaking 原理: 当 Webpack 执行 tree-shaking 时,会从入口文件开始递归地分析模块之间的依赖关系,识别出哪些模块被导入但未被使用。然后,Webpack 在构建过程中利用这些信息,只将真正被使用的代码打包到最终的输出文件中,从而减少打包体积。
总的来说,Webpack 的 tree-shaking 底层原理是通过静态代码分析、标记未使用代码以及压缩工具的配合来实现,从而提高打包的效率并减小输出文件的体积。
CommonJS是动态执行的,所以commonjs的代码不好进行tree-shaking
是的,你提到的 CommonJS 模块系统是一种动态执行模块的规范,而静态执行的 tree-shaking 技术则通常用于剔除没有使用的代码(无法被静态分析到的代码)以减少 bundle 的体积。由于 CommonJS 模块是在运行时进行加载和解析的,因此在编译阶段无法确定模块的依赖关系,导致编译器无法准确识别未被使用的代码,进而无法进行有效的 tree-shaking。
相比之下,ES6 模块采用静态导入语法,编译器可以在编译阶段准确地识别模块之间的依赖关系,因此能够进行更有效的 tree-shaking,剔除未被使用的代码。这也是为什么现代的打包工具(如 Webpack、Rollup 等)默认支持 ES6 模块的 tree-shaking,以减少最终打包生成的代码体积。
在使用 CommonJS 模块时,如果需要实现类似于 tree-shaking 的效果,一种常见的做法是通过静态分析工具(如 webpack-bundle-analyzer)结合工具(如 babel-plugin-import)来手动进行代码优化和按需引入,以达到减少不必要代码的目的。但这种方式相比于 ES6 模块的 tree-shaking 效果会有限,因为 CommonJS 的动态特性使得在编译阶段无法准确确定模块间的依赖关系。
因此,虽然 CommonJS 模块在动态执行方面具有灵活性,但在一些优化技术(如 tree-shaking)方面可能无法与静态导入的 ES6 模块系统相提并论。
CommonJS方便tree-shaking吗
CommonJS 模块系统并不太适合进行 tree-shaking,因为 CommonJS 模块是动态加载和执行的,导致编译器无法在编译阶段准确确定模块之间的依赖关系,从而无法有效地进行 tree-shaking。
Tree-shaking 是一种静态代码优化技术,通过分析静态的模块依赖关系,剔除未被使用的代码以减少最终打包生成的代码体积。在这方面,ES6 模块由于采用静态导入语法,能够在编译阶段准确识别模块间的依赖关系,更容易进行有效的 tree-shaking。
虽然有一些工具(如 Webpack)可以在一定程度上实现对 CommonJS 格式的代码进行类似于 tree-shaking 的效果,但这种方式通常要结合静态分析工具和手动配置,而且效果相比 ES6 模块的 tree-shaking 效果会有限。
综上所述,由于其动态加载特性,CommonJS 模块并不太适合进行传统意义上的 tree-shaking。如果你追求代码体积优化和快速加载速度,推荐使用 ES6 模块并结合现代打包工具进行 tree-shaking。
方法一:usedExports + Terser
设置usedExports为true
,打包后,会有有一段注释unused harmony export mul
,告知Terser
在优化时,可以删除掉这段代码
const TerserPlugin = require('terser-webpack-plugin');
方法二:sideEffects
- sideEffects:false,代表可以放心大胆的删除,没有任何副作用
- sideEffect:[ 文件1,文件2 ] ,登记有副作用的文件例如:
css的Tree Shaking:
- 早期使用
PurifyCss
,但该库已不再维护了 - 目前
PurgeCSS
- 配置:
- 有上面的配置,打包后,