你的
package.json里,有多少依赖是可以用浏览器原生能力替代的?过去几年,前端圈有一个心照不宣的习惯:遇到问题,先找 npm 包。状态管理用 Redux/Zustand,日期处理用 dayjs/moment,工具库用 lodash,动画用 GSAP/Framer Motion,状态用 Signals 还要额外引库。但现在,浏览器和 JavaScript 语言本身,正在把它们的饭碗一个一个端走。
2026 年,TC39 和各大浏览器引擎以前所未有的速度吞并了曾经属于第三方库的领地。以下这 5 个 npm 包,你已经可以从项目里删掉了。
一、删掉状态管理库:原生 Signals 已经落地
被替代的包: Redux、Zustand、MobX、Recoil、Jotai、Vue 的 ref(在跨框架场景下)
替代者: Signal.State / Signal.Computed / Signal.sub
过去十年,前端圈最大的分裂之一就是状态管理。React 有 Redux、Zustand、Jotai、Recoil;Vue 有 ref、reactive、Pinia;Solid 和 Svelte 从第一天就是 Signals 驱动。
每个框架都有自己的响应式原语,跨框架的状态逻辑复用几乎是不可能的。
2026 年,TC39 的 原生 Signals 提案正式落地。JavaScript 引擎层面统一了响应式原语。
javascript
// 无需引入任何库,直接在浏览器运行
const counter = new Signal.State(0);
const doubled = new Signal.Computed(() => counter.get() * 2);
Signal.sub(() => {
console.log(`当前计数:${counter.get()},两倍值:${doubled.get()}`);
});
counter.set(1); // 自动触发更新
这意味着什么?
- 你的状态管理代码可以一次编写,到处运行------React、Vue、Solid、Svelte 都能用同一套原语
- "状态管理库"这个品类,正式开始退出历史舞台
- 依赖体积直接减少几十到几百 KB
有开发者形容这是"前端圈十年分裂的终结"。当底层响应式原语统一后,框架之间的差异只剩下模板语法和组件模型了。
二、删掉 lodash:管道操作符终结"嵌套地狱"
被替代的包: lodash、ramda(以及大量 _.chain() 用法)
替代者: 管道操作符 |>
先看一段你肯定见过的代码:
javascript
const result = fn3(fn2(fn1(data)));
这种"俄罗斯套娃"式的函数嵌套,是前端代码可读性最大的杀手之一。lodash 的 _.chain() 曾经是解法,但它引入了整个库的体积。
2026 年,管道操作符(Pipeline Operator)正式进入 ES2026 Stage 4。
javascript
const result = data
|> fn1
|> fn2
|> fn3;
配合 await 的原生支持,异步流处理写起来像 Bash 脚本一样顺滑:
javascript
const user = userId
|> fetchUser
|> await
|> extractProfile
|> await
|> formatOutput;
管道操作符解决的是代码可读性问题,而 lodash 解决的是函数式编程的工具问题。 当语言原生支持管道、Array.prototype 方法已经足够完善、structuredClone 原生可用时,lodash 的存在价值被大幅压缩了。
如果你还在用 lodash,2026 年是最好的"减肥"时机。
三、删掉 dayjs / moment:Temporal API 浏览器覆盖率 98%
被替代的包: moment.js、dayjs、date-fns(大部分场景)
替代者: Temporal API
这是最没有争议的一个。
moment.js 已经停止维护多年,dayjs 虽然轻量但仍有 2KB+ 的体积。而 Temporal API 在 2026 年的浏览器覆盖率已经达到 98%。
javascript
// 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 的优势不只是语法更清晰:
- 时区处理是原生的 ,不需要
timezone插件 - 日历系统是原生的,支持非公历日历
- 不可变对象,不会出现 moment 那种"改了原对象还不自知"的坑
- 包体积直接减少 10KB-50KB
对移动端项目来说,这 10-50KB 的包体积削减,就是 LCP 指标上的真金白银。
四、删掉 Popper.js / Floating UI:Anchor Positioning 原生支持
被替代的包: Popper.js、Floating UI、Tippy.js
替代者: CSS Anchor Positioning
做 tooltip 的人都知道这个痛:
你想让一个下拉菜单出现在按钮下方。传统方案是------用 position: absolute,手动计算 top/left,写一堆 JavaScript 监听 scroll 和 resize 事件实时调整位置。或者引入 Popper.js / Floating UI,为了一个 tooltip 多加载十几 KB 的代码。
2026 年,CSS Anchor Positioning 已经可以原生解决这个问题:
css
/* 第一步:给触发元素命名锚点 */
.button {
anchor-name: --my-trigger;
}
/* 第二步:让浮层定位到锚点 */
.tooltip {
position: anchor(--my-trigger);
inset-area: bottom; /* 在锚点下方 */
}
就这两段 CSS。不需要 JavaScript,不需要绝对定位的体操动作,不需要引入任何库。
Anchor Positioning 就像给浮层装了 GPS 自动跟随系统------你只需要说"跟着那个按钮走",它就会自动保持完美的相对位置,无论页面怎么滚动、缩放。
五、删掉原生嵌套的 CSS 预处理器:PostCSS、Sass
被替代的包: Sass、Less、PostCSS + 各种插件
替代者: CSS 原生嵌套 + @layer + @scope
Sass 和 Less 曾经是前端开发的"标配"。变量、嵌套、mixin、函数------这些能力在原生 CSS 里曾经完全没有。
但 2026 年的 CSS 已经完全不一样了:
原生嵌套:
css
.card {
background: white;
& .title { font-weight: 600; }
&:hover { box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
}
@layer 管理层叠顺序:
css
@layer reset, base, components, utilities;
@scope 实现轻量样式隔离:
css
@scope (.card) to (.card__content) {
:scope { border-radius: 8px; }
}
OKLCH 成为颜色事实标准:
css
:root {
--color-primary: oklch(0.65 0.2 250);
--color-hover: oklch(from var(--color-primary) calc(l - 0.1) c h);
}
容器查询、text-box 精准文字对齐、sibling-index() 兄弟元素定位、滚动驱动动画------这些原生 CSS 能力在 2026 年都已经稳定可用。
对于大多数项目来说,Sass 和 PostCSS 已经从"必需品"变成了"可选品"。 如果你还在用 Sass,不妨评估一下:你的项目里有多少 Sass 特性是原生 CSS 已经能替代的?
六、还有两个"半替代"的包
6.1 动画库:GSAP / Framer Motion → 原生 View Transitions + 滚动驱动动画
View Transitions API 在 React 19.3 中已经稳定------<ViewTransition> 组件可以让元素在进入、退出、移动、缩放时自动播放动画。
滚动驱动动画 (animation-timeline: scroll())让进度条、视差滚动、渐显效果可以零 JavaScript 实现。
但对于复杂的时序动画(比如 GSAP 的 timeline 编排),原生方案还无法完全替代。
6.2 AI 推理库:ONNX Runtime Web → WebNN API
如果你在浏览器里跑 AI 模型,WebNN API 可以直接调用系统级 NPU 算力,不需要加载几十 MB 的 ONNX 运行时。
javascript
const context = await navigator.ml.createContext();
const builder = new MLGraphBuilder(context);
// 构建推理模型...
const output = await context.compute(graph, inputs);
不过 WebNN 目前浏览器覆盖率还不完整,ONNX Runtime Web 仍然是更稳妥的选择。
七、2026 年的前端"瘦身"清单
| 被替代的包 | 替代者 | 浏览器支持 | 可删体积 |
|---|---|---|---|
| Redux / Zustand | 原生 Signals | 全平台 | 20-100KB |
| lodash | 管道操作符 + Array 方法 | 全平台 | 50-100KB |
| dayjs / moment | Temporal API | 98% | 10-50KB |
| Popper.js / Floating UI | CSS Anchor Positioning | 全平台 | 10-30KB |
| Sass / PostCSS | 原生嵌套 + @layer | 全平台 | 构建时依赖 |
如果把上面这 5 个都删掉,一个中型前端项目的依赖体积可以减少 100-300KB。 在移动端弱网环境下,这可能意味着首屏加载时间减少 1-2 秒。
写在最后
2026 年的前端,正在经历一场 "原生复兴" 。
TC39 和浏览器引擎以前所未有的速度吞并了第三方库的领地。状态管理、函数工具、日期处理、浮层定位、CSS 预处理------这些曾经需要引入 npm 包才能解决的问题,现在浏览器原生就能做到。
JavaScript 正在变得越来越像一种"完备"的操作系统语言。 作为开发者,核心竞争力不再是熟练使用某种框架或库,而是知道什么时候该用原生能力、什么时候该引入依赖。
你的 package.json 里,有多少依赖是可以删掉的?
评论区聊聊:你最想删掉项目里的哪个 npm 包?