204

Using webpack, I'm trying to import isEqual since lodash seems to be importing everything. I've tried doing the following with no success:

import { isEqual } from 'lodash'

import isEqual from 'lodash/lang'

import isEqual from 'lodash/lang/isEqual'

import { isEqual } from 'lodash/lang'

import { isEqual } from 'lodash/lang'
Patrick Hund
  • 19,163
  • 11
  • 66
  • 95
cvdv
  • 2,691
  • 3
  • 14
  • 29

11 Answers11

315

You can install lodash.isequal as a single module without installing the whole lodash package like so:

npm install --save lodash.isequal

When using ECMAScript 5 and CommonJS modules, you then import it like this:

var isEqual = require('lodash.isequal');

Using ES6 modules, this would be:

import isEqual from 'lodash.isequal';

And you can use it in your code:

const obj1 = {username: 'peter'};
const obj2 = {username: 'peter'};
const obj3 = {username: 'gregory'};

isEqual(obj1, obj2) // returns true
isEqual(obj1, obj3) // returns false

Source: Lodash documentation

After importing, you can use the isEqual function in your code. Note that it is not a part of an object named _ if you import it this way, so you don't reference it with _.isEqual, but directly with isEqual.

Alternative: Using lodash-es

As pointed out by @kimamula:

With webpack 4 and lodash-es 4.17.7 and higher, this code works.

import { isEqual } from 'lodash-es';

This is because webpack 4 supports the sideEffects flag and lodash-es 4.17.7 and higher includes the flag (which is set to false).

Why Not Use the Version With the Slash? Other answers to this question suggest that you can also use a dash instead of a dot, like so:

import isEqual from 'lodash/isequal';

This works, too, but there are two minor drawbacks:

  • You have to install the whole lodash package (npm install --save lodash), not just the small separate lodash.isequal package; storage space is cheap and CPUs are fast, so you may not care about this
  • The resulting bundle when using tools like webpack will be slightly bigger; I found out that bundle sizes with a minimal code example of isEqual are on average 28% bigger (tried webpack 2 and webpack 3, with or without Babel, with or without Uglify)
Patrick Hund
  • 19,163
  • 11
  • 66
  • 95
  • Doesn't work for me for some reason, I am getting `_ is not defined` when using `_.isEquals` – cvdv Apr 18 '17 at 18:24
  • 10
    @cvDv, But it is not supposed to use like `_.isEqual`, you should use directly `isEqual` – Aren Hovsepyan Apr 18 '17 at 18:25
  • hmm im still get `isEqual` is undefined, I added `import isEqual from 'lodash.isequal'` to the top and below is just a `export const functionName` using isEquals – cvdv Apr 18 '17 at 18:35
  • 1
    Have you actually installed the module? npm i --save lodash.isequal – Patrick Hund Apr 18 '17 at 18:37
  • yeah looks like wasn't running watch with webpack so restarting it worked -_- ...thanks for the help – cvdv Apr 18 '17 at 18:40
  • I am trying to use differenceWith and import { differenceWith } from 'lodash.differenceWith'; does not work for me. Getting lodash_differenceWith_1.default is not a function – Evgeny Fedorenko Oct 27 '17 at 19:46
  • Think you actually need slash not period, ie `import isEqual from 'lodash/isequal'`. At least, that's what works for me on Win 10. – thund Nov 06 '17 at 01:12
  • No, it's a period. See documentation: https://www.npmjs.com/package/lodash.isequal – Patrick Hund Nov 06 '17 at 05:20
  • Ah. I'd just done `npm --save lodash` then `import whatever from 'lodash/whatever'`, which seemed to work (with smaller filesize) without my needing to explicitly run `npm --save lodash.whatever`. Is there any advantage to using your period method, since it seems to require running an extra `import` every time you want access to an additional function? – thund Nov 07 '17 at 19:02
  • Sorry - I meant running an extra `npm --save` for every additional function. – thund Nov 07 '17 at 19:12
  • `import template from 'lodash.template';` is not working and I am using Webpack and uglifyjs. `Uncaught ReferenceError: require is not defined` – tom10271 Jan 12 '18 at 03:20
  • 1
    @thund Since this answer gets a lot of up votes, I've taken the time to compare bundle sizes when using dot (as recommended by lodash docs) and slashes, see my edited answer – Patrick Hund Feb 15 '18 at 17:15
  • 2
    @PatrickHund: That's very interesting. I agree that the overhead of having the whole lodash on your development machine is pretty trivial, especially since it eliminates the need to run `npm --save lodash.whatever` for each function separately, but the larger bundle size could certainly make it worth using the period method. I'm surprised that there's a difference, so I'm glad you ran the numbers for us. – thund Feb 22 '18 at 20:51
  • @EvgenyFedorenko the correct way to import it is: `import differenceWith from 'lodash.differencewith'`. `lodash.differencewith` needs to be all in lowercase letters. – Lord Zed Feb 27 '18 at 12:01
  • 2
    what about typing for the individual installed functions? – Daniel Netzer Nov 08 '18 at 12:17
  • 1
    "28% bigger" of what? The isEqual function can't be more than 300 bytes. This seems like unnecessary hand optimization over the / version. – Michael Cole Mar 28 '19 at 17:10
  • 5
    It should be noted that using per method packages is no longer the recommended way and will be removed in lodash 5 - https://lodash.com/per-method-packages – D W Sep 06 '21 at 16:39
  • I have `lodash` pckg installed, and when I try to `import isEqual from "lodash/isEqual"; `my code deson't seem to be an issue, but I am to use the method `isEqual(arr1, arr2)` I get a type error `...is not a function`. Would someone know why? – m3.b Nov 15 '22 at 02:23
76

