引言
在 JavaScript 的日常开发中,lodash
是非常受欢迎的工具库,提供了大量实用的函数处理集合、对象、函数、字符串等。但你是否注意到,lodash
的现代替代品 lodash-es
被推荐用于现代前端工程中?它们看起来功能一致,为什么 lodash-es
更优?本篇文章将详细比较二者的区别,并通过源码分析几个核心函数的实现,解释为什么 lodash-es
在现代开发中表现得更好。
一、lodash vs lodash-es:基本区别
特性 | lodash | lodash-es |
---|---|---|
模块化支持 | CommonJS | ES Modules (ESM) |
Tree Shaking | 不支持 | ✅ 支持 |
打包体积 | 较大 | 较小(按需引入) |
兼容性 | Node.js 和旧浏览器兼容 | 现代浏览器/构建工具 |
性能(构建优化) | 较差 | ✅ 更佳(按需优化) |
二、为什么 lodash-es 更快?
1. 支持 Tree Shaking
现代构建工具如 Webpack、Vite、Rollup 等都支持对 ES Module 进行 Tree Shaking,即移除未使用的代码。这使得使用 lodash-es
可以显著减小最终打包体积,从而加快加载速度和执行性能。
例如:
ts
// lodash
import _ from 'lodash'
const result = _.cloneDeep(data) // 实际上导入了整个 lodash 库
// lodash-es
import cloneDeep from 'lodash-es/cloneDeep'
const result = cloneDeep(data) // 仅导入了 cloneDeep 函数
2. 编译优化更好
由于 lodash-es
使用原生 export
/import
,构建工具对其的优化(如 scope hoisting、压缩等)更加友好,这使得运行时代码更加高效。
三、函数实现对比分析
下面我们选取几个常用函数进行源码对比,看看是否存在性能或结构上的优化。
1. cloneDeep 函数
js
// lodash 的实现(简化后)
function cloneDeep(value) {
return baseClone(value, true, true)
}
lodash-es
的实现完全一致,来自同一源码。但差异在打包过程 :lodash
会将baseClone
和其他函数全都打包进来;lodash-es
只会引入cloneDeep
相关依赖函数,其他未使用函数不会包含。
2. debounce 函数
- 两者实现内容基本相同,但
lodash
是整体模块,依赖链庞大。 lodash-es
中这些依赖以独立模块存在,未引用则不会打包进来。
3. uniq 函数
lodash
引入 baseUniq、SetCache 等多个辅助函数。lodash-es
只保留实际使用的依赖模块。
四、实测性能对比
使用 Rollup + terser 压缩分别引入 lodash
和 lodash-es/cloneDeep
,观察最终打包大小:
使用方式 | gzipped 大小 |
---|---|
import _ from 'lodash' |
70+ KB |
import cloneDeep from 'lodash-es/cloneDeep' |
6 KB |
五、推荐使用方式
使用场景 | 推荐做法 |
---|---|
Node.js 脚本 | lodash (兼容性强) |
Web 项目 | lodash-es + 按需导入(节省体积) |
多函数调用 | 使用 babel-plugin-lodash 或 lodash-es |
完全极致优化 | 只引入 lodash-es 中的单个函数路径 |
六、总结
维度 | lodash | lodash-es |
---|---|---|
模块格式 | CommonJS | ES Module |
Tree Shaking | ❌ 不支持 | ✅ 支持 |
打包体积 | 大 | 小 |
函数实现 | 相同 | 相同 |
构建优化 | 差 | 好 |
推荐使用场景 | Node.js 脚本 | 浏览器 / 前端项目 |
附录:快速迁移到 lodash-es
sh
npm install lodash-es
修改:
ts
// from
import _ from 'lodash'
// to
import cloneDeep from 'lodash-es/cloneDeep'
import debounce from 'lodash-es/debounce'