zoukankan      html  css  js  c++  java
  • Lodash 浓缩

    Lodash 是个十分有用的工具库,但我们往往只需要其中的一小部分函数。这时,整个 lodash 库就显得十分庞大,我们需要减小 lodash 的体积。

    cherry-pick 方法

    Lodash 官方在 npm 上为每个方法维护了独立的包,便于我们直接引用。举个例子,如果我们需要lodash.chunk方法,可以直接安装lodash.chunk这个 npm 包,在代码中 import 即可:

    1
    2
    3
    import _chunk from 'lodash.chunk';
    const result = _chunk(['a', 'b', 'c', 'd'], 2);
    console.log(result);

    这样的弊端很明显,我们如果需要使用一个新方法,就要重新 install 一个新包并 require 进来。另外,每个包之间会有一部分重复(公共)方法会被重复打包,也会增大最终的打包体积。更好的解决办法,是直接从 lodash 完整库内导入方法:

    1
    2
    import flatten from 'lodash/flatten';
    import flatMap from 'lodash/flatMap';

    由于 lodash 库中,每个方法都以独立模块封装,这样的引入方法,在 webpack 打包时,只会按需取指定的两个模块进行打包。从flatten 和 flatMap) 的代码可以看出,二者都用到了./.internal/baseFlatten.js这个模块,在 webpack 打包时,这个模块就变成了公共模块,这就避免了引入两个独立方法的包带来的重复。这种引入方式,官方叫做 “cherry-pick methods”,就像捡樱桃一样,捡自己需要的方法。

    babel-plugin-lodash

    然而,cherry-pick 方法的书写习惯,和我们平时使用第三方库的书写习惯并不一致。我们更习惯于直接 import 整个库:

    1
    2
    3
    import _ from 'lodash';
    _.flatten([1, [2, 3], [4]])
    _.flatMap([1, 2], n => [n, n])

    这时,就是babel-plugin-lodash库发挥作用的时候。在 babel 编译代码时,这个插件可以自动把这种代码

    1
    2
    3
    4
    5
    import _ from 'lodash';
    import { add } from 'lodash/fp';

    const addOne = add(1);
    _.map([1, 2, 3], addOne);

    转化为

    1
    2
    3
    4
    5
    import _add from 'lodash/fp/add';
    import _map from 'lodash/map';

    const addOne = _add(1);
    _map([1, 2, 3], addOne);

    不过,这里有一些额外限制:必须要引入 babel(6以上版本);必须要使用 ES2015 的方式引入包(即 import 的方式)。

    lodash-webpack-plugin

    在这一步的基础上,我们还可以使用 lodash-webpack-plugin 进一步减包。它的原理是将我们用到的方法(和间接用到的内部方法)使用更简单的方法替代。具体的方法对应关系,参照源代码中的mapping.js使用方法也非常简单,只需要在 webpack 配置中引入该 plugin ,即可将所有的 cheery-pick 引入的方法自动进行转换。

    需要注意的问题

    一般介绍 lodash 打包优化的文章,介绍到这里就算结束了。但是,lodash-webpack-plugin 还有一系列的 feature 配置,它们的作用又是什么?实际上,经过 lodash-webpack-plugin 转化的 lodash 函数,已经和文档中对应的函数不完全等价,因此,如果我们用到了一些特定的特性,我们需要通过调整这些配置,保证我们的代码正常运行。

    要关注这些配置的作用,只需要关注mapping.js这个文件,其中配置了featuresoverrides两个变量。features中每一项对应一个开关,每个开关则对应着若干组替换规则。以cloning为例,当对应配置关闭(默认即为关闭)时,插件将把内部的_._baseClone(暂且这样表示)方法替换为_.identity方法。而overrides变量中的每一项表示:只要我们引用了对应方法,则打开对应配置开关。

    了解了这一点,我们再谈谈这个配置是怎样影响对应方法的。以_.sortBy方法为例,在它的源代码中(注:由于我们使用 npm 安装,因此需要查看 es 分支的源代码),我们可以看到它使用了四个内部库:

    1
    2
    3
    4
    import baseFlatten from './_baseFlatten.js';
    import baseOrderBy from './_baseOrderBy.js';
    import baseRest from './_baseRest.js';
    import isIterateeCall from './_isIterateeCall.js';

    flattening规则中,内部_baseFlatten将会被替换为_.head方法。本来根据_.sortBy文档,下列代码可以正常运行:

    1
    2
    3
    4
    5
    6
    7
    8
    var users = [
    { 'user': 'fred', 'age': 48 },
    { 'user': 'barney', 'age': 36 },
    { 'user': 'fred', 'age': 40 },
    { 'user': 'barney', 'age': 34 }
    ];

    _.sortBy(users, function(o) { return o.user; });

    经过插件转化后,这种写法将会抛出异常。我们只能使用下列写法:

    1
    _.sortBy(users, [function(o) { return o.user; }]);

    收到类似影响的函数还有_.overArgs,_.flow等几个方法。同理,_.get_.has等方法,也会_baseGet方法被替换受到影响。

    要解决这个问题,我们需要校验自己的代码中,有没有用到官方描述的Feature Sets中类似的特性,然后更改自己的代码,或者开启对应的特性配置。一般情况下,开启 flattening 和 paths 配置可以解决大部分问题。

  • 相关阅读:
    互联网秒杀设计
    生产者消费者模式实现
    Ping CAP CTO、Codis作者谈redis分布式解决方案和分布式KV存储
    VIM使用学习笔记 : 按键说明
    Cookie的有效访问路径
    简单的Cookie记录浏览记录案例
    认识Cookie和状态管理
    Java异常
    Java接口基础
    String常用方法
  • 原文地址:https://www.cnblogs.com/jcxfighting/p/8528889.html
Copyright © 2011-2022 走看看