1

问题描述:
我经常需要使用一些基础性的, 功能性函数, 比如数据去重, 对象合并等. 通常情况下,选择方向大致有3个:

  • 自己实现 API
  • 使用原生的 API
  • 使用 lodash 提供的 API

首先放弃 ‘自己实现API’ 这样的方式, 因为:

  1. 工作量大
  2. 即使实现了, 没有经过测试, 不够稳定
  3. 没有意义, 因为已经存在现成的, 别人实现的.

其次,如果原生提供的 API, 功能齐全, 兼容性好, 那么当然使用原生的 API.但是实际上原生 API 存在如下的一些问题:

  1. 语义不明, 比如说删除数组的某个元素, 通过 splice, 但是我们更希望通过 del 这个更明了的方法
  2. 功能不全, 比如说实现对象的拷贝, 通过 Object.assign(), 但是 Object.assign() 只能支持
    shadow copy, deep 不支持
  3. 兼容问题, 比如一些 ES6 出现的方法, 在低版本的设备中不支持
  4. API 不全, 也就是 API 不能覆盖我们所有的开发需求.
  5. 有些函数不符合我们的想法, 我们希望函数不会改变参与运算的数据结构, 但是原生的一些 API 会改变.

所以最终选择 lodash.js.

在基于 webpack 的环境中使用 lodash.

我们使用的姿势可以有如下几种:
1.整体通过 script 引入
这种引入方式不可行,体积太大, 会引入很多自己不需要的东西

2.单个引入
*在 main.js 里面引入, 以期望所有的组件都可以使用: 不可行, 在 main.js 里面引入, 只能在 main.js 里面生效

  • 在单个 .vue 组件里面引入
  • 将函数挂载到 window or Vue.prototype 上面 (推荐)
    创建 my-lodash.js
import {debounce} from 'lodash'
let _ = {
    debounce
}
window._ = _;

在 main.js 中引入此文件, 即可在全局环境中使用这些函数了.

关于引入 lodash 之后的体积变化

实验步骤:

我们先使用 vue-cli 创建一个新的, 空白的项目. 并且修改配置文件, 去掉js的压缩.

1. 对空白项目打包:

                  Asset       Size  Chunks                    Chunk Names
       static/js/app.js    15.4 kB       0  [emitted]         app
    static/js/vendor.js     338 kB       1  [emitted]  [big]  vendor
  static/js/manifest.js    6.06 kB       2  [emitted]         manifest

2. 在 App.vue 中引入 lodash/merge :

                  Asset       Size  Chunks                    Chunk Names
       static/js/app.js    15.6 kB       1  [emitted]         app
    static/js/vendor.js     409 kB       0  [emitted]  [big]  vendor       
  static/js/manifest.js    6.06 kB       2  [emitted]         manifest

3. 在 Hello.vue 中引入 lodash/merge :

                  Asset       Size  Chunks                    Chunk Names
       static/js/app.js    15.6 kB       1  [emitted]         app
    static/js/vendor.js     409 kB       0  [emitted]  [big]  vendor
  static/js/manifest.js    6.06 kB       2  [emitted]         manifest

观察可以发现

  1. 引入 lodash/merge之后, 体积增加了: 71k
  2. 不管你是在 App.vue 还是在 Hello.vue 中引入, 最终都会被打包到 vendor.js 中.

继续实验步骤, 现在我们加上压缩.
1. 不引入 lodash/merge

                  Asset       Size  Chunks             Chunk Names
       static/js/app.js    11.7 kB       0  [emitted]  app
    static/js/vendor.js     110 kB       1  [emitted]  vendor
  static/js/manifest.js    1.49 kB       2  [emitted]  manifest

2. 引入 lodash/merge:

                  Asset       Size  Chunks             Chunk Names
    static/js/vendor.js     125 kB       0  [emitted]  vendor
       static/js/app.js    11.8 kB       1  [emitted]  app
  static/js/manifest.js    1.49 kB       2  [emitted]  manifest

观察可以发现: 引入 lodash/merge 之后, 体积增加了 15k.

考虑新的问题:
我们在项目中引入了 lodash/merge 函数, 然后我们使用的一个第三方的 npm lib, 它也使用了lodash/merge, 此时打包, 会有什么样的结果?

第三方 lib 的大小

    Asset     Size  Chunks             Chunk Names
 index.js  24.4 kB       0  [emitted]  app
style.css  3.75 kB       0  [emitted]  app

引入第三方 lib, 打包之后的大小:

                  Asset       Size  Chunks             Chunk Names
    static/js/vendor.js     149 kB       0  [emitted]  vendor
       static/js/app.js      12 kB       1  [emitted]  app
  static/js/manifest.js    1.49 kB       2  [emitted]  manifest

观察:
相比较而言, 增加了 24k 大小, 也就是说我们引入的第三方 lib, 大小为 24k, 和我们看到的结果一致.

这个结果反馈出来的是:
第三方 lib 中, 引用的 lodash/merge 函数, 然后项目中自己也使用了 lodash/merge 函数。
此时, 二者之间并没有公用.

面对这个结果, 我们能做的是什么呢?

  1. 让 第三方 lib, 就是我自己的第三方 lib, 在打包的时候, 不会把它的依赖项目一起打包起来.
  2. 在第三方 lib 的 package.json 里面声明它的依赖项目.

用户在下载第三方 lib 的时候, 会一起把在 package.json 中的依赖项目一起下载.

最后我们来讨论下:
我们说引入了一个 lodash/merge 函数, 项目的体积在压缩后就增加了 15k, 那么如果多引入几个函数呢?

引入 lodash/assign + 8k
引入 lodash/concat + 1k
引入

import _assign from 'lodash/assign'
import _concat from 'lodash/concat'
import _map from 'lodash/map'
import _keyBy from 'lodash/keyBy'
import _orderBy from 'lodash/keyBy'
import _sampleSize from 'lodash/sampleSize'
import _reject from 'lodash/reject'
import _isArray from 'lodash/isArray'
import _isBuffer from 'lodash/isBuffer'
import _merge from 'lodash/merge'

最终项目大小增加了 29k.


云水摇啊摇
362 声望15 粉丝

不信人间有白头.