My mistake importing lodash correctly

My mistake importing lodash correctly

Posted 2023-10-15

What is lodash?

"A modern JavaScript utility library delivering modularity, performance & extras."

✅ copied
import _ from 'lodash' _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor) // => [1.1, 2.3] _.groupBy([6.1, 4.2, 6.3], Math.floor); // => { '4': [4.2], '6': [6.1, 6.3] } _.groupBy(['one', 'two', 'three'], 'length'); // => { '3': ['one', 'two'], '5': ['three'] }

What is Vite?

  • Frontend build tool that is extremely quick to build your applications.

  • I'd recommend everyone using it if they get a chance.

  • Vite has built in tree shaking. But there are some cases where it doesn't work well. Lodash is one.

  • Spoiler: the 'issue' I'm raising is fixed by reading lodash's documentation better.

What is tree shaking?

  • A bundler technique to remove unused/dead code, leading to a smaller JS bundle size.

How I've been using lodash in frontend applications

import { isNil } from 'lodash' console.log(isNil(someValue))

And I assumed from lodash, only isNil would be in my JS that I serve to clients

Smallest lodash function to run this test with:

Very small function, to check if a value is undefined or null

function isNil(value) { return value == null; }

Impact of importing incorrectly (with vite)

All sizes are from running yarn build and looking at the built JS filesize on disk.

  • New Vite app - 143.41 kB
  • import _ from 'lodash' (and using _.isNil()) - 216 kB ❌
  • import * as _ from 'lodash' (and using _.isNil()) - 216 kB ❌
  • import {isNil} from 'lodash' - 216 kB ❌
  • import isNil from 'lodash/isNil' - 143.48 kB ✅
  • import {isNil} from 'lodash-es' - 143.45 kB ✅

Results in NextJS

Similar test, showing the bundle size changes.

NextJS handles lodash imports better.

  • New NextJS app (not using lodash) - 87.7 kB
  • import _ from 'lodash' (and using _.isNil()) - 114 kB ❌
  • import * as _ from 'lodash'- 114 kB ❌
  • import {isNil} from 'lodash' - 87.8 kB ✅
  • import isNil from 'lodash/isNil' - 87.8 kB ✅
  • import {isNil} from 'lodash-es' - 87.8 kB ✅

Vite's tree shaking works well normally

This isn't to knock Vite or lodash.

Here is an example where it works well.

✅ copied
export const smallFn = () => 'x' export const largeFn = () => { const data =[ 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // ... around 4000 more lines ].join() }

import {smallFn} from './fns'          ✅ 143 kB

import {largeFn} from './fns' ❌ 406 kB

This isn't a new issue

Lodash have this documented well on their website. And they offer solutions.

import isNil from 'lodash/isNil' // or import { isNil } from 'lodash-es'

You can also use tools like babel-plugin-lodash to automatically apply these.

In summary

If using lodash on frontend applications, double check your imports and bundle size.

Switch to the ESM lodash version at lodash-es

Or use the import isNil from 'lodash/isNil' style

Recommend adding eslint-plugin-lodash import rules to enforce it in your app


Subscribe to my
Full Stack Typescript Developer

If you enjoyed my content and want more Full Stack Typescript content, then enter your email below.

I send a few links every couple of weeks, that I personally found useful from around the web.

Focusing on Build-tools, Typescript, NextJS, and also
engineering soft skills posts.

Welcome to my site and blog - Code Driven Development.

This is where I dive topics relating to modern software engineering - with a focus on Typescript, React, web accessibility and Agile practices

I pick topics that I think are interesting, that I think others might find interesting, or write up guides that I wish I had read before learning a topic.