Lodash 是我们很常用的一个库(npm 周下载量是 2.8 亿次,react 是 0.8 亿次,webpack 是 1.1 亿次),但很多人引入 Lodash 并不优雅(打包后的体积过大),本文就带大家来看看 Lodash 常用的几种引入方式。
先写结论,想看细节的话,可以继续。本文所有的代码都在这个仓库中。
结论
- 直接写
import _ from 'lodash';
或import { isEqual } from 'lodash';
引入的是整个 Lodash 包,约 70kb 左右(压缩后),import isEqual from 'lodash/isEqual';
引入的单个使用到的文件,约 15kb 左右(压缩后)。 - 对于已有的项目,很多代码都是前两种写法的,那也不能一个一个的去改吧,是的,可以使用
babel-plugin-lodash
来帮助我们把前两种 变成第三种写法。 - 对于新写的代码,推荐使用
lodash-es
包,因为这可以省去 babel 编译的时间。
直接引入
// one.js
import _ from 'lodash';
console.log(_.isEqual(NaN, NaN));
build 后生成的 js 大小如下:
解构引入
// two.js
import { isEqual } from 'lodash';
console.log(isEqual(NaN, NaN));
build 后如下:
可以看到,都是 72 kb。
具体文件引入
// three.js
import isEqual from 'lodash/isEqual';
console.log(isEqual(NaN, NaN));
build 后如下:
咦,这个时候我们看到了神奇的事情,打包后只有 15 kb,这就说明 webpack 只打包了用到的代码,其他没用到的并没有打包进去。 说明文档也是这样指出的:
那我们就一直这样引入吧,还能做到按需加载,岂不是很 happy,其实不然,当我们引入的方法多了之后,就会变成如下这样:
import isEqual from 'lodash/isEqual';
import chunk from 'lodash/chunk';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';
// ...
这样就写了很多重复的代码,明显没有解构写方便:import { isEqual, chunk, debounce, throttle } from 'lodash';
当然 Lodash 这么牛逼的库不可能想不到这个问题,所以有 babel-plugin-lodash 可以使用,它做的就是一些代码转换,如下:
这个 babel 插件可以让以上 2 种方式都转成 文件引入。棒棒,我们来试一下:
// four.js
import _ from 'lodash';
import { add } from 'lodash/fp';
import isEqual from 'lodash/isEqual';
const addOne = add(1);
_.map([1, 2, 3], addOne);
console.log(isEqual(NaN, NaN));
当我们没有使用 babel-plugin-lodash 时,build 后如下:
167kb,好大。。。用了之后呢?神奇的事情发生了,一样的代码打包之后只有 48kb,nb(antd 也有一个类似的插件,是 babel-plugin-import,大家可以试一下)
只需要在 webpack 中添加如下代码即可:
module: {
rules: [
// other ...
{
loader: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/,
query: {
plugins: ['lodash'],
presets: [['@babel/env', { targets: { node: 6 } }]],
},
},
],
},
如果你的项目代码中,有很多不规范的 import 写法,用这个方法非常友好,但如果你新写的项目,还是推荐你使用如下方式:
使用 es 引入
查看 Lodash 源码的 tag,你会发现有一个 es 分支:
切换到这个 tag 查看代码,如下:
可以看到都是使用 ES Module 的模式引入的,因为 webpack 是一个模块打包器,所以她可以直接解析 ES Module 的代码,所以使用如下引用方式,也可以减小体积:(lodash-es 是一个单独的包;由于这里写都是 var 变量等兼容性很好的代码,所以不需要 babel 编译;推荐看 Lodash 源码的话,使用这个包)
// five.js
import { isEqual, map } from 'lodash-es';
console.log(isEqual(NaN, NaN));
map([1, 2, 3], console.log);
最终,只有 16kb,也很酷!
我是推荐使用 es 引入的,因为这可以减少 babel 编译的时间。(当然这只对于支持 ES Module 语法的才行,如果是 node 使用,还是乖乖地 require 具体文件吧,不过 node 也快要支持 ES Module 了)