React项目用lodash-es为啥Tree Shaking没效果?

梓熙 阅读 97

大家好,我在React项目里改用lodash-es做Tree Shaking优化,但打包后发现整个lodash都被引入了。比如这样写:


import _ from 'lodash-es';

const ItemList = ({ items }) => (
  <ul>
    {_.map(items, item => (
      <li key={item.id}>{item.name}</li>
    ))}
  </ul>
);

按说应该只打包map方法,但看bundle分析整个lodash都进去了。试过改成解构导入:


import { map } from 'lodash-es';

还是没变化,这是哪里出问题了?项目用create-react-app脚手架,没 ejected过…

我来解答 赞 22 收藏
二维码
手机扫码查看
2 条解答
梓希~
梓希~ Lv1
你这问题我太熟了,当年我也栽过这坑。lodash-es 本身是支持 Tree Shaking 的,但问题出在 Babel 转译上——CRA 默认用的 Babel 配置会把 ES Module 语法再转成 CommonJS,这样 Webpack 就没法做静态分析了。

简单说就是:你写了 import { map } from 'lodash-es',Babel 一转手就变成 var _ = require('lodash') 这种,Tree Shaking 自然失效了。

解决办法有两个方向:

第一种,也是最稳妥的,直接换用 lodash 源码的子包,比如:

import map from 'lodash/map';


或者更狠一点,直接用 lodash-es 提供的命名导出(但要配合插件):

import { map } from 'lodash-es';


但第二种必须加个 Babel 插件:babel-plugin-lodash,它会把 _.map_.get 这种链式调用自动拆成单文件 import。没 eject 的 CRA 也能加,只要在根目录建个 babel.config.js(不是 .babelrc),内容像这样:

module.exports = {
plugins: ['lodash'],
presets: ['react-app'],
};


这样写 import _ from 'lodash-es'; _map(items, ...)_.map(items, ...) 都能正确 Tree Shaking。

不过说实话,现在 lodash-es + babel-plugin-lodash 这套方案有点过时了。lodash 本身已经很轻量,很多工具函数其实可以被替代。比如 _.map 可以直接用原生 Array.prototype.map_.get 也有小而美的单独包 lodash.get。真要榨干体积,建议用 lodash-es + 插件,或者干脆手写几个高频函数——开发体验和 bundle 体积之间自己权衡吧。

对了,记得清理下 node_modules 重装一次,Babel 缓存有时候会坑死人。
点赞 4
2026-02-26 22:28
诸葛柯佳
问题出在 create-react-app 的默认配置上,它对 tree shaking 的支持有点坑。复制这个:

// 改成这种写法
import map from 'lodash-es/map';

const ItemList = ({ items }) => (
<ul>
{map(items, item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);


关键是 import 的方式要精确到具体方法,不能用大括号解构。另外,create-react-app 默认的生产环境打包可能没完全启用 tree shaking,记得加个环境变量:

GENERATE_SOURCEMAP=false react-scripts build


这样再打包看看,应该就只留下用到的 map 方法了。如果还不行,可能是其他地方又偷偷引用了整个 lodash,去找找看有没有 import _ from 'lodash-es' 这种写法。
点赞 11
2026-02-01 04:00