This article is published in English.
Native Browser APIs Replacing Popular npm Packages in 2026
Explains how native JavaScript and CSS features like Signals, the pipeline operator, Temporal, and Anchor Positioning are replacing common npm packages.
It's worth interrogating your own package.json for a second: how many of those entries exist purely to fake a capability the browser has since learned to do on its own?
For most of the past ten years, the default response to almost any frontend headache was "grab a package." Need state management? Reach for Redux, Zustand, or MobX. Need dates? Moment or dayjs. Need utility helpers? lodash. Need animation? GSAP or Framer Motion. Every framework accumulated its own pile of glue code to patch holes in the platform.
By 2026, that pattern is shifting faster than most teams realize. TC39 and the major browser vendors have spent the last several years steadily building native equivalents for whole categories of third-party tooling. Below are five packages you can seriously consider dropping from your dependencies right now, plus two more that have only gotten halfway to obsolete.
1. State management libraries — native Signals just landed
Replaces: Redux, Zustand, MobX, Recoil, Jotai, and framework-native reactivity such as Vue's own reactive references
Replaced by: the standardized Signal primitives (State, Computed, and the sub subscription helper)
Few problems have split frontend development as sharply as picking a way to manage state. React's ecosystem moved through Redux, then Zustand, then Jotai, then Recoil. Vue built its own reactivity primitives and later layered Pinia on top. Solid and Svelte, meanwhile, were built around signals from the start. Each framework invented its own version of the reactive primitive, which meant reusing state logic between frameworks was nearly impossible.
That constraint eased in 2026 once TC39's native Signals proposal reached implementation. The reactive primitive now lives directly inside the JavaScript engine:
// No library. This runs in the browser as-is.
const counter = new Signal.State(0);
const doubled = new Signal.Computed(() => counter.get() * 2);
Signal.sub(() => {
console.log(`count: ${counter.get()}, doubled: ${doubled.get()}`);
});
counter.set(1); // triggers the subscription automatically
Here's what that shift actually buys you:
- Your state logic can be authored once and reused everywhere — React, Vue, Solid, and Svelte can all read from the same underlying primitive
- "State management library" is fading as a standalone product category
- You strip tens or even hundreds of kilobytes out of your bundle immediately
Some engineers have framed this as closing out a decade-long standoff between frontend frameworks. Once the reactive core is shared across ecosystems, the remaining differences between frameworks come down to template syntax and component structure — not the mechanics of how state updates propagate.
2. lodash — the pipeline operator ends "callback hell's cousin"
Replaces: lodash, ramda, and most _.chain() usage
Replaced by: the pipeline operator, |>
Chances are you've written something like this before:
const result = fn3(fn2(fn1(data)));
That kind of nested function call — where you have to read from the inside out just to figure out the actual execution order — has long been one of JavaScript's worst readability offenders. lodash's _.chain() used to paper over this, but it meant dragging in the entire library just to get a cleaner call order.
As of 2026, the pipeline operator advanced to Stage 4 in ES2026. The same expression now reads in natural top-to-bottom order:
const result = data
|> fn1
|> fn2
|> fn3;
Paired with native await support, asynchronous pipelines end up reading almost like shell scripts:
const user = userId
|> fetchUser
|> await
|> extractProfile
|> await
|> formatOutput;
The pipeline operator addresses a readability issue, whereas lodash was mostly solving the older problem of the language lacking functional utilities outright. Now that piping is built in, Array.prototype methods have matured, and structuredClone is universally available, lodash's justification for existing has narrowed considerably. If it's still sitting in your dependencies in 2026, trimming it is probably the easiest bundle-size win available to you.
3. dayjs and moment — Temporal API hits 98% browser coverage
Replaces: moment.js, dayjs, and date-fns for the majority of use cases
Replaced by: the Temporal API
This entry is the least contentious on the list. moment.js has sat in maintenance-only mode for years, and even the "lightweight" dayjs still adds over 2KB to your bundle. Meanwhile, the Temporal API has reached 98% browser coverage.
// dayjs
const d = dayjs('2026-09-11').add(1, 'month').format('YYYY-MM-DD');
// Temporal
const d = Temporal.PlainDate.from('2026-09-11').add({ months: 1 }).toString();
Temporal isn't only about tidier syntax — it eliminates genuine bugs that date libraries have struggled with for years:
- Time zone handling is native, so no separate timezone plugin is needed
- Calendar system support is native, including non-Gregorian calendars
- Instances are immutable, avoiding the classic moment.js trap of accidentally mutating an object you thought was untouched
- Bundle size drops by 10 to 50KB
For projects with a heavy mobile audience, that 10–50KB reduction isn't just a nice-to-have — it translates directly into a better LCP score.
4. Popper.js and Floating UI — Anchor Positioning is now native CSS
Replaces: Popper.js, Floating UI, Tippy.js
Replaced by: CSS Anchor Positioning
If you've ever built a tooltip, you know the drill. You need a dropdown to show up right under a button. The old-school approach is position: absolute, hand-calculating top and left, then hooking up scroll and resize listeners so the thing doesn't drift out of place. Or you reach for Popper.js or Floating UI and tack on another dozen-plus kilobytes just to handle positioning.
By 2026, CSS Anchor Positioning takes care of this at the platform level:
/* Step 1: name the anchor element */
.button {
anchor-name: --my-trigger;
}
/* Step 2: pin the floating element to it */
.tooltip {
position: anchor(--my-trigger);
inset-area: bottom; /* below the anchor */
}
That's it — the entire solution. No JavaScript, no manual absolute-positioning math, no external library. Think of Anchor Positioning as a GPS lock for floating UI elements: point it at the trigger button, and it stays glued in place no matter how the page scrolls or the viewport resizes.
5. Sass and PostCSS — native nesting, @layer, and @scope
Replaces: Sass, Less, PostCSS and its plugin ecosystem
Replaced by: native CSS nesting, @layer, and @scope
There was a time when Sass and Less felt mandatory. Variables, nesting, mixins, reusable functions — plain CSS simply didn't offer any of that. That's no longer the case in 2026.
Native nesting:
.card {
background: white;
& .title { font-weight: 600; }
&:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
}
@layer for controlling cascade order:
@layer reset, base, components, utilities;
@scope for lightweight style isolation:
@scope (.card) to (.card__content) {
:scope { border-radius: 8px; }
}
OKLCH has become the standard color format:
:root {
--color-primary: oklch(0.65 0.2 250);
--color-hover: oklch(from var(--color-primary) calc(l - 0.1) c h);
}
Throw in container queries, precise text alignment via text-box, sibling-based positioning through sibling-index(), and scroll-driven animations — all of which are stable across browsers by 2026 — and Sass has shifted from a default requirement to an optional tool for most projects. If it's still an automatic addition to your stack, it's worth checking how many of the features you're using it for are now handled natively.
Two packages that are only half-replaced
Not every item on this list has a full native replacement yet. Two are close, but the platform hasn't fully caught up.
Animation libraries — GSAP and Framer Motion versus native View Transitions. The View Transitions API became stable with React 19.3, and its <ViewTransition> component can automatically animate elements as they enter, exit, move, or change size. Scroll-driven animation, via animation-timeline: scroll(), gives you progress indicators, parallax effects, and fade-ins with no JavaScript at all. That said, for intricate, manually choreographed animation sequences — the kind GSAP specializes in — native tooling still isn't a full substitute.
AI inference — ONNX Runtime Web versus WebNN. For browser-based model inference, the WebNN API can access system-level NPU acceleration directly, sidestepping the need to load tens of megabytes of ONNX runtime code.
const context = await navigator.ml.createContext();
const builder = new MLGraphBuilder(context);
// build the inference graph...
const output = await context.compute(graph, inputs);
The limitation: WebNN still doesn't have complete browser support, so ONNX Runtime Web remains the more dependable choice for the time being.
Removing all five of these categories from a mid-sized frontend codebase can cut 100 to 300KB from your dependency footprint. On a slow mobile connection, that reduction can translate into 1 to 2 seconds shaved off first paint.
The takeaway
Frontend development in 2026 is living through a native-platform resurgence. TC39 and browser engines are absorbing ground that used to belong exclusively to the npm ecosystem — state management, functional helpers, date handling, floating-element positioning, and CSS preprocessing. Problems that once required pulling in a package now have answers built directly into the browser.
JavaScript is starting to look like a genuinely self-sufficient platform language. The skill worth developing isn't deep expertise in any one framework or library — it's judgment about when the platform is enough and when a dependency still pulls its weight.
So take a look at your package.json: how many lines could you delete today?