Skip to content
Whyire
← Back to Engineering Journal
10 MIN / BEST PRACTICES / AUGUST 14, 2026 — BY TADIWA GWENA

The Weight of What You Did Not Write: A Zero-Dependency Philosophy for Web Performance

The Weight of What You Did Not Write: A Zero-Dependency Philosophy for Web Performance

An investigation into what the browser can now do on its own, what it still cannot, and why every line of code you did not ship is a line no one has to pay for.

I. The Phone That Waits

Picture a phone that is not new. Its screen is a little scratched, its battery holds perhaps two-thirds of what it once did, and somewhere in its modest allotment of memory, a browser tab is trying to render a website. The website was built by people who have never held this particular phone, tested on networks faster than the one it is currently gasping through, on machines with more memory than this device will ever have. The page requests a framework runtime, a component library, an animation library, a date-formatting library, an icon library, a state-management library, and, buried three dependencies deep in a lockfile nobody has opened in a year, a scattering of small utilities nobody remembers choosing. Each of these was a reasonable decision on its own, made by a reasonable developer, on a reasonable day. Together, they are a tax — paid not by the person who wrote the code, but by the person holding the phone, in seconds of their life and megabytes of their data plan, waiting for a button to become clickable.

This is the quiet cruelty of modern web development: the cost of convenience is almost always deferred, and almost always deferred onto someone else's device.

The proposition of this piece is not that JavaScript is bad, or that libraries are sin. It is narrower and more useful than that: a great deal of what the modern web ships as a dependency — a downloaded, parsed, executed piece of someone else's code — is now available as a platform capability, built into the browser itself, requiring no download at all. Knowing the difference, and having the discipline to prefer the platform when it will do, is what a zero-dependency philosophy actually means in practice. It is not asceticism for its own sake. It is refusing to make someone else's low-end phone pay for a convenience you could have gotten for free.

II. The Ground Truth: What the Web Actually Weighs in 2026

The Page Has Been Gaining Weight for a Decade, and It Has Not Stopped

HTTP Archive's Web Almanac, drawing on a crawl of more than 17 million live websites, put the median mobile home page at 2.36 megabytes as of July 2025 — up 8.4% from the year before, and a 202.8% increase over the 845 kilobyte median mobile page of a decade earlier, in July 2015. Desktop pages fared no better, growing 7.8% year-over-year to a median of roughly 2.7 megabytes. JavaScript alone accounted for a median of 664 kilobytes on desktop home pages and 690 kilobytes on their inner pages, with the heaviest 10% of sites shipping close to two megabytes of JavaScript before a single pixel of content has necessarily rendered.

It is worth sitting with a comparison one developer offered in mid-2026, having watched a hobbyist ship a fully playable first-person shooter — multiple levels, several enemy types, textures, and music — inside a 64-kilobyte Windows executable: the median JavaScript payload on an ordinary website today is roughly ten times the size of that entire game.

Interaction to Next Paint Is Where the Bloat Becomes Visible to Users

In March 2024, Google formally replaced First Input Delay with Interaction to Next Paint (INP) as the third Core Web Vital, alongside Largest Contentful Paint and Cumulative Layout Shift. Where FID measured only the delay before a page's first interaction, INP measures the full round trip — from input to the browser painting a response — across every interaction a user makes during a session, weighted toward the worst ones rather than an average. Google further refined the underlying measurement methodology in 2026 to weight sustained interaction latency more heavily, specifically so that a handful of genuinely painful stutters can no longer be statistically hidden behind a majority of fast, trivial ones.

The results, measured against real users through Chrome's User Experience Report rather than a lab benchmark, are not flattering. As of the May 2026 CrUX data release, only 55.9% of tracked origins passed all three Core Web Vitals, and roughly 40% of mobile origins were still failing the INP threshold of 200 milliseconds outright. INP's punishing quality is precisely because it is measuring what a zero-dependency philosophy exists to fix: the cumulative main-thread cost of parsing, compiling, and executing everything a page decided to load, running on hardware that is, for a very large share of the world's users, considerably less capable than the machine the developer built and tested on.

jQuery Turned Twenty, and Is Still on Two-Thirds of the Web

On 14 January 2026, jQuery — the library that, more than any other single piece of software, defined how a generation of developers wrote JavaScript — turned twenty years old. Three days later, on 17 January 2026, its maintainers shipped jQuery 4.0.0, the first major version release in nearly a decade. According to W3Techs' measurements, as of mid-2026 jQuery remains present on roughly two-thirds to seventy percent of all websites, and on the large majority of sites where any JavaScript library is detectable at all — a persistence owed substantially to the fact that it ships by default inside WordPress, which itself powers over 42% of the web.

