DEV Community

Cover image for A Single Regex Got Its Own npm Package. It Gets 70 Million Downloads a Week.
Aditya Agarwal
Aditya Agarwal

Posted on • Edited on

A Single Regex Got Its Own npm Package. It Gets 70 Million Downloads a Week.

A regular expression was popular enough to warrant its own npm package. It's downloaded 70 million times a week.

The package is shebang-regex. Here's the entire source code:

const shebangRegex = /^#!(.*)/;
export default shebangRegex;
Enter fullscreen mode Exit fullscreen mode

Seriously, there's one line of actual code there. One line wrapped in a package, published to npm, and unwittingly linked into millions of projects by way of their dependency trees.

In a blog post that hit 379 points on Hacker News this week, James Garbutt lays out what he refers to as the three pillars of JavaScript bloat. And honestly, it puts words to something every JS dev has known in their gut for years but never quite been able to articulate.


Pillar One: Old Runtime Support 🦕

The likes of is-string still exist because somewhere, someone needs to cover ES3. Think IE6. Think early Node before they shimmed Array.forEach.

For that person, this makes sense. For the rest of us in evergreen land, downloading dead-weight we never actually wanted.


Pillar Two: Atomic Architecture 🧱

That's the thinking behind the idea that every function should be its own package. arrify turns a value into an array. slash replaces backslashes. is-windows checks if process.platform is win32.

The promise is reusable lego bricks. The reality is one-consuming packages — written by the same person, for the same package.

Nuxt's dependency tree has two versions of is-docker, two versions of is-stream, and two versions of is-wsl. Each and every one of those could have been a three-liner.


Pillar Three: Ponyfills That Won't Leave 👋

The globalthis ponyfill is still being downloaded millions of times a week. Browsers have natively supported this for 7 years, since 2019.

These aren't exceptions. This is the rule.


The Numbers 📊

→ The average node_modules folder for a modern framework project sits between 400 and 700 MB
→ The average JS project has 42 direct dependencies and 683 transitive ones (Sonatype)
→ That means for every package you actually chose, you got 16 you didn't


The Cleanup Has Started 🧹

But it's not all bad news.

The e18e community, who's been quietly waging a cleanup initiative, has started solving the problem seriously. They're writing tools that will scan your dependency tree, flag known bloated packages, and suggest modern replacements, with their module-replacements tracking the worst offenders already.

pnpm's content-addressable store can cut node_modules size by up to 89% by deduplicating across projects. Package managers now offer features like minimumReleaseAge to slow down supply chain attacks.

Perhaps the most promising development has been the most intangible. It's philosophical.

The next time you reach for npm install, open up the source and read the package. If the entire thing fits inside a tweet, perhaps just write the damn thing yourself.

Your node_modules will thank you.

What's the most ridiculous single-responsibility package in your dependency tree? 👇

Top comments (7)

Collapse
 
pengeszikra profile image
Peter Vivo

Use any dependence just a good reason. For example my rustroke first prompt is not using any non standard rush dependency, because dependency even a rust dependency will increase a compiler time. No dependency means 2sec rust compiler time. JS part also don't have dependency just use JSdoc but that just help for AI so do not need to config it, or add devdependency.

Collapse
 
adioof profile image
Aditya Agarwal

well said!

Collapse
 
annavi11arrea1 profile image
Anna Villarreal

Ooooh! This is entertaining! 😂🦚 I appreciate you pointing this out. Ill definitely investigate this a bit at some point. I have been curious about node modules. This is a good excuse as any to do some poking.

Collapse
 
adioof profile image
Aditya Agarwal

haha glad to hear!

Collapse
 
francistrdev profile image
FrancisTRᴅᴇᴠ (っ◔◡◔)っ

The next time you reach for npm install, open up the source and read the package. If the entire thing fits inside a tweet, perhaps just write the damn thing yourself.

Noted lol. It's also good to note that if it is in one file, you could also do a CDN or download a single file just to run it locally. A good example is p5.js and ml5.js since it offers the user to download a min.js file.

Great post!

Collapse
 
trinhcuong-ast profile image
Kai Alder

Ran npx depcheck on a side project last month and found 12 packages I wasn't even using anymore. But the transitive dependency rabbit hole is what really gets you — I traced one of my deps and it pulled in is-number, which is literally return typeof value === 'number'.

The e18e initiative is great but I think the real fix needs to come from package managers themselves. Like, what if npm/pnpm had a built-in "inline threshold" — if a package is under X lines of actual code, just inline it during install instead of creating another folder in node_modules?

Also worth mentioning: Bun's approach of bundling common polyfills into the runtime itself helps a ton. Moved a project from Node to Bun and shaved off like 40% of my dependencies just because Bun natively handles stuff that Node still needs packages for.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.