用Baseline给前端依赖做减法:少发JS的实用审计指南

浏览器平台能力持续增强,许多npm依赖已可以被原生API替代。本文介绍如何以Baseline为基准,系统审计并移除冗余依赖,减少打包体积,同时避免兼容性风险。
浏览器在追赶,你的依赖清单该更新了
大多数前端开发者的习惯是:装一个依赖,跑通测试,然后就再也不看它了。但浏览器平台从未停止进化——今天你 package.json 里躺着的不少库,可能早已被原生API覆盖。
以典型的中型JavaScript应用为例,压缩并gzip后,通常有60KB到90KB的依赖其实是平台已经能原生处理的。日期和数字格式化、HTTP请求、模态框、工具提示、深拷贝、数组分组……这些几年前还是“必须上库”的功能,如今多数已不再是短板。
依赖之所以还在,并非开发者懒惰,而是团队很少按Baseline的节奏重新审计依赖,或者根本没意识到浏览器功能迭代有多快。大家会跑 npm audit 查安全漏洞,却极少问一句:“这个库还在做浏览器做不了的事吗?”于是依赖就这么留了下来。
先搞懂Baseline的三个状态
Baseline是WebDX社区组发起的一个项目,用直白的方式告诉你某个Web特性在主流浏览器(Chrome、Edge、Firefox、Safari)中的可用性。特性分为三种状态:
- Limited availability:尚未在所有主流引擎中实现,依赖时需要降级方案。
- Baseline Newly available:刚在所有主流引擎中落地,最新浏览器可用,但老设备可能缺失。
- Baseline Widely available:已在所有主流引擎中稳定存在30个月,基本可以放心使用。
“Newly”到“Widely”之间的30个月窗口,对审计至关重要。Widely可用的特性,今天就能安心替换库;Newly可用的特性,则需要先确认你的用户群体,或者做好特性检测。后面的审计中,我们会区别对待这两种情况。
想查询某个特性的状态,可以用 webstatus.dev、MDN(每个参考页面顶部都有Baseline徽章),或者通过 web-features npm包编程查询。
删库前的三个问题
看到“浏览器现在支持了”就急着删库?先别急。表面零成本的替换,可能悄悄影响一部分用户,或者让你失去一个没意识到的依赖特性。
删任何库之前,先问自己三个问题:
1. 替代方案对我的用户群体是Baseline安全的吗?
不是“是否达到Baseline”,而是是否达到“Widely available”。如果只是“Newly available”,而你的用户还有不少在用旧浏览器(比如企业内部系统、教育机构),那替换就可能带来风险。
2. 我是否用到了库的“隐藏功能”?
很多库不仅仅是API的封装,还提供了边缘情况处理、polyfill、跨浏览器兼容逻辑。比如 Intl.DateTimeFormat 原生API对某些语言环境的支持可能不如 moment-timezone 全面。替换前,梳理一下你实际调用的API面,而不是只看文档首页。
3. 替换后的代码可维护性如何?
原生API通常更简洁,但有时候库的抽象更符合业务语义。如果团队已经习惯了某个库的写法,强行替换可能增加维护成本。性能收益 vs 团队学习成本,需要权衡。
按“簇”审计,而不是逐库排查
逐个检查依赖效率太低,而且容易漏。更高效的做法是按功能簇分组审计——因为收益往往是成组出现的。
以下是我常建议开发者优先检查的几组:
- 日期与数字处理:
Intl.DateTimeFormat、Intl.NumberFormat已覆盖大部分格式化需求。TemporalAPI(虽然还在推进中)未来会进一步替代date-fns和moment。 - HTTP请求:
fetch早已是Baseline Widely available,axios的很多高级功能(拦截器、取消请求)现在可以用AbortController和原生fetch实现。 - UI组件:
<dialog>元素原生支持模态框,popover属性覆盖工具提示和弹出层,CSS :has()选择器解决了很多原本需要JavaScript的样式逻辑。 - 数据操作:
structuredClone()是原生深拷贝,Array.prototype.groupBy()(或Object.groupBy())处理数组分组。
实操:把审计变成可重复的流程
光知道理论不够,你需要一个能反复执行的流程。我建议这样:
- 用
web-featuresnpm包扫描你的依赖,看看哪些库对应的能力已经是Baseline Widely available。 - 对每个候选替换项,跑三个问题检查(兼容性、隐藏功能、维护成本)。
- 做bundle体积对比——用
webpack-bundle-analyzer或vite-plugin-analyzer看实际节省了多少。 - 先灰度替换,再全面删除——在部分页面或功能上验证效果,确认无回归后再清理依赖。
平台仍有短板,别盲目追求“零依赖”
必须诚实:平台原生能力并不总是完备的。比如 Intl 对某些小众语言环境的支持不如成熟库细致;<dialog> 的样式定制在某些浏览器中仍有局限;fetch 的进度事件至今没有原生方案。
所以,目标不是“零依赖”,而是**“每个依赖都有存在的理由”**。把那些浏览器已经做得很好的功能交还给平台,把精力聚焦在真正需要库的复杂场景上——这才是少发JavaScript的真正意义。
下次升级依赖时,不妨把“这个库还在做浏览器做不了的事吗?”加入你的检查清单。你会发现,现代浏览器的能力边界,比你想象的要宽得多。