The library itself is not enormous by today's standards — roughly 87 kilobytes uncompressed, about 30 kilobytes gzipped — but on a mid-range mobile device that weight is not free: independent measurements attribute an additional 150 to 300 milliseconds of Total Blocking Time to jQuery's parse-and-execute cost alone, before accounting for whatever the site actually does with it, and its event-delegation model adds measurable overhead to exactly the kind of interaction Interaction to Next Paint is now scoring. More concerning from a security standpoint: 2026's Open Source Security and Risk Analysis report found that four long-standing jQuery cross-site-scripting vulnerabilities continue to affect an estimated 25–28% of enterprise codebases, not because the flaws are new or undiscovered, but because a library adopted twenty years ago is still quietly present, unpatched, in projects nobody thinks of as “using jQuery” anymore.

Platform Capabilities vs. Third-Party Dependencies Architectural Spectrum

Every Dependency Is Also a Trust Relationship, and Trust Has Been Breaking

The bytes are one cost. The second, less discussed cost of a deep dependency tree is that every package you install is also a promise that its maintainer's npm account, GitHub credentials, and CI pipeline will never be compromised — a promise the ecosystem has broken repeatedly and expensively in recent memory. On 8 September 2025, an attacker gained control of a widely trusted maintainer's npm account through a convincing phishing email and published malicious versions of eighteen packages, including two of the most foundational utilities in the entire JavaScript ecosystem, chalk and debug, which between them accounted for more than 2.6 billion weekly downloads. The payload targeted cryptocurrency wallet transactions in the browser, silently rewriting destination addresses. Security researchers at Wiz estimated that roughly one in ten cloud environments were touched by the compromised packages within the first two hours alone, before the malicious versions were pulled.

That incident was not isolated. Amazon's threat intelligence team subsequently linked the chalk/debug compromise, an earlier March 2025 compromise of a crypto-related package, and a March 2026 compromise of axios — a library used by well over 100 million projects weekly — to the same North Korea-linked threat actor, operating through the identical playbook each time: socially engineer a trusted maintainer, publish a poisoned update, let automatic dependency updates do the rest. A self-propagating worm nicknamed Shai-Hulud, which spreads by stealing a compromised developer's own publishing credentials and using them to infect the packages they maintain, resurfaced in a third generation in late December 2025. As recently as August 2026, a credential-stealing payload with a built-in persistence mechanism was found shipped inside keyv, a package present in tens of thousands of production environments.

None of this is an argument that open-source software is untrustworthy in general. It is an argument that dependency count is a security metric, not merely a convenience metric — every additional package in a lockfile is another maintainer whose inbox, another CI token, another supply-chain link that a project's security now silently depends on, whether or not anyone remembers agreeing to that dependency.

III. The Principle: Prefer the Platform

None of the preceding is an argument for writing everything by hand in raw JavaScript out of stubbornness. It is an argument for a specific ordering of preference, applied deliberately at the moment a developer reaches for a new dependency: first, ask whether the browser platform itself — native CSS, or a built-in browser API — already does this, well, for free, with no download, no parse cost, and no third-party maintainer standing between your users and a working page. Only when the honest answer is no should a library enter the conversation, and even then, the smallest, most narrowly scoped one available should win over the general-purpose framework.

By 2026, the honest answer to “does the platform already do this” has changed for a genuinely large number of interface patterns that, as recently as three or four years ago, reliably required JavaScript. What follows is a survey of where that line currently sits — not where a marketing page claims it sits, but where actual, checkable browser support sits as of the middle of 2026.

IV. What the Browser Now Does For You

Layout That Responds to Its Container, Not the Viewport

Container queries — the ability to style an element based on the size of its own containing element rather than the overall browser viewport — reached what the specification community calls Baseline widely available status by 2023 and, by 2026, are described across multiple independent surveys of the CSS landscape as having reached “universal,” production-safe support across all major browsers. Any component that previously used a ResizeObserver in JavaScript purely to measure its parent and toggle a class in response can, in the overwhelming majority of cases, be replaced with a native @container query today, with no runtime cost at all.

Conditional Styling Without a Class-Toggling Script

The :has() selector — which allows a parent element to be styled based on the state of its descendants, something CSS was historically unable to do at all — is likewise settled, Baseline-supported territory in every major browser by 2026. Patterns that used to require a small JavaScript utility watching for a checkbox's checked state, or a form field's validity, purely to toggle a sibling class, can very often be expressed directly in a single CSS selector instead.

Nesting, Without a Preprocessor

Native CSS nesting — writing selectors inside one another the way Sass long allowed — is now supported directly by the browser, meaning a meaningful share of projects that pulled in a Sass or PostCSS build step purely for nesting syntax no longer need to. The nesting itself ships with zero runtime weight, because it is compiled away by the browser's own CSS parser, not by a bundler.