If you just want to include isEqual and not the rest of the lodash functions (useful for keeping your bundle size small), you can do this in ES6;

import isEqual from 'lodash/isEqual'

This is pretty much the same as what's described in the lodash README, except that there they use require() syntax.

var at = require('lodash/at');
Jo Sprague
  • 16,523
  • 10
  • 42
  • 62
  • This answer should work, but if you come across the error: `isEqual.isEqual is not a function` due to your ESM configuration, try using: `import * as isEqual from 'lodash/isEqual';` – timray Oct 23 '20 at 15:43
37

With webpack 4 and lodash-es 4.17.7 and higher, this code works.

import { isEqual } from 'lodash-es';

This is because webpack 4 supports sideEffects flag and lodash-es 4.17.7 and higher includes the flag (which is set to false).

Edit

As of version 1.9.0, Parcel also supports "sideEffects": false, threrefore import { isEqual } from 'lodash-es'; is also tree shakable with Parcel.

kimamula
  • 11,427
  • 8
  • 35
  • 29
9

Not related to webpack but I'll add it here as a lot of people are currently moving to typescript.

You can also import a single function from lodash using import isEqual from 'lodash/isEqual'; in typescript with the esModuleInterop flag in the compiler options (tsconfig.json)

example

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es5",
    "lib": ["es6", "dom"],
    "moduleResolution": "node",
    "esModuleInterop": true,
    ...
  }
}
Alex Beauchemin
  • 1,072
  • 1
  • 17
  • 24
8

I think it is worth noting lodash documentation on per method packages to answer this question at least as of June 2020:

Lodash methods are available in standalone per method packages like lodash.mapvalues, lodash.pickby, etc. These packages contain only the code the method depends on.

However, use of these packages is discouraged and they will be removed in v5.

Although they may seem more lightweight, they will usually increase the size of node_modules and webpack/rollup bundles in a project that transitively depends on multiple per method packages and/or the main lodash package. Whereas many methods in the main lodash package share code, the per method packages internally bundle copies of any code they depend on.

The docs actually recommend:

Don't worry—if you import or require methods directly, e.g. const throttle = require('lodash/throttle'), only the subset of lodash code your package uses will be bundled in projects that use your package.

Additionally this page has some pretty interesting research into different import options and resulting build sizes: https://www.blazemeter.com/blog/the-correct-way-to-import-lodash-libraries-a-benchmark

stelloprint
  • 303
  • 2
  • 9
3

Best way is with the slash:

import isEqual from 'lodash/isEqual'  //or equivalent

Maybe dotted per function packages were the right answer once, but their use is now discouraged and they will be removed.

Also, as stated by Lukas, it's better than import {isEqual} from 'lodash', as this will import all lib and then extract one function to the current scope.

Nick
  • 81
  • 6
2

Lodash lists a couple of options in their README:

  • babel-plugin-lodash

    • Install lodash and the babel plugin:
    $ npm i --save lodash
    $ npm i --save-dev babel-plugin-lodash @babel/cli @babel/preset-env
    
    • Add this to your .babelrc
    {
      "plugins": ["lodash"],
      "presets": [["@babel/env", { "targets": { "node": 6 } }]]
    }
    
    • Transforms this
    import _ from 'lodash'
    import { add } from 'lodash/fp'
    
    const addOne = add(1)
    _.map([1, 2, 3], addOne)
    

    Roughly to this:

    import _add from 'lodash/fp/add'
    import _map from 'lodash/map'
    
    const addOne = _add(1)
    _map([1, 2, 3], addOne)
    
  • lodash-webpack-plugin

    • Install lodash and webpack plugin:
    $ npm i --save lodash
    $ npm i --save-dev lodash-webpack-plugin babel-core babel-loader babel-plugin-lodash babel-preset-env webpack
    
    • Configure your 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-es using the lodash cli

    • $ lodash modularize exports=es -o ./
mlunoe
  • 4,422
  • 4
  • 32
  • 43
1

import { isEqual } from 'lodash-es'; is importing the entire library. I am using Rollup which should do tree shaking by default.

Whenever I've written my own modules, this named import syntax works and Rollup successfully tree shakes, so I'm a bit confused as to why it won't work with Lodash.

Ollie Williams
  • 1,996
  • 3
  • 25
  • 41
1

Most of the methods has their own packages. Install the relevant package/method:

npm i -S lodash.debounce
npm i -D @types/lodash.debounce

Then just import the method and use it

import debounce from 'lodash.debounce';

debounce(() => { ...

Also see: https://www.npmjs.com/package/lodash.debounce

Gil Epshtain
  • 8,670
  • 7
  • 63
  • 89
0

If you're using a REPL on the browser (chrome dev tools or Deno for example), and you really just need to quickly test something without using any IDE, babel or tool, you can import a single or more lodash functions from almost any website unless they're CORS restricted, in the following way:

(arr => Promise.all(arr.map(_ =>
  import ('https://cdn.skypack.dev/lodash.' + _))).then(_ => _[0].default(arr, _.map(d => d.default))))(
  ["zip", "unzip", "groupby", "mapvalues"])
  .then(_ => Object.fromEntries(_)).then(_ => {
  //you can use _ with zip, unzip, groupby, and mapvalues
  console.log(Object.keys(_))
})
Rainb
  • 1,965
  • 11
  • 32
-2

this actually worked for me

import { isEqual } from 'lodash';
vikiival
  • 363
  • 3
  • 7
  • 32
    You still get the full lodash library by using this syntax. OP wants to only get the isEqual funtion, reducing the size of his bundle. – Nyegaard Sep 29 '17 at 09:00
  • 2
    This will import all lib and *then* extract one function to the current scope. – Lukas Liesis Apr 28 '18 at 06:56