268

I had a pull request feedback below, just wondering which way is the correct way to import lodash?

You'd better do import has from 'lodash/has'.. For the earlier version of lodash (v3) which by itself is pretty heavy, we should only import a specidic module/function rather than importing the whole lodash library. Not sure about the newer version (v4).

import has from 'lodash/has';

vs

import { has } from 'lodash';

Thanks

Bill
  • 17,872
  • 19
  • 83
  • 131
  • 7
    See [this answer](https://stackoverflow.com/a/45305804/1541563) for a more in-depth discussion as to why the latter can still incur a performance optimization in some environments such as Webpack. It's due to the use of static-analysis and tree-shaking. – Patrick Roberts Jul 25 '17 at 18:17
  • Does this answer your question? [How to Import a Single Lodash Function?](https://stackoverflow.com/questions/43479464/how-to-import-a-single-lodash-function) – Henke Feb 10 '21 at 16:31

10 Answers10

327

import has from 'lodash/has'; is better because lodash holds all it's functions in a single file, so rather than import the whole 'lodash' library at 100k, it's better to just import lodash's has function which is maybe 2k.

Rich
  • 5,603
  • 9
  • 39
  • 61
Bill
  • 17,872
  • 19
  • 83
  • 131
  • Is this true for both v3 and v4? – mc9 Aug 04 '16 at 01:40
  • @SungWonCho i think so, i am currently on 3.9.1, so i am sure v4 will do the same – Bill Aug 04 '16 at 03:44
  • I can confirm that your answer works for v4 as well. – mc9 Aug 04 '16 at 04:42
  • 2
    @GeorgeKatsanos you just import the function you want to use, you don't need '_' – Bill Oct 29 '16 at 11:57
  • Maybe it would be useful to add to your answer that you need to install the separate npm method package in order to be able to import it.. For example `npm install lodash/has - - save` – George Katsanos Oct 30 '16 at 02:33
  • what about the dot syntax: `import has from 'lodash.has'`? – faceyspacey.com Oct 30 '16 at 14:20
  • 10
    @GeorgeKatsanos `'lodash/has'` isn't a separate package. There's a file called `has.js` in the root of the regular `'lodash'` package, and `import has from 'lodash/has'` (or `const has = require ('lodash/has`) will load that file. There *are* separate method packages on npm, but they use the "dot syntax": `'lodash.has'`. This would also be a valid way to go about it if you don't mind installing a separate package for *every* method you use (and potentially making your `package.json` massive as a result). – daemone Nov 30 '16 at 15:26
  • 95
    I have to add here that, if you use webpack 2 or rollup (a bundler that supports tree shaking), then `import { has } from 'lodash'` would work the same way, since the rest will be stripped out – Alex JM Dec 05 '16 at 10:08
  • Is it okay to import functions that are already defined in the global scope, for example, `import isFinite from 'lodash/isFinite';`, or `import find from 'lodash/find';`? – nnyby Jan 11 '17 at 19:59
  • @nnyby that's fine, but why would you want to declare at global scope? if you want to do global scope, you will have to do `import find from 'lodash/find'; global.find = find;` i don't recommend that tho – Bill Jan 12 '17 at 03:08
  • @AlexJM you commented a while ago, but may I ask what plugin you would need to accomplish that with webpack 2? or does it do that automatically? – PDN Jul 23 '17 at 17:58
  • 3
    @PDN webpack 2 tree shaking should do it for you automatically – Bill Jul 24 '17 at 00:22
  • 30
    unlike some others, my tree shaking wouldn't work with the more obvious syntax, it was only after I switched to lodash-es and used the `import has from 'lodash-es/has'` syntax did I get full tree shaking. went from 526KB to 184KB, see https://stackoverflow.com/questions/41991178/correct-way-of-importing-and-using-lodash-in-angular – Brandon Culley Aug 03 '17 at 18:59
  • @GeorgeKatsanos it's unnecessary to `import _ from 'lodash'` if you call range without preceding it by an underscore: `range(.,.)` as opposed to `_.range(.,.)`. – darkmoves Jun 29 '18 at 16:22
  • @AlexJM i just tried your suggestion with webpack 3+ and it doesn't work. Getting full library loaded. – tylik Nov 06 '18 at 22:52
  • @AlexJM is there anywhere else you are import the entire loadash? – Bill Nov 06 '18 at 23:33
150

If you are using webpack 4, the following code is tree shakable.

import { has } from 'lodash-es';

The points to note;

  1. CommonJS modules are not tree shakable so you should definitely use lodash-es, which is the Lodash library exported as ES Modules, rather than lodash (CommonJS).

  2. lodash-es's package.json contains "sideEffects": false, which notifies webpack 4 that all the files inside the package are side effect free (see https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free).

  3. This information is crucial for tree shaking since module bundlers do not tree shake files which possibly contain side effects even if their exported members are not used in anywhere.

Edit

As of version 1.9.0, Parcel also supports "sideEffects": false, threrefore import { has } from 'lodash-es'; is also tree shakable with Parcel. It also supports tree shaking CommonJS modules, though it is likely tree shaking of ES Modules is more efficient than CommonJS according to my experiment.

Legends
  • 21,202
  • 16
  • 97
  • 123
kimamula
  • 11,427
  • 8
  • 35
  • 29
  • I converted all of my lodash imports to `import { ... } from 'lodash-es';` My bundle still includes the whole library. – Isaac Pak Jan 28 '19 at 00:55
  • 3
    @IsaacPak Make sure that you are not transpiing ES modules to CommonJS. If you are using TypeScript, you have to set `--module` compiler option as `es6`, `es2015` or `esnext`. – kimamula Jan 28 '19 at 02:09
  • I'm not using TypeScript and my .babelrc env preset is set to `modules: false` so they aren't transpiled to CommonJS. I am using Bruce's solution now which seems to work. Thanks for your contribution, I'm sure it works but I just don't have the setup for it. – Isaac Pak Jan 28 '19 at 11:47
  • unfortunately, can't use lodash-es with jest at this point: https://github.com/facebook/jest/issues/4842#issuecomment-491434065 – apollo Oct 13 '19 at 23:10
  • @IsaacPak read: [treeshaking](https://webpack.js.org/guides/tree-shaking/#conclusion) – Legends Jan 13 '20 at 22:18
  • 3
    `import has from 'lodash-es/has'` and `import {has} from 'lodash-es'` both variants do treeshaking when using `webpack-4` – Legends Jan 13 '20 at 23:36
  • @Legends is correct. Lodash v4 with Webpack v4 does not require -es for it to be tree-shakeable. See: https://www.azavea.com/blog/2019/03/07/lessons-on-tree-shaking-lodash/ – micnguyen Jan 14 '20 at 02:25
  • Didn't say that. `Lodash` uses `CommonJS` syntax, you cannot import from a CJS module. So you have to use `lodash-es` which uses `ES` module syntax and therefore enables treeshaking in webpack. – Legends Jan 14 '20 at 13:44
  • Does **not** work when using the `jest`: https://github.com/facebook/create-react-app/issues/5241 – Victor Jul 27 '21 at 07:42
25

Import specific methods inside of curly brackets

import { map, tail, times, uniq } from 'lodash';

Pros:

  • Only one import line(for a decent amount of functions)
  • More readable usage: map() instead of _.map() later in the javascript code.

Cons:

  • Every time we want to use a new function or stop using another - it needs to be maintained and managed

Copied from:The Correct Way to Import Lodash Libraries - A Benchmark article written by Alexander Chertkov.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Nikhil
  • 1,267
  • 15
  • 16
  • 2
    Thanks for the useful answer. However, I like the `_.map()` syntax to be clear that an external library is being used. Is `import _ from 'lodash'` equally efficient as your suggestion or is there another way of being able to use this syntax? – Toivo Säwén Jan 21 '20 at 14:10
  • 2
    @ToivoSäwén I completely agree and prefer the explicit `_.map()` syntax as well. Were you able to figure out a way to maintain that while doing es6 imports and tree-shaking? – Raj Apr 23 '20 at 05:45
  • This answer seems like a simple copy and paste from https://www.blazemeter.com/blog/the-correct-way-to-import-lodash-libraries-a-benchmark. If so, it would be better to provide credit. – Lacek Aug 14 '20 at 09:02
  • 1
    `import { map as _map, tail } from 'lodash'` – McKay Dec 03 '20 at 22:29
  • 1
    the article linked actually states the smallest bundle size, without some special plugins, is "one-by-one or ‘modules’ import". e.g. `import map from "lodash/map"` – TurtleTread Mar 16 '22 at 08:12
11

You can import them as

import {concat, filter, orderBy} from 'lodash';

or as

import concat from 'lodash/concat';
import orderBy from 'lodash/orderBy';
import filter from 'lodash/filter';

the second one is much optimized than the first because it only loads the needed modules

then use like this

pendingArray: concat(
                    orderBy(
                        filter(payload, obj => obj.flag),
                        ['flag'],
                        ['desc'],
                    ),
                    filter(payload, obj => !obj.flag),
Charith Jayasanka
  • 4,033
  • 31
  • 42
4

If you are using babel, you should check out babel-plugin-lodash, it will cherry-pick the parts of lodash you are using for you, less hassle and a smaller bundle.

It has a few limitations:

  • You must use ES2015 imports to load Lodash
  • Babel < 6 & Node.js < 4 aren’t supported
  • Chain sequences aren’t supported. See this blog post for alternatives.
  • Modularized method packages aren’t supported
Orlando
  • 9,374
  • 3
  • 56
  • 53
2

I just put them in their own file and export it for node and webpack:

// lodash-cherries.js
module.exports = {
  defaults: require('lodash/defaults'),
  isNil: require('lodash/isNil'),
  isObject: require('lodash/isObject'),
  isArray: require('lodash/isArray'),
  isFunction: require('lodash/isFunction'),
  isInteger: require('lodash/isInteger'),
  isBoolean: require('lodash/isBoolean'),
  keys: require('lodash/keys'),
  set: require('lodash/set'),
  get: require('lodash/get'),
}
Aronanda
  • 191
  • 1
  • 2
  • 3
2

I think this answer can be used in any project easily and brings the best result with less effort.

For Typescript users, use as following :

// lodash.utils.ts
export { default as get } from 'lodash/get';
export { default as isEmpty } from 'lodash/isEmpty';
export { default as isNil } from 'lodash/isNil';
...

And can be used the same way as importing lodash :

//some-code.ts
import { get } from './path/to/lodash.utils'

export static function getSomething(thing: any): any {
    return get(thing, 'someSubField', 'someDefaultValue')
}

Or if you prefer to keep the _ to avoid conflicts (ex. map from rxjs vs lodash)

//some-other-code.ts
import * as _ from './path/to/lodash.utils'

export static function getSomething(thing: any): any {
    return _.get(thing, 'someSubField', 'someDefaultValue')
}

UPDATE : Seems like the right way to export is :

export * as get from 'lodash/get';
export * as isEmpty from 'lodash/isEmpty';
export * as isNil from 'lodash/isNil';
...

But there is a weird collision with @types/lodash, I've removed this type package because I would get this error :

Module '"/../project/node_modules/@types/lodash/cloneDeep"' uses 'export =' and cannot be used with 'export *'.ts(2498)

UPDATE :

After some digging, I've turned tsconfig.json feature esModuleInterop to true, and it allows me to do the following :

import get from 'lodash/get';
import isEmpty from 'lodash/isEmpty';
import isNil from 'lodash/isNil';
...

export { get, isEmpty, isNil, ... };

Note that this affects all your imports in your projects that has been defined as import * as lib from 'lib'. Follow the documentation to be sure it's suitable for you.

0

import { cloneDeep, groupBy } from 'lodash';

I think this is simpler when you don't need to convert array to lodash object by using _.

const groupData = groupBy(expandedData, (x) => x.room.name);

Nam Do
  • 83
  • 1
  • 7
-2

For those who want to keep using _ , then just import them like this:

import groupBy from 'lodash/groupBy';
import filter from 'lodash/filter';
import get from 'lodash/get';

window._ = {groupBy, filter, get};
Madian Malfi
  • 595
  • 1
  • 8
  • 26
-7

I think the more cleaner way of importing lodash is just like this:-

import _ from 'lodash'

then you can use what ever you want just by using this underscore just like this:-

_.has()
Taher
  • 11,902
  • 2
  • 28
  • 44
Rtesa
  • 1
  • 1