A Developer's Journey Home
I still remember the first time I right-clicked on a webpage and selected "View Source." I was a teenager, the web was young, and that single action felt like being handed the keys to a secret world. There it was—the actual code that made the page work. HTML tags I could read. JavaScript I could copy, tweak, and learn from. No build step, no compilation, no node_modules folder. Just text files that browsers understood.
That simplicity wasn't a limitation—it was the magic. You could learn by reading. You could experiment by copying. The barrier between "user" and "developer" was just a View Source click away.
Somewhere along the way, we lost that. The web became professionalised, industrialised. Frameworks emerged to solve real problems, but they also erected walls. Try right-clicking on a modern React application and viewing source. You'll find minified JavaScript bundles, webpack artifacts, and precisely nothing that teaches you how the page actually works.
At uRadical, we've spent the last year migrating away from JavaScript frameworks—React, Svelte, Vue—back to vanilla JavaScript and Web Components. Our most recent migration, from Svelte to vanilla JS, crystallised everything we'd been feeling. And the results surprised even us:
99.7% reduction in node_modules size (from 119MB to 412KB)
94% fewer npm dependencies (from 18 packages to just 1)
83% less source code (from 4,695 lines to 812)
Zero build step — ES modules load directly in the browser
But here's the thing: this isn't about nostalgia. It's about recognising that the browser has finally caught up with our ambitions. The platform that needed jQuery to smooth over inconsistencies and React to manage complexity has matured into something genuinely capable. We're not going backwards—we're arriving at where the web was always meant to be.
The Browser Finally Grew Up
When I started building for the web, JavaScript was a toy language for form validation and rollover images. The idea that you'd build an entire application in JavaScript would have seemed absurd. We needed the server to do the real work.
Then came the AJAX revolution, and suddenly JavaScript was everywhere. But browsers were inconsistent, APIs were limited, and we genuinely needed abstraction layers. jQuery papered over browser differences. Backbone gave us structure. React solved the state management nightmare that came with complex single-page applications. These tools existed because the platform couldn't do the job alone.
That's no longer true. As of 2025, every major browser—Chrome, Firefox, Safari, Edge—fully supports Web Components without polyfills. Custom Elements let you define your own HTML tags. Shadow DOM provides encapsulation. ES Modules eliminate the need for bundlers. CSS has variables, nesting, container queries, and :has() selectors. The Fetch API replaced XMLHttpRequest. async/await made asynchronous code readable.
The browser isn't the problem anymore. It hasn't been for years. We just kept reaching for frameworks out of habit.
Web Components: The Standard That Took Its Time
I remember the early Web Components specs—the promise was tantalising but the reality was rough. Browser support was patchy. The APIs felt awkward. The Shadow DOM created as many problems as it solved. For years, "wait for Web Components" was a punchline.
That wait is over. The technology has matured quietly while everyone was arguing about React versus Vue. Industry observers noted that 2025 marked the year of Web Components' resurgence—not because of hype, but because the fundamentals finally work.
The enterprise world figured this out early. Salesforce rebuilt their entire platform on Lightning Web Components. SAP created UI5 Web Components for their modern interfaces. Google's Lit library provides a minimal layer over native APIs for teams wanting slight ergonomic improvements. When companies managing billions in enterprise software commit to a technology, it's not experimentation—it's strategy.
What I find most compelling is the philosophy behind Web Components: build once, use anywhere. A Web Component works in a React app, a Vue app, a vanilla HTML page, or a WordPress site. It doesn't care about your framework choices. It just works, because it's built on the platform itself. That's the kind of interoperability the early web had by default—and that frameworks took away.
The Exhaustion Is Real
I've been building for the web for over three decades now. I've lived through the jQuery era, the Backbone era, the Angular 1 to Angular 2 schism, the rise of React, the emergence of Vue, the Svelte enthusiasm. Each transition demanded relearning. Each framework promised this time would be different.
The 2024 State of Frontend survey captured what many of us have been feeling: excessive complexity, poor performance, choice overload, breaking changes. Developers are tired. The cognitive overhead of staying "current" has become unsustainable.
The New Stack recently observed that frontend developers are returning to vanilla JavaScript as a response to collective burnout. "Framework fatigue isn't just a meme anymore," they wrote. "It's a collective burnout." The web's pendulum is swinging back toward minimalism—toward code you can actually read and understand without consulting documentation for a specific framework version.
This resonates with something I felt as a teenager but couldn't articulate: the joy of understanding what you're building. Our Svelte codebase worked fine, but every change meant navigating a 170-line Rollup configuration, TypeScript compilation quirks, and 138 packages in node_modules. The friction was constant. The abstraction layers had become the complexity they were meant to hide.
The npm Supply Chain Has Become a Liability
If fatigue were the only issue, we might tolerate it. But 2025 made the security case impossible to ignore.
In September, attackers compromised maintainer accounts through phishing and injected malicious code into 18 widely-used npm packages—including foundational libraries like chalk and debug. These packages see over 2.6 billion downloads per week. The malicious code targeted cryptocurrency transactions, redirecting funds to attacker wallets. The community responded within hours, but the window was enough.
Then came the Shai-Hulud worm—a self-replicating npm attack that spread through developer credentials, compromising over 500 packages. The second wave was worse: it triggered during pre-install and, if it couldn't steal credentials, would attempt to destroy the victim's entire home directory.
Red Hat issued advisories. Palo Alto Networks published breakdowns. GitLab discovered it spreading through their monitoring systems. npm revoked all classic tokens and mandated shorter expiration periods.
Every dependency is a trust relationship with a maintainer you've never met, secured by credentials that might already be compromised. Our Svelte project had 138 packages in node_modules—138 potential attack vectors. Our vanilla JS replacement has 13. That's not just a number; it's a dramatically reduced attack surface.
In the early web, there was no supply chain to attack. Your code was your code. That simplicity had security benefits we didn't appreciate until we lost them.
The Return to the Server (Where We Started)
Here's an irony: after a decade of pushing everything to the client, the industry is rediscovering that server-side rendering is actually… good. Faster for users. Better for SEO. More accessible. The approaches have evolved—edge computing, streaming SSR, partial hydration—but the principle is the same one we started with: send HTML from the server.
Web Components fit naturally here. Unlike framework components that often require JavaScript to render anything at all, Web Components with light DOM content can be streamed and displayed immediately. JavaScript enhances what's already there rather than creating it from nothing. This is progressive enhancement—a concept as old as the web itself—finally implemented properly.
When I built my first websites, they were server-rendered by default because there was no other option. We're coming full circle, but with better tools and a deeper understanding of why it matters.
Being Honest About the Tradeoffs
I'm not pretending Web Components are perfect. The Shadow DOM, while powerful for encapsulation, creates real friction. Global styles don't cascade into shadow roots by default. Form elements inside Shadow DOM don't automatically participate in parent forms. Debugging can be trickier.
The workarounds exist: CSS custom properties pierce the shadow boundary; the ElementInternals interface connects custom elements to forms; you can use light DOM for content needing global styles while reserving Shadow DOM for truly encapsulated widgets. Or skip Shadow DOM entirely—Web Components don't require it.
I'm also not arguing that frameworks have no place. Complex applications with intricate state management, large teams needing standardised patterns, projects where the build step provides genuine value—these are valid reasons to reach for React or Vue or Svelte. The point isn't that frameworks are bad. It's that they're not always necessary, and the costs—dependency weight, security surface, cognitive load, the loss of simplicity—should be weighed honestly.
What Our Migration Actually Delivered
Here's the full picture of our Svelte-to-vanilla-JS migration:
| Metric | Before (Svelte) | After (Web Components) | Change |
|---|---|---|---|
| npm dependencies | 18 packages | 1 package | -94% |
| node_modules size | 119 MB | 412 KB | -99.7% |
| node_modules packages | 138 packages | 13 packages (dev only) | -91% |
| Source files | 29 files (.svelte, .ts) | 12 files (.js) | -59% |
| Lines of code | 4,695 lines | 812 lines | -83% |
| Build config files | 3 (Rollup, tsconfig, preprocessor) | 0 | -100% |
| Build step required | Yes | No | Eliminated |
We preserved everything that matters: carousel, hamburger menu, contact form, responsive design, scoped styles. Users notice nothing different except faster load times. But here's what I notice: I can View Source again. Someone curious about how our site works can right-click and actually learn something. That feels like returning to the web I fell in love with.
Where This All Leads
The trends we've followed are now hitting the mainstream. Publications document the shift back to vanilla JavaScript. Surveys show developers questioning framework necessity. Security incidents force teams to audit dependency trees.
We're not claiming to be prophets. The signals were there: browser APIs maturing, supply chain attacks escalating, developer burnout intensifying. What we did was act on those signals.
For teams considering a similar path: start with new projects. Evaluate honestly whether your application's complexity justifies framework overhead. Audit your dependency tree—not just for vulnerabilities, but for necessity. Consider what happens when a core dependency gets compromised.
The web platform is mature enough to handle modern application development without heavy abstractions. Web Components provide reusability without lock-in. ES modules eliminate the build step. The browser is capable in ways it never was when I first hit View Source as a teenager.
At uRadical, we'll continue building with vanilla JavaScript and Web Components. Not out of nostalgia, but because the numbers support it and the philosophy aligns with what made the web special in the first place: openness, simplicity, the ability to learn by looking.
The frameworks will keep evolving. New ones will emerge. But the platform moves forward too, and increasingly, its native capabilities are enough. Sometimes the best way forward is to return to what worked—with the wisdom to know why it worked in the first place.
uRadical provides hosting and development services with a focus on simplicity, security, and long-term maintainability. Learn more at uRadical.io