引入 Lodash 的最佳方式

12,767 阅读3分钟

Lodash 是我们很常用的一个库(npm 周下载量是 2.8 亿次,react 是 0.8 亿次,webpack 是 1.1 亿次),但很多人引入 Lodash 并不优雅(打包后的体积过大),本文就带大家来看看 Lodash 常用的几种引入方式。

先写结论,想看细节的话,可以继续。本文所有的代码都在这个仓库中。

结论

  1. 直接写 import _ from 'lodash';import { isEqual } from 'lodash'; 引入的是整个 Lodash 包,约 70kb 左右(压缩后),import isEqual from 'lodash/isEqual'; 引入的单个使用到的文件,约 15kb 左右(压缩后)。
  2. 对于已有的项目,很多代码都是前两种写法的,那也不能一个一个的去改吧,是的,可以使用 babel-plugin-lodash 来帮助我们把前两种 变成第三种写法。
  3. 对于新写的代码,推荐使用 lodash-es 包,因为这可以省去 babel 编译的时间。

直接引入

// one.js
import _ from 'lodash';

console.log(_.isEqual(NaN, NaN));

build 后生成的 js 大小如下:

image.png

解构引入

// two.js
import { isEqual } from 'lodash';

console.log(isEqual(NaN, NaN));

build 后如下:

image.png

可以看到,都是 72 kb。

具体文件引入

// three.js
import isEqual from 'lodash/isEqual';

console.log(isEqual(NaN, NaN));

build 后如下:

image.png

咦,这个时候我们看到了神奇的事情,打包后只有 15 kb,这就说明 webpack 只打包了用到的代码,其他没用到的并没有打包进去。 说明文档也是这样指出的:

image.png

那我们就一直这样引入吧,还能做到按需加载,岂不是很 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 可以使用,它做的就是一些代码转换,如下:

image.png

这个 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 后如下:

image.png

167kb,好大。。。用了之后呢?神奇的事情发生了,一样的代码打包之后只有 48kb,nb(antd 也有一个类似的插件,是 babel-plugin-import,大家可以试一下)

image.png

只需要在 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 分支:

image.png

切换到这个 tag 查看代码,如下:

image.png

可以看到都是使用 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);

image.png

最终,只有 16kb,也很酷!

我是推荐使用 es 引入的,因为这可以减少 babel 编译的时间。(当然这只对于支持 ES Module 语法的才行,如果是 node 使用,还是乖乖地 require 具体文件吧,不过 node 也快要支持 ES Module 了)