Page and State Transitions, Without a Router Library's Animation Layer

The View Transitions API — which lets a developer declare that the browser should automatically animate between two DOM states, or between two full page navigations, by capturing before-and-after snapshots and cross-fading or morphing between them — has matured substantially. Single-document view transitions (animating a change within one page, such as a filtered list re-rendering) have been stable since 2023; cross-document view transitions (animating a full navigation from one page to another, the pattern that used to require a JavaScript single-page-application router with a dedicated transition library bolted on) became broadly usable across Chrome, Edge, and Firefox during 2024–2025, with Safari support arriving in 2025. Refinements shipped between October 2025 and April 2026 — including view-transition-class, which lets a single animation rule target a whole collection of elements at once, and JavaScript-settable View Transition Types, which let an app signal whether a transition is conceptually “forward” or “backward” — mean that, as of mid-2026, a genuinely large share of what used to require a client-side router's dedicated animation library can be declared in a handful of lines of CSS instead. The one universal caveat, which applies to every animation technique discussed in this article without exception: always branch on the prefers-reduced-motion media query, so that users who have told their operating system they do not want motion effects are not served them anyway.

Scroll-Linked Effects, Off the Main Thread

Scroll-driven animations — content that fades in, scales, or otherwise changes as the user scrolls, tied directly to scroll position rather than to elapsed time — shipped in Chrome from July 2023 and reached Safari and Firefox through 2025. This is one of the more consequential replacements on this list specifically for the argument this article is making, because the JavaScript alternative — a scroll event listener, typically paired with requestAnimationFrame throttling and often an IntersectionObserver to know when to even start listening — is a well-documented performance trap. Naive scroll listeners fire continuously and run on the main thread, and the jank they cause is worst precisely on the low-end, low-RAM devices that a zero-dependency, performance-first philosophy exists to protect. The native CSS version runs on the browser's compositor thread, entirely outside the main thread the user's clicks and taps are competing for.

Dropdowns, Tooltips, and Modals Without a Positioning or Modal Library

The Popover API, stabilized across all major browsers by 2024, provides a native, accessible way to show and dismiss dismissible layers — replacing a meaningful share of what modal libraries used to be needed for, including built-in light-dismiss behaviour and top-layer rendering that used to require careful manual z-index management. CSS Anchor Positioning, which lets an element be visually tethered to another element on the page — the core function of libraries like Popper.js or its successor Floating UI, used for years to position tooltips and dropdowns correctly near their trigger — shipped in Chrome from April 2024, with Safari and Firefox support following through 2025 and into 2026. Anchor positioning is, as of this writing, the least settled feature on this list: independent trackers of the CSS landscape in 2026 consistently flag it as needing a JavaScript fallback for browsers that do not yet support it, or scoping its use to environments where the development team controls which browser is in play. It is the feature most likely to look finished in a demo and then fail quietly for a meaningful slice of real visitors — precisely the kind of gap a team serious about actual device and browser diversity needs to check for itself, on MDN's Baseline status indicator, rather than assume.

Colour and Theming Without a Preprocessor's Colour Functions

Native CSS now includes color-mix(), the light-dark() function for one-line light/dark theme switching, and the OKLCH colour space for perceptually uniform colour manipulation — collectively covering a large share of what Sass's colour functions, or a small JavaScript theming utility, used to be reached for.

Breaking Up Long Tasks Without a Scheduling Library

On the JavaScript side specifically — because a zero-dependency philosophy is about removing unnecessary code, not removing JavaScript as a category — the platform has also grown native tools for the exact problem INP measures. scheduler.yield(), alongside the Long Animation Frames API surfaced through the web-vitals library from version 4 onward, gives developers a native way to voluntarily break up long-running JavaScript tasks so the browser can paint and respond to input in between, without reaching for a third-party task-scheduling library. The IntersectionObserver and ResizeObserver APIs — themselves native, dependency-free browser primitives rather than libraries — remain the correct tool for the genuine cases container queries and scroll-driven animations don't cover, such as triggering a data fetch when an element scrolls into view. The Web Animations API provides native, JavaScript-controlled animation with performance characteristics competitive with dedicated animation libraries for a large share of common cases — full-featured animation libraries still earn their place for complex sequencing and physics-based motion, but a surprising number of projects reach for one to accomplish what element.animate() already does natively.

Native Elements That Used to Be Widgets

The <dialog> element provides native modal semantics, focus trapping, and light-dismiss. The <details> and <summary> elements provide a native, keyboard-accessible disclosure widget — an accordion — with zero JavaScript. Native HTML form validation (required, pattern, type="email", and the associated :invalid/:user-invalid styling hooks) covers a meaningful share of what form-validation libraries exist to do, particularly for straightforward business forms that don't need cross-field asynchronous validation logic.

