Stop Installing Packages for Things JavaScript Already Does
Every npm install adds supply chain risk, bundle size, and complexity. Here are 7 cases where a single line of native JavaScript replaces a popular package.
1. UUID Generation (replaces uuid)
const id = crypto.randomUUID();
// "3b241101-e2bb-4d7a-8702-9e3c8a4f5b6a"
Package: uuid — 30M+ weekly downloads, 7KB
Native since: Node 19+, all modern browsers
2. Deep Clone (replaces lodash.cloneDeep)
const clone = structuredClone(original);
Package: lodash.cloneDeep — 10M+ weekly downloads
Native since: Node 17+, all modern browsers
Bonus: Handles circular references, Maps, Sets, Dates, RegExp
3. Array Grouping (replaces lodash.groupBy)
const grouped = Object.groupBy(users, user => user.role);
// { admin: [...], user: [...], moderator: [...] }
Package: lodash.groupBy — 8M+ weekly downloads
Native since: Node 21+, Chrome 117+, Firefox 119+
4. Query String Parsing (replaces qs)
const params = Object.fromEntries(new URLSearchParams("name=john&age=30"));
// { name: "john", age: "30" }
Package: qs — 65M+ weekly downloads, 30KB
Native since: forever (URLSearchParams is old)
5. Debounce (replaces lodash.debounce)
const debounce = (fn, ms) => { let t; return (...a) => { clearTimeout(t); t = setTimeout(() => fn(...a), ms); }; };
Ok, it's a two-liner. But it's 1 line if you minify it, and it's 100 bytes vs 7KB for lodash.debounce.
6. Flatten Arrays (replaces array-flatten)
const flat = nested.flat(Infinity);
// [1, [2, [3, [4]]]] → [1, 2, 3, 4]
Package: array-flatten — 25M+ weekly downloads
Native since: ES2019, Node 11+
7. Number Formatting (replaces numeral)
const formatted = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(1234567.89);
// "$1,234,567.89"
Package: numeral — 3M+ weekly downloads, 60KB, unmaintained since 2017
Native since: forever. Intl handles currencies, percentages, compact notation, units.
The Real Cost of NPM Packages
1 unnecessary package =
+ 1 supply chain attack vector
+ 1 thing that can break on next Node version
+ 1 thing that needs security updates
+ X KB added to your bundle
+ Y seconds added to npm install
After the event-stream incident, the ua-parser-js hack, and the colors.js sabotage — minimizing dependencies isn't paranoia, it's engineering.
When to Still Use the Package
-
uuid: If you need v1/v3/v5 UUIDs (not just v4) -
qs: If you need nested object serialization -
lodash: If you need 5+ utilities from it (import specific functions)
For everything else — check MDN first, npm second.
What packages have you replaced with native APIs? Would love to hear your list.
More from me: 10 Dev Tools I Use Daily | 77 Scrapers on a Schedule | 150+ Free APIs
Top comments (0)