lodash | 如何正确的 import lodash
前言
通常前端都会导入一些好用的第三方套件,但是有时后导入的套件并非是基于 es module 进行开发,webpack 没办法发挥 tree shaking 的功能,在 import 时一不注意就会载入一堆没有必要的 function。
在这篇文章中以 lodash 作为举例, lodash 是个能够帮我们处理各种资料的函式库,减少写一些比较琐碎的程式码。但因为 lodash 在 2012 年就被开源,历史较为久远,可能有多种缘故,导致目前 lodash 本身并不是使用 es module。所以如果在意 bundle size 的大小,就要特别注意在 import lodash 的方式。
先安装我们需要的 lodash :
yarn add lodash
安裝 webpack-bundle-analyzer
yarn add -D webpack-bundle-analyzer
webpack.config.js 中加入以下代码
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
然后用 yarn start 启动 server ,跟方法 1 一样,除了原本专案的 8080 port 之外,你还会看到在 8888 port 启动了 webpack-bundle-analyzer
一、分析用不同的方式 import lodash 的结果
第一种方式:不指定 function 的路径
不指定 function 路径也就像我们平常使用 named exports 的 module 一样,我们稍微修改 App.js 的程式码,在 component 里面加上 lodash 的 isEmpty:
import React from 'react';
import { isEmpty } from 'lodash';
const App = ({ title }) => (
<div>{isEmpty(title) ? 'Title is Empty!!' : title}</div>
);
export default App;
接着,我们用 webpack bundle analyzer 看看使用这种 import 方式的 bundle size 为多少。
很夸张的是,明明只有用到 isEmpty 这个 function,结果 lodash 打包后的档案大小却足足有 531KB, 不禁让人怀疑 isEmpty 是多么伟大的 function 😆,做了包山包海的事情。
第二种方式:指定 function 的路径
接下来,我们换一种 import 的方式,看看对 bundle size 会有什么影响。
天哪,换一种方式结果让 lodash 打包后的大小足足少了 22 倍,这是什么魔法?
import isEmpty from 'lodash/isEmpty';
为什么两种 import 的方式会导致 bundle size 不一样
我们必须知道 lodash 是一个使用 UMD (Universal Module Definition) 的套件,这意味着 lodash 并不满足在 webpack 中的 tree-shaking 必须是 es module 的条件。所以第一种方法实际上会载入完整的 lodash ,最终导致 bundle size 莫名的巨大;而第二种方法就是只载入一个档案,再从档案中拿出我们需要的 isEmpty,如此一来就不用担心载入整包 lodash 的问题。
可是如果都要像第二种方法这样写 code 实际上有点麻烦,而且团队可能一开始没考虑到这个问题,程式码已经有多处使用第一种方法,改起来十分麻烦。
二、如何正确的 import lodash
以下提供两种我认为比较简易的解法,可以用最少量的配置,达到降低 bundle size 的方法。
使用 lodash-es 而不是 lodash
这也是 lodash 的 GitHub 提到的作法,lodash 的 GitHub 中写道:「Looking for Lodash modules written in ES6 or smaller bundle sizes? Check out lodash-es.」,所以第一种解法便是改用 lodash-es:
// 下載 lodash-es
yarn add lodash-es
// 修改程式碼 lodash 的引用,變成使用 lodash-es
import { isEmpty } from 'lodash-es';
你可以看到 bundle size 顺利地从 531KB 降低到 24KB 左右,与上面提到的第二种 import 的方法有异曲同工之妙。
至于为什么第二种 import 方法与用 lodash-es 最终打包后的档案大小不一样,这又是另一个议题了。
使用 babel-plugin-import
如果你不想动到大量的程式码,上面使用 lodash-es 意味者必须全域取代 lodash 的引用,其实有另一个解法是使用 babel 的插件,让 babel 帮我们从第一种 import 的方式改成第二种。
首先,安装 babel-plugin-import 这个插件:
yarn add -D babel-plugin-import
然后修改 .babelrc 中的设定:
{
...
"plugins": [
[
"import",
{
"libraryName": "lodash",
"libraryDirectory": "",
"camel2DashComponentName": false
}
]
]
}
再用 webpack bundle analyzer 看看打包后的档案大小,可以看到档案打小与第二种 import 的方式一样都是 24.31KB,同样成功地降低 bundle size。
结论
在这篇文章中我们了解了如何透过 webpack bundle analyzer 分析打包后的档案,并且透过这个工具看到不同 import lodash 方式对于 bundle size 的影响。
针对如何降低 lodash 被打包后的档案大小,本文提供两种方式,分别是使用 lodash-es 全域取代原本 lodash 的引用,或使用 babel-plugin-import 非侵入式的改动大量的程式码,而是在打包时处理,这两种方式都可以达到不把完整的 lodash 都打包进 bundle 的结果,就看各位如何选择啰!
原文链接:
https://medium.com/starbugs/the-correct-way-to-import-lodash-libraries-bdf613235927