V. Where the Platform Genuinely Is Not Enough Yet

A zero-dependency philosophy that pretends the platform is finished is not rigour, it is denial, and denial produces worse outcomes than honest dependency management does. As of mid-2026, several real gaps remain, and pretending otherwise sends teams chasing broken production experiences in the name of purity:

  • Complex, cross-field, asynchronous form validation at genuine scale still generally benefits from a small, purpose-built library rather than hand-rolled logic — the native validation API covers the straightforward eighty percent, not the harder twenty.
  • Anchor positioning, as noted above, still needs a JavaScript fallback path for full cross-browser reliability in 2026; teams shipping to an audience with meaningfully older browsers should not treat it as universally safe yet.
  • Complex state management in large, deeply interactive applications is a genuinely different problem than the interface-polish patterns discussed above, and a lightweight state library is frequently still the right call — the zero-dependency argument is about interface chrome and animation, not an argument against all abstraction everywhere.
  • Charting, rich text editing, and drag-and-drop at production quality remain areas where a well-chosen, narrowly scoped library reliably beats a hand-rolled equivalent, because the edge cases these problems accumulate over years of real-world use are not trivially reproducible from a specification document.

The discipline, in other words, is not zero dependencies as an absolute. It is treating every dependency as a decision that must justify its weight, its maintenance burden, and its position in the trust chain — rather than a decision made once, by habit, at the start of a project, and never revisited.

VI. The Housekeeping Nobody Enjoys, But That Compounds

Two further, less glamorous practices consistently separate genuinely lean production sites from ones that only look lean in a demo:

Check what your build tooling is actually shipping, not what you assume it ships. An estimated 95% of production sites in 2026 still run their code through Babel, and a significant share of those still transpile modern, universally supported syntax — optional chaining, nullish coalescing, async/await — down into verbose, slower-executing ES5, because a browserslist configuration set to target Internet Explorer 11 years ago was never revisited after Microsoft ended support for that browser in June 2022. This is dead weight with a name in the performance community: a “zombie polyfill,” present not because any real user needs it, but because nobody scheduled the ten minutes it takes to delete a stale configuration line.

Measure transfer size, not raw file size. A 300-kilobyte raw JavaScript file might compress to 80 kilobytes over the wire with Brotli — the number that actually determines how long a user on a constrained connection waits. Bundle visualizer tooling built into modern bundlers can report gzip and Brotli sizes directly, and any serious performance review should be reading those figures, not the uncompressed ones, when deciding whether a dependency's weight is acceptable.

VII. A Practical Test Before Adding Anything

Before a new dependency enters a project, three questions, asked in order, do most of the useful work:

  1. Does native CSS already do this? Check the feature's Baseline status on MDN directly, rather than relying on memory or a two-year-old blog post — this landscape has moved quickly, and yesterday's “not ready yet” is often today's universal support.
  2. Does a built-in browser API already do this — IntersectionObserver, ResizeObserver, the Web Animations API, <dialog>, native form validation — without a third-party runtime?
  3. If neither, is there a genuinely small, narrowly scoped library that solves exactly this one problem, rather than a general-purpose framework whose one useful feature is accompanied by fifty unused ones?

Only after all three questions have been asked honestly does reaching for a dependency stop being a habit and start being a decision — one made in view of its real cost: the kilobytes it adds to a page a stranger's ageing phone must parse before responding to a tap, and the maintainer's inbox it quietly adds to the list of things that must never be compromised for the site to stay safe.

VIII. Closing

There is a kind of craftsmanship that shows itself not in what was added, but in what was correctly left out — the carpenter who does not reach for another brace because the joint was already sound, the storyteller who trusts a single well-placed silence more than another sentence. The web, over the last decade, largely forgot this instinct. It reached for another library the way a nervous cook reaches for another spice, convinced that more was the same thing as better.

It was not. The nurse's clinic still runs on a mid-range phone. The trader's browser tab is still competing with three other open apps for the same gigabyte of RAM. The bars on the signal indicator still fall to nothing more often than any of us building these pages would like to admit. Every kilobyte a team chooses not to ship is a kilobyte that phone did not have to fight through, on a network that did not have to carry it, paid for out of a data budget that was never unlimited to begin with. That is not a constraint to apologise for. It is, done well, the whole discipline.

Sources

Figures cited reflect the most recent publicly available measurements at the time of writing (August 2026), drawn from HTTP Archive's Web Almanac, W3Techs, Google's Chrome UX Report, and named security research teams, and are attributed to their original sources throughout.


Continue Exploring the Journal

Return to the index of published engineering essays and research archives.

View Journal Index →