Loadsh 是一个一致性、模块化、高性能的 JavaScript 实用工具库。在数据操作时,我们经常会用的 loadsh 封装好的一些工具方法,但是并不想把整个包打包进项目里面。
以下提供几个按需打包 lodash 的方法。
使用方法:
import {isEmpty, isObject, cloneDeep} from 'lodash';
存在问题:
当我们仅使用 lodash 其中一两个方法的时候,webpack 会将这个库打包进去,造成了不必要的资源浪费;
从 vue-cli@3 提供的打包分析工具可以看到,打包后 lodash 有 70.7kb。
解决办法有 3 种:
1. 单独引入
Lodash 中的每个函数在 NPM 都有一个单独的发布模块,我们可以只引入我们需要的模块。
import isEqual from 'lodash.isequal';
// 或者
import difference from 'lodash/difference';
在模块比较多的时候,这种写法比较麻烦,不推荐。
2.使用插件优化
$ npm i --save lodash
$ npm i --save-dev lodash-webpack-plugin babel-core babel-loader babel-plugin-lodash babel-preset-env webpack
webpack.config.js
var LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
var webpack = require('webpack');
module.exports = {
module: {
rules: [{
use: 'babel-loader',
test: /\.js$/,
exclude: /node_modules/,
options: {
plugins: ['lodash'],
presets: [['env', {modules: false, targets: {node: 4}}]]
}
}]
},
plugins: [new LodashModuleReplacementPlugin(), new webpack.optimize.UglifyJsPlugin()]
};
以上工作完成了,在每个你需要使用 lodash 函数的文件中只需要引用一次 lodash,即可调用任意函数而不会造成完全打包。
3.使用 lodash-es
tree-shaking 作为 rollup 的一个杀手级特性,能够利用 ES6 的静态引入规范,减少包的体积,避免不必要的代码引入,webpack2 也很快引入了这个特性。
要用到 tree-shaking,必然要保证引用的模块都是 ES6 规范的。lodash-es 是着具备 ES6 模块化的版本,只需要直接引入就可以。
import {isEmpty, isObject, cloneDeep} from 'lodash-es';
可以看到,使用优化后,lodash 从原来的 70.7kb 减少到了20.2kb效果还是很明显的。
问题
根据方法2使用了插件后,确实是起作用了,用webpack-bundle-analyz插件分析可以看出lodash打入包中的体积已经变小了很多。
后来我在项目中又使用了路由懒加载,再用webpack-bundle-analyz插件一分析,发现lodash被重复打包了两份。一份体积较小,一份全量。
几经尝试,后来的解决办法是:在模块中被引用的lodash,通过方法1(单独引入)来引入。
import lodashAssign from 'lodash/assign'
lodashAssign(newObj, obj)
而在store/actions.js,以及util下的js文件中的lodash还是保留方法2的方式来引入。也就是:
import _ from 'lodash'
_.compact(myarr)
用webpack-bundle-analyz插件分析,问题解决:
我怀疑问题的出现,是因为延迟加载的模块中所引用的lodash并没有被 lodash-webpack-plugin 处理,所以就被全量包含进来了。
不过这也仅是我的猜测而已,如果有知道原因的大佬,跪请告知~