Vanilla JS Still Wins the Complexity Budget
Modern browsers closed the old gaps. Frameworks still cost real money in size, churn, and cognitive load.
Frontend teams still reach for a framework on almost every greenfield UI. That reflex is understandable. For years the platform was inconsistent and the language was thin, so libraries papered over real holes. The holes are mostly gone. What remains is a habit that quietly spends a complexity budget most products never earn back.
The case for vanilla JavaScript is not anti-framework purism. It is a cost argument. Plain JavaScript (no React, Vue, Angular, jQuery, or other external layer) gives direct access to the language and browser APIs. You trade some boilerplate for smaller payloads, fewer upgrade landmines, and the ability to debug without peeling three abstraction layers. For a large class of work that trade is rational.
The platform caught up
"Vanilla" simply means pure JavaScript: the language and native browser surface, unaltered by libraries or frameworks. The term itself started as a joke. In 2012 Eric Wastl published a tongue-in-cheek site marketing Vanilla JS as a framework that shipped at 0 bytes uncompressed (25 bytes gzipped). The gag stuck because it was true. A surprising amount of imported code was already available in the browser if you were willing to use it.
That observation is stronger today. Modern browsers are far more standards-compliant than they were in the jQuery era. You can select and mutate the DOM with querySelector and friends, issue network requests with fetch, compose modules natively, use classes and promises, and lean on the rest of the post-ES6 surface without polyfill theater for most targets. The old justification for a framework ("I need consistent APIs across browsers") has largely evaporated for mainstream work.
Frameworks still abstract hard problems well. They also insert their own hard problems: build pipelines, version migrations, dependency graphs, and mental models that only exist inside that ecosystem. When something breaks, the path from symptom to root cause runs through framework internals. Developers who never learned the platform hit a wall there. Developers who did can keep shipping.
What you actually pay for
Complexity has a bill. Frameworks buy development velocity, reusable component patterns, and a shared vocabulary that helps distributed teams collaborate. Those are real wins on large product surfaces with many concurrent feature owners.
They also buy:
- Larger client payloads and longer parse/compile time
- Dependency and supply-chain surface you must monitor
- Upgrade and deprecation work on a schedule you do not control
- Abstraction that hides performance and correctness bugs until they are expensive
- Hiring and onboarding lock-in to one component model
Vanilla work has the opposite profile. You write more of the glue yourself (form handling, small state machines, routing if you need it). File size stays small because there is no framework runtime. Behavior is inspectable with ordinary browser tools. You can scale the architecture progressively instead of importing an SPA stack on day one of a marketing site.
The disadvantages are honest. Large applications without structure become hard to maintain. Common tasks take more lines. There is no blessed component lifecycle or state library handed to you. That is the point of a complexity budget: you spend the structure only when the product's interaction model or team size demands it, not by default.
When vanilla is the right default
Use plain JavaScript first when:
- The project is small or medium and the interaction model is modest (forms, progressive enhancement, light dashboards, content sites with islands of interactivity).
- Performance or payload size is a hard constraint (low-end devices, emerging markets, strict Core Web Vitals targets).
- You need full control over browser-specific behavior without fighting a framework's rendering model.
- The team is learning the platform or needs to stay fluent enough to debug any stack later.
Reach for a framework when the product is a large, long-lived client application with complex shared state, many concurrent contributors, and a design system that benefits from a single component contract. Collaboration and practice effects are genuine advantages of popular frameworks. Pretending otherwise is ideology, not engineering.
The middle ground is underused. Native ES modules, modern CSS, and Web Components cover a surprising amount of encapsulation without a full framework. You can ship a multi-page app with progressive enhancement, add a few custom elements for the interactive bits, and keep the dependency list near zero. That is still "vanilla" in spirit and far cheaper than a full SPA for many internal tools and marketing surfaces.
How working developers should actually decide
Start the next project with an explicit question: what interaction complexity forces a framework on day one? If the answer is "none yet," open with plain JS and a thin build step (or none). Keep the door open to extract components later.
Concrete habits that pay off:
- Prefer platform APIs before packages.
fetch,URLSearchParams,AbortController,IntersectionObserver, and the DOM are enough for most CRUD and progressive UIs. - Use ES modules and keep state local until sharing it across distant views becomes painful. Lift state only when you feel the pain, not because a tutorial did.
- Measure payload and runtime on a mid-tier phone, not only on a developer laptop. Framework "overhead" is abstract until you watch main-thread time.
- Treat frameworks as optional accelerators, not the definition of frontend work. When the chosen framework misbehaves, the people who know the language underneath fix it; everyone else files issues and waits.
None of this requires rejecting React or Vue for products that truly need them. It requires stopping the automatic import of their entire model for pages that do not.
The industry spent a decade treating frameworks as the default unit of frontend work. The platform improved. Team and product sizes did not all grow with it. For a lot of shipping software, vanilla JavaScript is not a step backward. It is the lower-cost way to stay in control of complexity you will eventually own either way.
Sources & further reading
- Why Vanilla JavaScript — guseyn.com
- What is Vanilla JavaScript? - GeeksforGeeks — geeksforgeeks.org
- javascript - What is VanillaJS? - Stack Overflow — stackoverflow.com
- Learn Vanilla JavaScript Before Fancy Frameworks - Snipcart — snipcart.com
- Vanilla JavaScript - What is it? - Ubiqum — ubiqum.com
Lenn writes about cloud platforms, Kubernetes internals, and the infrastructure decisions that quietly make or break engineering organizations. Based in Berlin's vibrant tech scene, they have a talent for turning dense platform-engineering topics into prose that people actually finish reading.
Discussion 0
No comments yet
Be the first to weigh in.