Tree Shaking 为什么没生效?我明明用了 ES6 模块啊

子硕 Dev 阅读 25

我在用 Webpack 打包一个 React 项目,发现 lodash 的整个包都被打包进去了,哪怕我只 import 了一个 debounce。我查了文档说 Tree Shaking 要求用 ES6 模块,我也确实这么写了,但还是没效果,是不是哪里配置错了?

这是我的代码:

import { debounce } from 'lodash';

function MyComponent() {
  const handleResize = debounce(() => {
    console.log('resized');
  }, 300);

  return <div onResize={handleResize}>Hello</div>;
}

我试过加 sideEffects: false 到 package.json,也确认 mode 是 production,但 bundle 里还是有整个 lodash……

我来解答 赞 10 收藏
二维码
手机扫码查看
2 条解答
UI敏涵
UI敏涵 Lv1
这坑我之前也踩过,不是你配置的问题,是 lodash 本身的问题。

lodash 主包是 CommonJS 格式导出的,不管你怎么 import,Webpack 都没法做 Tree Shaking。想生效得用 lodash-es,这个才是 ES Module 版本:

import { debounce } from 'lodash-es';


或者单独装具体的函数包,比如 lodash.debounce,也能解决。
点赞 1
2026-03-02 07:06
智营
智营 Lv1
你这问题太典型了,很多人以为写了 import 就是 ES Module,其实根本不是那么回事。

问题出在你引入的包本身。npm 上的 lodash 默认包,里面全是 CommonJS 格式的代码。Tree Shaking 的核心是静态分析,CommonJS 是动态加载的,Webpack 根本没法在编译阶段安全地把你没用的代码剔除掉。所以不管你怎么配 sideEffects,它只能把整个 lodash 都塞进去。

要解决这个问题,最直接的办法是把包换成 lodash-es。这才是官方提供的 ES Module 版本。

代码改一行就行:

import { debounce } from 'lodash-es';


这样 Webpack 才能识别出哪些导出是没用的,直接把没用的函数在打包时干掉。重新跑一下构建,你会发现体积瞬间小几十 KB。

如果你项目太大,到处都是 import { ... } from 'lodash',懒得改代码,也可以用 babel-plugin-lodash 配合 lodash-webpack-plugin。这俩插件组合能把你的引用自动转成 import debounce from 'lodash/debounce' 这种按需加载的方式,也能达到优化效果。

不过既然还在开发阶段,直接切 lodash-es 最省事,原生支持 Tree Shaking,别让用户白白下载那么大一堆没用的代码。
点赞 3
2026-03-01 18:02