Lodash是非常多人使用的JavaScript的工具函式庫,提供許多方便用來操作陣列、物件、字串、數值的函數。Webpack是JavaScript的模組建置工具,運行在Node.js上,它可以將零散的JavaScript檔案用各式工具優化並打包起來,加快網頁的載入時間。由於Lodash有很多零散的函數,一般專案應該也用不到其中的一半,所以它十分需要利用Webpack來砍掉沒有用到的程式碼,以減少網頁上JavaScript程式碼的體積。



本篇文章不會介紹用Webpack打包檔案的方式,如果您還不熟悉這部份的話,請先閱讀這篇文章:

https://magiclen.org/webpack/

Lodash官方網站:

https://lodash.com/

將Lodash加入現有的Webpack專案中

安裝Lodash套件

為了要能夠在Webpack中使用到Lodash,我們需要安裝lodash套件。指令如下:

npm i --save lodash

加入lodash-webpack-plugin外掛

lodash-webpack-plugin外掛可以幫助我們設定要開啟Lodash的哪些功能,其還有用到babel-plugin-lodash這個套件,必須要和Babel搭配使用。

在終端機執行以下指令來安裝:

npm i -D lodash-webpack-plugin babel-plugin-lodash

webpack.config.js設定檔中,將lodash-webpack-plugin的實體加進plugins欄位的陣列中。

如下:

const LodashWebpackPlugin = require('lodash-webpack-plugin');

module.exports = {
    ...
 
    plugins: [
        ...
 
        new LodashWebpackPlugin()
 
        ...
    ]
 
    ...
};

接著在載入器規則中的babel-loader的選項(options)內加上plugins欄位,將lodash加進plugins欄位的陣列中。

如下:

module.exports = {
    ...
 
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        plugins: ['lodash'],
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    }
 
    ...
};

如此一來在JavaScript程式中,就可以用如以下的方式來使用Lodash,而不必擔心會將整個Lodash的程式碼都打包進輸出的JavaScript檔案中。

import _ from 'lodash';

console.log(_.isElement(document.body));

設定Lodash要啟用的功能

lodash-webpack-plugin外掛預設開放的Lodash功能是最精簡的,如果要啟用更多Lodash提供的功能,要在建立lodash-webpack-plugin的實體時,透過建構子傳入物件來設定要啟用的特色(feature)。

例如:

const LodashWebpackPlugin = require('lodash-webpack-plugin');

module.exports = {
    ...
 
    plugins: [
        ...
 
        new LodashWebpackPlugin({
            collections: true,
            paths: true,
        })
 
        ...
    ]
 
    ...
};

不過也並不是所有的特色都要自行啟用,lodash-webpack-plugin也會自動去看JavaScript程式碼中有用到的Lodash函數,來決定要自動強制啟用哪些特色。

需要手動啟用的特色如下。

shorthands

當這個特色啟用時,走訪相關的回呼(callback)函數就可以支援簡略的寫法。

例如:

let users = [
    {user: 'barney', inactive: false},
    {user: 'fred', inactive: true},
    {user: 'pebbles', inactive: true}
];

console.log(_.dropRightWhile(users, function (o) {
    return o.inactive;
}));

可以簡寫為:

console.log(_.dropRightWhile(users, {inactive: true}));
console.log(_.dropRightWhile(users, ['inactive', true]));
console.log(_.dropRightWhile(users, 'inactive'));
caching

用來加速cloneDeepisEqualuniq等函數。

collections

讓物件也可以使用陣列用的集合類的函數。

例如:

function square(n) {
    return n * n;
}

console.log(_.map([4, 8], square));

[4, 8]這個陣列也可以換成物件,如下:

console.log(_.map({ 'a': 4, 'b': 8 }, square));
exotics

使Lodash支援JavaScript的SetMapSymbolArrayBuffer、型別陣列(Typed Arrays,例如Int8ArrayUint8Array)和Node.js的Buffer

guards

讓Lodash更能正常地在一些比較特別的場景下工作。

例如:

let a = new Array(3);

a[1] = '123';

console.log(_.keys(a));

以上的陣列a是一個稀疏矩陣(Spare Array),,它的長度雖然被定義為3,但它在記憶體中實際並沒有那麼長。在不啟用guards特色的情況下,上面這個程式只會印出Array [ "1" ],但如果啟用guards特色,上面這個程式就會印出Array(3) [ "0", "1", "2" ],看起來直覺多了!

metadata

這個應該是用來Debug的特色,可以讓Lodash產生出來的函數在使用toString()方法的時候更加易讀。

例如:

console.log(_.ary(parseInt, 1).toString());

在沒有啟用metadata特色的情況下,會印出如下的文字:

function s(){for(var y=arguments.length,v=Array(y),b=y;b--;)v[b]=arguments[b];if(T)var d=c(s),h=u(v,d);if(x&&(v=o(v,x,g,T)),S&&(v=e(v,S,w,T)),y-=h,T&&y<M){var I=a(v,d);return f(n,r,t,s.placeholder,m,v,I,j,O,M-y)}var $=_?m:this,k=P?$[n]:n;return y=v.length,j?v=l(v,j):E&&y>1&&v.reverse(),A&&O<y&&(v.length=O),this&&this!==p&&this instanceof s&&(k=F||i(k)),k.apply($,v)}

在啟用metadata特色的情況下,會印出如下的文字:

function parseInt() {
/* [wrapped with _.ary] */
    [native code]
}
deburring

例如:

console.log(_.deburr('déjà vu'));

在沒有啟用deburring特色的情況下,會印出以下文字:

déjà vu

在啟用metadata特色的情況下,會印出以下文字:

deja vu
paths

讓Lodash的欄位相關的函數可以支援用陣列或是.來指定頂層以下的欄位。

例如:

const object = {
    a: {
        b: 2
    }
};

_.set(object, ['a', 'b'], 3);

console.log(_.get(object, 'a.b'));
placeholders

啟用placeholders特色之後就可以使用底線_來省略掉不想明確賦值的參數。

例如:

function greet(greeting, name) {
    return greeting + ' ' + name;
}

let sayHelloTo = _.partial(greet, _);

console.log(sayHelloTo('fred'));

以上partial函數第二個參數傳入的_會自動被__lodash_placeholder__字串所取代。

chaining

這個特色應該是要讓Lodash能夠使用chain函數,但並沒有實質作用。