一文了解webpack和vite中Tree-Shaking

1、什么是Tree-Shaking

1.1 摇树优化(Tree Shaking)是Webpack中一种用于优化JavaScript代码的技术。它的目标是通过静态分析,从代码中剔除未被使用的模块,从而减少最终打包文件的大小。

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

2、适用范围&实现原理

1.1 适用范围:

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

摇树优化要求代码使用ES6模块化的语法。确保你的代码基于ES6模块化进行编写,而不是使用CommonJS或AMD等其他模块化方案。

ESM:export + import

Common JS:module.exports + require

javascript 复制代码
// 导入所有内容(不会触发 tree-shaking)
import lodash from 'lodash'
 
// 导入命名导出 (会触发 tree-shaking)
import { debounce } from 'lodash'

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

2.2 实现原理

以webpack为例,webpack 会从入口文件开始,对你 import 的代码进行静态分析,如果发现某个模块没有被任何地方使用,就会将该模块标记为 unused harmony exports,并且在生成产物时不再 export 该模块。最后,再将生成产物交给 uglify 或 terser 这样的压缩工具进行处理,此时未被 export 的代码就会被当成死代码删除。 需要注意的是,tree shaking 并不会直接删除代码,只是分析模块依赖关系并去掉未引用代码的 export,真正进行死代码消除的是 uglify 或 terser 这样的压缩工具。

相关配置

javascript 复制代码
// webpack.config.js
module.exports = {
  optimization: {
    usedExports: true, // 开启 tree shaking
    concatenateModules: false, // 关闭模块合并
    minimize: false // 关闭代码压缩
  }
}

3、webpack中的Tree-Shaking

Webpack 5对Tree Shaking进行了改进,可以更有效地删除未使用的代码,从而使打包后的文件更小,加载更快

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

  • 使用 ESM 规范编写模块代码
  • 配置 optimization.usedExports 为 true,启动标记功能
  • 启动代码优化功能,可以通过如下方式实现:
    • 配置 mode = production:在Webpack的配置中,将mode设置为production模式。这会自动启用一系列的优化功能,包括摇树优化
    • 配置 optimization.minimize = true
    • 提供 optimization.minimizer 数组
javascript 复制代码
// webpack.config.js
module.exports = {
  entry: "./src/index",
  mode: "production",
  devtool: false,
  optimization: {
    usedExports: true // 启用tree-shaking
  }
}

4、vite中的Tree-Shaking

生产模式下vite会默认开启所有优化通过tree-shaking摇掉未使用代码


Vite中未使用资源仍被打包问题 :简单参考

5、为什么Tree-shaking失效

5.1 sideEffects副作用

在Webpack中,sideEffects是一个用于优化打包输出的配置选项。它用于指示哪些模块具有副作用 ,或者说哪些模块是否会对整个应用程序的行为产生影响,以便Webpack可以进行更有效的处理。

设置sideEffects的目的是告诉Webpack哪些模块没有副作用,以便它可以在打包过程中优化代码。Webpack可以根据这些信息,例如删除未使用的导入、通过摇树优化(tree-shaking)消除未使用的代码等。

详细说明:https://zhuanlan.zhihu.com/p/260724544

5.2 babel-loader使Tree-shaking失效

使用Babel Loader确实有可能导致Tree-shaking失效,这是因为Babel Loader默认情况下会将所有ES6模块转换为CommonJS模块,而CommonJS模块的导入和导出方式是动态的,无法在编译时进行静态分析。

为了解决这个问题,你需要在Babel配置中进行相应的调整,以保持ES6模块的静态导入和导出,从而使Tree-shaking能够正常工作。

首先,确保你安装了@babel/preset-env插件,并在Babel配置文件(通常是.babelrc或babel.config.js)中进行如下配置:

javascript 复制代码
{
  "presets": [
    ["@babel/preset-env", {
      "modules": false
    }]
  ]
}

在上述配置中,将modules选项设置为false,以保持ES6模块的形式。这样Babel在转换代码时就不会将ES6模块转换为CommonJS模块。

通过pure标记一些只在开发环境中,但生产环境不需要的代码

javascript 复制代码
var test = /*#__PURE__*/function () {
  return 996;
}();

在Babel 6之后的版本可以用/#PURE/注释,这样在做副作用检查的时候,就可以认为该方法没有副作用,标记为"纯函数",方便删除。这样的好处在于一些特别的测试数据不会出现在线上环境中~

5.3 export default 会导致 Tree Shaking 失败

javascript 复制代码
import {add} from './add';
import {sub} from './sub';

export default {add, sub}

具体说明:https://zhuanlan.zhihu.com/p/123268547

参考文档:https://zhuanlan.zhihu.com/p/549543919

相关推荐
原则猫7 小时前
UDP 到底怎么实现可靠的
前端
Java后端的Ai之路7 小时前
14、ReactJS - 路由(Router)
前端·react.js·状态模式
裕晟资质规划9 小时前
三类涉密资质延续时限差异分析:军工60日与集成印制3个月的边界
java·服务器·前端·网络·安全
ShineWinsu9 小时前
对于JavaScript:JavaScript基础语法的解析
开发语言·前端·javascript·面试·web·基础语法·循环
月夏9 小时前
Vue3 转 React:18 项对照表 + 5 个必踩的坑(附 7 天上手路线)
前端
广州华水科技9 小时前
单北斗GNSS位移监测系统的应用与维护解析
前端
梦曦i9 小时前
uni-storage 0.1.0 发布:TTL过期管理+多实例隔离
前端·storage·uni-app x
猫头_10 小时前
AI 流式传输工程指南:模型吐出半截 JSON,前端如何边收边渲染?
前端·javascript·llm
console.log('npc')11 小时前
第 1 章 项目概述与环境搭建
前端·人工智能·大模型
定栓11 小时前
Webpack迁到Vite第七节(二):全家桶移除 — Babel 全家桶深度分析
前端·webpack·node.js