Stop Waiting for Frameworks to Save You: Why I'm Building Smaller Again
Admin User
Author
I spent two hours last week debugging why a fresh Next.js project was pulling in 847KB of JavaScript just to display a contact form. The form itself? Plain HTML with basic validation. The irony hit me hard: I'd reached for a tool designed to solve a problem I didn't have, and now I'm paying the performance tax forever.
This isn't a new realization. But reading through the history of how we got here—from table layouts to CSS standards to the current framework explosion—I realized something uncomfortable: we're repeating patterns we already learned to break.
The web keeps oscillating between extremes, and right now, I think we're due for a correction.
The Pendulum Never Stops
The original article traces a fascinating arc: from the chaotic '90s (tables, spacer GIFs, Courier New), through the standards movement that actually worked, into the AJAX era that made things interactive, and finally into the modern framework age where we treat JavaScript as a requirement rather than an enhancement.
Each shift made sense at the time. Table layouts were genuinely the only way to build complex grids. CSS was limited. JavaScript libraries solved real browser compatibility problems. React fundamentally changed how we think about state management on the client.
But here's what bothers me: we're now treating the solutions to yesterday's problems as permanent architecture. I see developers reaching for React to build static documentation sites. I see Next.js projects that are really just blogs. I see Vue used for simple interactive components when vanilla JavaScript would suffice.
We've mistaken "powerful enough to build anything" with "necessary for everything."
The Real Cost of Convenience
Those frameworks absolutely make development easier—I'm not arguing they don't. The developer experience is genuinely better. Hot module reloading, TypeScript support out of the box, the ecosystem... it's all legitimately nice.
But that convenience has a hidden invoice attached. Users wait longer for pages to render. SEO becomes a puzzle to solve instead of a feature you get for free. Performance optimization becomes something you have to actively fight for rather than getting as default behavior.
More insidious: we've created a dependency chain where we can't adopt new web standards until the framework does. CSS Grid, Flexbox, @supports queries—I've waited months for framework upgrade cycles to recommend these to teams, even though browsers had perfect support.
Standards Have Won (Even If We Don't Believe It)
This is the part that actually excites me. Browser support for modern CSS and JavaScript is absurdly good now. I can use grid, CSS custom properties, fetch, async/await—all with 90%+ browser coverage—without needing a single dependency.
When I check CanIUse, the common response is "it's already supported." The barrier isn't browser compatibility anymore. It's that we've stopped learning what the platform itself offers.
I built a multi-column, responsive layout last month with nothing but CSS Grid and vanilla JavaScript. Total bundle size: 2KB. It would have been harder five years ago. Today, it was straightforward.
What I'm Actually Doing Differently
I'm not swearing off frameworks entirely—that's not pragmatic or fair to the problems they solve. But here's my personal rule now: I ask first.
Before reaching for Next.js, I ask: Does this need server-side rendering? Do I need that framework's specific patterns? Or could I ship this faster, smaller, and more sustainably with plain HTML, CSS, and JavaScript?
Before adding a state management library: Am I solving a real problem or just automating complexity I could avoid entirely?
Before integrating a third-party package: Could I write this in 50 lines of code instead of adding another dependency?
The answer is often "no, this framework is the right call." But increasingly, it's been "actually, let's keep this simple."
// Instead of reaching for a framework for this
// Just use the platform directly
document.querySelectorAll('[data-toggle]').forEach(button => {
button.addEventListener('click', (e) => {
const target = document.querySelector(button.dataset.toggle);
target.classList.toggle('hidden');
});
});
Dead simple. No build step. No framework update anxiety in two years.
The Discomfort I Can't Shake
Here's what keeps me up at night: I might be wrong about this. Maybe I'm just rediscovering the limitations of vanilla JavaScript that React solved a decade ago. Maybe I'll build something that grows into complexity I can't manage.
But I think that discomfort is healthy. We need more developers willing to question whether we've cargo-culted framework adoption as a default rather than a deliberate choice.
The web's superpower is that it works across everything, degrades gracefully, and has remarkable backwards compatibility. We should design around those strengths instead of fighting them.
What are you building this week? Are you using the smallest tool for the job, or the most powerful one you know?
Source: This post was inspired by "The Wax and the Wane of the Web" by A List Apart. Read the original article