Killing Lodash: Inside You-Dont-Need-Lodash-Underscore

How a single JSON file and an ESLint plugin automated the transition from heavy utility libraries to native JavaScript.

6 min read • View on GitHub • More from you-dont-need

A bulky Swiss Army knife being disassembled by a single, precise scalpel, representing the replacement of heavy utility libraries with precise native JavaScript methods.
The transition from 'install everything' to 'native first' requires precise tooling.
Key Takeaways

The Dependency Zero Manifesto

In the mid-2010s, developers routinely imported 70KB of Lodash just to use three array methods. It was the era of 'install everything,' where convenience trumped bundle size. As JavaScript evolved, the ECMAScript standard began absorbing these utility functions directly into the language. You-Dont-Need-Lodash-Underscore emerged as the handbook for the vanilla JavaScript rebellion.

However, this project is not just a documentation repository. It is an active build-pipeline enforcer. By transforming a static list of native alternatives into an ESLint plugin, the maintainers automated the obsolescence of utility libraries. The tool actively scans codebases and flags unnecessary dependencies, allowing developers to shave massive weight off their bundles by trusting modern browser APIs.

I was shipping more Lodash than the framework running my entire app. ... Total lines added: 20 Bundle size saved: 72KB

Ignatius Sani, Senior Engineer & Founder @Lumina · I Replaced Lodash With 20 Lines of Vanilla JS

A Data-Driven Exterminator

The most surprising element of the repository is its architecture. Most ESLint plugins require developers to write complex Abstract Syntax Tree (AST) parsing logic for every single rule. You-Dont-Need-Lodash-Underscore sidesteps this entirely with meta-programming.

The 'brain' of the project is a single file: rules.json. This centralized database maps Lodash methods to their native alternatives. The core logic engine, all.js, iterates over this JSON file to dynamically generate AST detection logic on the fly. This data-driven approach solves the scaling problem of writing lint rules and makes open-source contributions frictionless.

"isNil": {
    "ruleName": "is-nil",
    "compatible": true,
    "alternative": "value === null || value === undefined"
}

The ESLint plugin generates rules dynamically from a central JSON database, abstracting away complex AST parsing.

Navigating the Null-Safety Trap

Vanilla JavaScript historically lacked the graceful failure of methods like _.get(). A direct 1:1 refactor from Lodash to native JavaScript often introduces the risk of a TypeError: cannot read property exception if a value evaluates to null or undefined.

A close-up of a sturdy stone bridge with a single missing keystone block, with a small warning flag planted right before the gap. This illustrates the danger of refactoring without null-checking.
Refactoring without null-checking introduces structural vulnerabilities.

The project manages this risk using a clever compatible boolean flag in its JSON schema. If a native alternative risks throwing an exception on null values, the plugin smart-downgrades the linting notification from an Error to a Warning. This demonstrates a sophisticated understanding of safe versus unsafe refactoring boundaries.

// Lodash (Safe)
const value = _.get(obj, 'a.b.c');

// Native Pre-ES2020 (Unsafe)
const value = obj && obj.a && obj.a.b && obj.a.b.c;

// Native ES2020+ (Safe Optional Chaining)
const value = obj?.a?.b?.c;

When You Actually Still Need Lodash

Despite the rise of native JavaScript, utility libraries are not entirely obsolete. The decision to remove Lodash depends heavily on the specific needs of the codebase. Native methods are ideal for standard array manipulation and optional chaining, but strict functional programming or deep cloning complex legacy objects may still warrant dedicated tools.

LibraryPrimary Use CaseNull SafetyBundle Impact
Native JSStandard array/object manipulationRequires optional chainingZero
LodashDeep cloning, deep merging, legacy supportExcellent (graceful failure)Heavy (requires tree-shaking)
RamdaStrict functional programmingManaged via functional compositionModerate