DEV Community

Cover image for The Hidden Cost of 'Just Install This Library'
Kudzai Murimi
Kudzai Murimi Subscriber

Posted on

The Hidden Cost of 'Just Install This Library'

The Button That Taught Me a Lesson

Last week, I needed a button. Just a simple button with rounded corners and a loading state.

Old me would have written some HTML and CSS. Done in 15 minutes.

New me, swimming in the modern ecosystem, did this:

npm install @radix-ui/react-button
npm install class-variance-authority
npm install clsx
Enter fullscreen mode Exit fullscreen mode

Two hours later, the button worked beautifully. Then I tried to add a custom style and... nothing. The styles just wouldn't apply. Turns out, the component library uses Shadow DOM, and now I'm reading documentation about CSS encapsulation at midnight.

I saved myself from writing a button. I created a debugging adventure.

The Abstraction Trade-Off

Here's the thing: modern libraries solve real problems! They give us:

  • Accessibility out of the box
  • Cross-browser compatibility
  • Battle-tested patterns
  • Beautiful defaults

But they also come with a cost that's easy to miss: complexity debt.

Every layer you add is another thing to understand when debugging. Your "simple" stack might look like this:

<Button variant="primary">Submit</Button>
Enter fullscreen mode Exit fullscreen mode

But under the hood, you've got:

  • Your component library
  • The primitive component it wraps
  • The styling system
  • The CSS framework
  • The build tool processing everything

When something breaks, you need to debug through all of them.

How Abstractions Stack Up

I think about this as layers of trade-offs:

Plain HTML/CSS/JS: Total control, more code to write
Utility libraries (like lodash): One dependency, solves one problem
Frameworks (React, Vue): Learning curve, but gives you reactivity
Component libraries: Accessibility + UX, but harder to customize
Full solutions (Next.js, etc.): Everything integrated, lots of moving parts

Each level up gives you more out of the box, but takes more effort to customize or debug.

My Simple Rules

After getting burned a few times, here's what I ask before installing anything:

1. Do I understand the problem this solves?

If I can't explain why I need it, I probably don't need it yet.

2. Can I explain how it works in two sentences?

If not, I'm adding complexity I can't debug.

3. What's my escape hatch?

If this library gets abandoned or doesn't work, can I replace it without rewriting everything?

4. Am I choosing this because it's popular or because it fits?

Twitter hype is not a good reason to add a dependency.

Start Simple, Add Complexity When You Feel the Pain

My favorite strategy now: start boring.

// Start here
<button className="btn" onClick={handleClick}>
  Submit
</button>

// Only upgrade when you actually need:
// - Complex keyboard navigation
// - Advanced accessibility
// - Loading states
// - Multiple variants
Enter fullscreen mode Exit fullscreen mode

Let the pain guide you. If you find yourself writing the same button code 10 times, then reach for a library.

When Abstractions Are Worth It

Don't get me wrong, I still use libraries! But now I'm more intentional:

Use them for:

  • Accessibility (screen readers, keyboard nav)
  • Complex UI patterns (date pickers, modals)
  • Things I'd likely get wrong (form validation, security)

Skip them for:

  • Styling simple components
  • One-off features
  • Things I understand well

The Real Lesson

Every abstraction is a trade-off. You're borrowing time today and potentially paying debugging time later.

That's not bad! Sometimes it's absolutely worth it. But we should make that choice consciously, not automatically reach for the shiniest tool.

The best developers I know aren't the ones using the most libraries. They're the ones who can explain why they chose each one.

Your Turn

Before your next npm install, pause and ask:

  • What problem am I solving?
  • Can I start simpler?
  • Do I understand how this works?

You might still install the library. But you'll do it with your eyes open.

What's your take? Do you prefer starting simple or using battle-tested libraries from the start? Let me know in the comments!

Top comments (0)