删掉这5个npm包:前端依赖瘦身与原生API替代指南

发布时间:2026/9/19 7:13:37
删掉这5个npm包:前端依赖瘦身与原生API替代指南 如果你点进这篇文章十有八九跟我一样某天清理 package.json 时忍不住开始算这里 200 多个 dependencies到底还有多少是“历史遗留问题”。2026 年再回头我最大的感触是这几年前端工具链最大的变化不是又出了什么新框架而是浏览器和 Node.js 本身正在一点点把那些我们习以为常的 npm 包重新变成“非必需品”。这些年我接手过不少老项目也帮团队做过依赖瘦身最常被问的一句话是“这个包不用了那用什么”这篇文章想直接告诉你答案有 5 个 npm 包在 2026 年这个时间点大部分项目完全可以删掉了。删除之后不仅不影响功能反而让代码更贴近标准、更容易被新人接手。当然我会把替换方案、迁移步骤和踩坑点一起写清楚方便你直接照着改。1. 为什么 2026 年还要纠结“删不删包”这件事1.1 依赖的成本比你看到的安装时间更隐蔽很多团队对依赖数量不敏感总觉得“npm install 不也就几十秒吗”。但依赖的真实成本横跨整个软件生命周期锁文件体积、CI 缓存命中率、npm audit扫描面、漏洞披露后的应急响应范围以及打包时即便被 tree-shaking解析器也得先扫一遍整个包的入口和模块图。我见过一个实际案例一个内部中后台项目只是引了一个moment首屏 bundle 就多了 70KBgzip 前 300KB 左右而产品需求里真正用到的只是“格式化成YYYY-MM-DD”和“当前时间加减几天”。这样的用法用原生Intl.DateTimeFormat或几行手写函数就能解决却让所有访问后台的员工白白承担了下载和解析成本。这里可以用生活里的例子类比这就像你为了拧一颗螺丝专门买了一个 40 件的工具箱然后把整个工具箱都背在身上出门。螺丝刀本身不重重的是那些你可能永远用不到的其他工具。1.2 标准库已经把缺口补上了过去我们离不开第三方包根本原因是原生能力确实不行。但这几年变化很大浏览器端fetch、URL、URLSearchParams、Object.fromEntries、Array.prototype.at、structuredClone、Intl系列陆续跟进Node.js 端全局fetchNode 21 稳定Node 20 已默认可用、fs.rmSync、fs.cpSync、--env-file参数、内置 test runner都在快速补齐。换句话说很多 npm 包当年解决的问题如今已经是“平台能力”而不是“第三方能力”了。2026 年还把它们留在 dependencies 里就像买了新手机却还在用十年前的数据线——不是不能充电而是没必要占着那个口。1.3 什么时候不应该删必须说明删包不是政治正确别为了删而删。如果项目还要兼容 IE11或者目标环境是 Node 16 以下的老运行时那fetch、structuredClone这些原生方案就得自己打 polyfill这时候保留第三方包反而是更稳的选择。我建议的判断标准就三条一是你明确知道自己的运行环境是什么二是项目有足够的测试保护改完能确认行为没变三是替换成本低于长期维护成本。满足这三条再动手。2. 这 5 个 npm 包的首选替代方案与迁移方法先给个速览表再逐个拆。待删 npm 包典型职责原生替代方案2026 年推荐状态axiosHTTP 请求fetch / undici大部分项目可直接替换lodash工具函数集合ES6 原生方法合集按需迁移大多可直接删moment.js日期时间处理Intl / Temporal / dayjs 按需强烈建议替换dotenv加载环境变量node --env-fileNode 20.6 可完全替代rimraf跨平台删除目录fs.rmSyncNode 14.14 可完全替代2.1 axios 替换从拦截器到超时处理axios 在很长一段时间里是前端请求库的默认选择因为它封装了请求拦截、响应拦截、取消请求、超时处理等等。但 2026 年浏览器和 Node.js 都内置了 fetch大部分项目的需求并不需要 axios 那套复杂抽象。最简单的替换把axios.get(url, { headers })换成fetch(url, { headers })返回的是一个 Response 对象需要.json()或.text()取数据。这里有一个关键区别必须注意fetch 在 HTTP 状态码是 400、500 时并不会 reject它只在网络错误或 CORS 失败时才抛异常。所以原来 axios 的响应拦截器里判断response.status的逻辑迁移后要改成显式检查response.ok或response.status。// 改造前axios 版本 const res await axios.get(/api/user, { timeout: 5000 }); return res.data; // 改造后fetch 原生版本 const controller new AbortController(); const timer setTimeout(() controller.abort(), 5000); try { const res await fetch(/api/user, { signal: controller.signal }); if (!res.ok) { throw new Error(HTTP ${res.status}: ${res.statusText}); } return await res.json(); } finally { clearTimeout(timer); }取消请求用AbortController替代 axios 的CancelToken这是标准做法。拦截器逻辑则可以封装成一层 request 模块把 header 注入、token 刷新、统一错误提示放在一个函数里调用方无需感知底层用的是哪个实现。如果团队里改造任务重也可以先建一个request.js做适配层内部从 axios 换成 fetch业务方只改 import。2.2 lodash 替换ES6 原生方法就够了lodash 是“删包清单”里最容易出现分歧的一个因为它的 API 太全了。但说实话绝大多数项目只用到get、uniq、cloneDeep、debounce、groupBy、flattenDeep这么几个方法。这些在 2026 年的标准 API 里都有对应物lodash 方法原生替代_.get(obj, a.b)可选链 空值合并obj?.a?.b ?? defaultValue_.uniq(arr)[...new Set(arr)]_.cloneDeep(obj)structuredClone(obj)_.groupBy(arr, key)Object.groupBy(arr, (item) item[key])_.flattenDeep(arr)arr.flat(Infinity)_.pick(obj, keys)Object.fromEntries(keys.map(k [k, obj[k]]))举一个实际迁移例子原来我经常写import _ from lodash; const names _.uniq(users.map((u) u.name)); const detail _.get(user, profile.detail, 暂无);换成原生const names [...new Set(users.map((u) u.name))]; const detail user?.profile?.detail ?? 暂无;代码可读性反而更好因为读者不需要去查 lodash 文档也能看懂。需要提醒的是_.isEqual这种深比较目前没有一个完全等价的原生替代如果项目里大量用了深比较建议用JSON.stringify(a) JSON.stringify(b)做兜底但要注意它处理不了undefined、函数、循环引用。这种情况可以先保留一个独立的isEqual纯函数实现而不是整个 lodash 留在依赖里。2.3 moment.js 替换先考虑 Intl再考虑体积更小的库moment.js 是一个公认的“落日项目”官方早在 2020 年就宣布进入维护模式不再增加新功能只修严重问题。但它到今天还在不少老项目的 dependencies 里躺着原因多半是“改起来要动很多业务代码”。如果你只是做格式化、日期加减、时间差计算可以用原生Intl.DateTimeFormat配合少量代码解决。下面是一个常见场景的对比// 改造前moment return moment(date).format(YYYY-MM-DD HH:mm); // 改造后原生 Intl return new Intl.DateTimeFormat(zh-CN, { year: numeric, month: 2-digit, day: 2-digit, hour: 2-digit, minute: 2-digit, hour12: false, }).format(new Date(date)).replace(/\//g, -);如果项目里用到的 moment 特性确实很多比如时区转换、多语言、复杂的相对时间我的建议不是硬用原生而是先换到dayjs。dayjs 的 API 基本和 moment 一致但体积只有 moment 的十几分之一迁移时把 import 路径换掉大部分代码不用动然后再逐步替换到原生方案。2026 年更推荐的长期目标是等待Temporal被主流运行时支持到时候日期时间处理会彻底走向标准。2.4 dotenv 替换Node.js 原生支持加载 .env 文件dotenv 是另一个“工具链层”的依赖本身不进浏览器包但它同样占着 dependencies 里的一个位置。Node.js 从 20.6 开始支持--env-file参数21.7 又补了--env-file-if-missing文件不存在不报错这意味着如果你用的是 Node 20完全不需要在代码里import dotenv/config了。原来启动命令是node -r dotenv/config index.js现在可以改成node --env-file.env index.js如果要区分开发和生产环境可以为不同环境准备不同文件或者在 package.json 里写多个 script。比如{ scripts: { dev: node --env-file.env.development index.js, start: node --env-file.env.production index.js } }需要注意两点一是--env-file不会覆盖已经存在的 process.env 变量也就是说操作系统的环境变量优先级更高这种设计可以防止本地误覆盖线上配置二是不要在代码里直接依赖process.env在模块加载时就被注入的顺序否则迁移后可能出现变量未定义的奇怪问题。如果你们的部署平台比如 Docker、云平台本来就注入环境变量那连启动参数都可以省了。2.5 rimraf 替换fs.rmSync 一行命令搞定rimraf 当年解决的问题是“用 Node 跨平台地删除目录”。在 Node 14.14.0 之前原生fs.rmdirSync在递归删除这个问题上表现很不稳定所以大家习惯用rimraf dist vite build这种写法。现在 Node 原生方法已经成熟fs.rmSync配合{ recursive: true, force: true }就能完成同样的事情。在 package.json 里可以直接这样写{ scripts: { clean: node -e \require(fs).rmSync(dist, { recursive: true, force: true })\, build: npm run clean vite build } }如果项目里用了 TypeScript 或 ESM也可以写成一个clean.mjs脚本import { rmSync } from node:fs; rmSync(dist, { recursive: true, force: true });这里force: true的作用是目录不存在时不抛错正好对应 rimraf 的默认行为。另一个容易被忽略的点是如果你曾经依赖 rimraf 处理 Windows 上“文件被占用导致删除失败”的情况Native 的rmSync在某些边界上表现略有差异但绝大多数前端构建场景不会遇到真正遇到的话再用fs.rm的异步版本或错误重试也不迟。3. 删除依赖后的工程化改造与数据验证3.1 分批迁移先替换实现再从清单里移除直接删包然后全局搜索替换是最危险的做法一次改几百处代码出了 bug 很难定位。我通常把迁移拆成六个步骤每个步骤单独提交跑一次npx knip或npx depcheck列出这些包在整个代码库里的实际引用位置。建立映射清单每一个被引用的 API 对应什么原生替代方案。逐个模块替换每替换完一个模块就运行相关单测。全部替换后跑一遍完整测试包括 E2E。用 bundle 分析工具对比替换前后的产物体积差异。确认无问题后再从 package.json 里移除包并执行npm install更新锁文件。有个细节值得注意npx depcheck只能识别显式 import无法识别字符串形式的动态加载比如require(lodash/ methodName)这种写法。所以替换前最好全局搜一下有没有这种“间接引用”免得以为删干净了上线时才报模块找不到。3.2 用数据判断“值不值得删”删包之前可以先量化一下收益。以一个小型中后台项目为例我在一次实际改造中测到的大致数据如下依赖浏览器 bundle 体积gzip 后安装时间占比备注moment约 68KB中替换后立减axios约 12KB低若不封装体积收益一般但减少抽象层lodash全量 import约 24KB低如果一直用子路径 import体积本就可控dotenv0仅 Node 运行期低减少依赖树与审计面rimraf0仅构建期低减少依赖树与审计面从表面看真正对浏览器体积影响最大的是 moment 和 lodashaxios 和工具链类依赖更多是“减少依赖树复杂度”的收益。2026 年团队协作中每少一个包就少一份 API 学习成本和 license 审查工作这对长期维护的价值往往比体积数字更重要。3.3 兼容性矩阵与降级策略删包前要明确你的目标运行时。下面是一个我常用的兼容性对照表你可以根据项目实际情况调整能力Node 18Node 20现代浏览器近 2 年IE11全局 fetch可用experimental18.0 有可用且稳定20可用不可用AbortController可用可用可用不可用structuredClone17 可用可用可用不可用Object.groupBy不可用21 可用可用Chrome 117不可用fs.rmSync可用14.14可用不适用不适用--env-file不可用20.6 可用不适用不适用如果项目需要兼容旧环境不必一次性全都删可以分两个阶段第一阶段把 axios、moment、rimraf 这些替代方案已经成熟的包换掉第二阶段等基础设施升级到 Node 20 后再处理 dotenv。浏览器端如果遇到Object.groupBy不支持的场景用reduce做个兼容函数只用几行也不需要引 lodash。4. 我实际迁移中踩过的坑与排查清单4.1 高频问题迁移后行为变了但测试没发现最典型的是 fetch 的错误处理。axios 遇到 HTTP 500 会走进 catch而 fetch 默认不抛错这会导致线上接口报错时页面毫无反应或走到了成功分支。这个坑遇到过一次以后我会在迁移时强制要求所有换成 fetch 的地方必须显式处理res.ok。另一个高频问题来自structuredClone。它看起来和_.cloneDeep行为相似但两个大差异会坑到你一是structuredClone不能克隆函数和 DOM 节点二是它不保留原型链克隆出来的对象是纯对象。如果项目里有自定义类实例需要深拷贝直接替换会丢方法。这种情况下我会保留一个很小的cloneDeep函数而不是为了“彻底删除”硬换。4.2 如何在不回滚的情况下做验证“改完了但不确定对不对”——解决这个问题不能靠感觉要靠筛选条件。我给团队做迁移时会先用代码覆盖率工具跑一遍单测再把涉及这些包的页面都过一遍手工冒烟用例。重点检查的用例包括深链接进入页面时的数据加载、错误状态展示、表单提交失败提示、以及历史数据中特殊的空值/超时时间处理。如果项目没有自动化测试我会先提一个临时 PR用size-limit之类的工具做体积回归门槛同时把迁移前后两次接口请求的响应日志对比一轮。很多时候 bug 不是因为语法错误而是因为“错误的空值兜底”和“null vs undefined”的语义差异——这正是 lodash_.get返回 undefined 而可选链也返回 undefined、但中间层的空对象结构可能不同的原因。4.3 团队协作中的注意事项删包看起来是技术活其实是协作活。第一个要注意的是一个包被多个工程复用时先别急着在公共包或 monorepo 里改而是要先把所有调用方列清楚否则删完 A 项目的 importB 项目还在用。第二点是在 Code Review 阶段建立“新代码原生优先”的规则。我见过最理想的状态不是“今天删光所有包”而是立一个规矩新增代码不准用lodash旧代码慢慢迁移。这样半年后回头看旧依赖自然就会被更替掉团队也不需要在某一次大版本升级里承担所有风险。最后一个建议是把这次删除记录整理到团队 Wiki 里写清楚“为什么删、如何替代、有哪些坑”。否则过两年新同学接手看到fetch封装觉得不好用又引回 axios那这次改造就白做了。如果让我给一个最直观的体感数据过去一年我把公司两个老项目里的 axios、lodash、moment、rimraf 全部清掉后CI 安装耗时从接近 40 秒降到 20 秒出头锁文件少了十几 MB。但真正让我觉得值得的不是那点速度而是后来新同事接手时不再需要对着 lodash 文档查_.isEqual的语义——原生 API 读起来即看即懂。最后再分享一个小技巧如果你开始动手了可以顺便把chalk、commander、inquirer这类工具链包也放进观察清单。Node.js 的util.styleText、util.parseArgs和node:readline/promises现在都能接手它们的核心场景。2026 年的删包清单往后只会越来越长。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询