当前位置: 首页 > news >正文

前端工程反思笔记:从 CDN 依赖包被删导致个站打不开到数年前因11 行代码导致上千项目崩溃谈谈npm黑洞- 统计下你的项目有多少个依赖吧!

最近,我的个站由于用到了免费CDN(国外的因为访问问题,改成了国内的bootcdn)上的一个vuejs包,当时是为了加速,但是没想到它这些年变了,一些包路径变了/没有进行缓存,导致整个站点无法访问。我开始反思前端工程中的依赖管理问题,尤其是某些优化,我之所以使用公开的库,是为了增加命中率,让用户打开网站的速度快一些,而不是重新从我的服务器下载个一模一样的文件。在搜索相关问题的过程中,我发现早在几年前,NPM 上的 “left_pad” 包被作者删除时,整个前端社区的项目纷纷遭遇了崩溃,印象到了数千项目的部署。

今天,呼吁大家反思一下:我们的前端项目设计的过于复杂(超过实际的复杂)、依赖是不是太多了!

先发起一个呼吁:前端使用第三方依赖时,优选下0依赖的包。发布新包时,不妨造造轮子

NPM 依赖陷阱:循环、深层的依赖

下图清晰的说明了npm黑洞问题:
在这里插入图片描述
例如我随便打开了一个package.lock文件,就有5000行,这还只是一个只有一个页面的vue3+vite项目的单页应用,依赖也仅仅是包含:

 "dependencies": {"@ant-design/icons-vue": "^7.0.1","ant-design-vue": "4.x","dayjs": "^1.11.11","pinia": "^2.1.7","rxjs": "^7.8.1","vue": "^3.4.29","vue-i18n": "^9.13.1","vue-router": "^4.4.0"},"devDependencies": {"@intlify/unplugin-vue-i18n": "^4.0.0","@types/node": "^20.14.9","@vitejs/plugin-vue": "^5.0.5","@vitest/ui": "^1.6.0","@vue/test-utils": "^2.4.6","autoprefixer": "^10.4.19","jsdom": "^24.1.0","postcss": "^8.4.39","sass": "^1.77.6","sass-loader": "^14.2.1","tailwindcss": "^3.4.4","typescript": "^5.2.2","unplugin-vue-components": "^0.27.2","vite": "^5.3.1","vitest": "^1.6.0","vue-tsc": "^2.0.21"}

但是,实际安装的包有数百个,很多都是二次依赖、三次依赖。

11行代码影响上万个项目的发布事件

前端开发中,NPM 依赖的数量往往让人瞠目结舌。一个简单的前端项目可能引入数百个包,而每个包可能又有成百上千的二次依赖。这种依赖链的复杂性使得我们难以全面掌控项目中的所有外部模块,也增加了潜在的脆弱性。一个上游包的更新或删除,可能直接影响到数千个甚至上万个下游项目,正如 “left_pad” 事件所展示的那样。

“left_pad” 是一个只有 11 行代码的小工具,其代码如下:

module.exports = leftpad;
function leftpad (str, len, ch) {str = String(str);var i = -1;if (!ch && ch !== 0) ch = ' ';len = len - str.length;while (++i < len) {str = ch + str;}return str;
}

但它被删除后,立即导致了大量依赖它的项目无法正常工作。这样一个小工具的失效引发的连锁反应,不仅是对整个前端社区的警醒,更是让我们意识到我们对这些工具的过度依赖。

这个事件中,一位开发者因为对管理方式不满而选择删除了自己在 NPM 上发布的所有包,包括 “left_pad”。由于许多流行的前端库直接或间接依赖于这个小工具,导致数千个项目在构建过程中失败,甚至一些大型企业的服务也因此受到影响。这次事件让开发者意识到,尽管一个工具看起来非常小,但它在整个生态中的影响可能非常大。这样的事情让我们不禁感叹,前端生态系统在享受模块化开发带来便利的同时,也存在着巨大的隐患。

详细的可搜索 left pad事件 或者 查看 或许无法访问的维基百科

所有者当时的发言是:

这个库是我创建的,我有权删除

开源库的使用问题:所有权与维护压力

除了依赖的复杂性,开源库的所有权和维护问题也成为了前端社区不可忽视的隐患。许多清理类、工具类的小型开源库被大量使用,但这些库的所有权仍然掌握在个人开发者手中,这意味着开发者有完全的权利删除或停止维护这些库。例如 “left_pad” 的创建者认为这个库是他创建的,因此他有权利删除它。这种所有权问题让整个社区的稳定性变得不可预测。

此外,许多开源库虽然被大公司广泛使用,但它们的维护者可能只是一位个人开发者,并没有从中获得足够的收入或支持。这就导致了两个潜在的问题:

  1. 开发者维护压力大:个人开发者在面对成千上万用户的需求时,往往难以承担更新和维护的压力。他们没有足够的时间和资源去修复问题或引入新功能,这可能导致库长期得不到维护。这种状况不仅让依赖这些库的开发者处于被动地位,也让整个项目的稳定性面临风险。

  2. 维护者缺乏激励:许多开源项目的开发者并没有从他们的劳动中获得经济回报,当他们觉得自己的付出得不到应有的认可时,可能会选择放弃维护。这就让那些依赖这些库的项目处于危险之中,尤其是在需要快速响应的情况下。开源项目需要开发者的热情和动力,但如果缺乏有效的激励机制,这种热情往往难以持久。

更糟糕的是,这些开源库常常是整个前端生态中不可或缺的一部分。大公司将它们纳入自己的项目,而不一定会对其进行额外的测试或二次开发,导致对这些库的依赖一旦出现问题,就会对整个系统造成严重的影响。维护者在个人时间、资源和激励不足的情况下,很难对社区的庞大需求做出及时的响应,进一步加剧了这种不可控性。

NPM 的问题:依赖地狱与不可控性

NPM 生态虽然给开发者带来了极大的便利,但也伴随着一些深层次的问题:

  1. 过度依赖第三方包:很多时候,开发者会为了图方便而直接使用现成的库,即使它的功能实现非常简单。这不仅增加了项目的复杂性,还可能引入额外的安全隐患。一个简单的字符串补全工具,可能成为数千个项目的依赖,这种现象不仅增加了项目的重量,还使得项目的稳定性更加脆弱。

  2. 不可控的依赖链:NPM 中每个包都有可能依赖多个其他包,这些依赖又会再继续依赖下去,形成错综复杂的依赖链。这些依赖链中的任意一个包的更新、弃用或删除,都会影响整个项目的稳定性。这就像是一个庞大的多米诺骨牌,一旦有一个节点出现问题,整条依赖链都可能会受到冲击。开发者往往难以掌握这些复杂的依赖链,导致问题出现时束手无策。

  3. 版本管理的混乱:虽然语义化版本控制是前端社区的一个标准,但许多开发者在发布版本时并没有严格遵守这一规范,导致版本间的不兼容性成为常态。加之 “^” 或 “~” 号的使用,使得我们的依赖更新不再受自己控制。版本的不一致性往往会导致无法预料的问题,尤其是在某些库自动升级时,可能会引入新的 bug 或与其他依赖产生冲突。

如何避免依赖陷阱:减少依赖、重视模块设计

要避免依赖陷阱,我们需要对依赖进行更严格的管理,并重视模块的设计与代码的可控性:

  1. 减少不必要的依赖:在引入第三方库之前,应该首先考虑该功能是否可以自己实现。如果功能简单,自己编写代码通常比引入一个依赖更为稳妥。这样不仅可以减少对外部模块的依赖,还可以更好地掌控代码的质量和安全性。

  2. 管理依赖版本:尽量锁定依赖的具体版本,避免使用模糊版本号,以减少潜在的不兼容问题。同时可以利用工具(如 npm-shrinkwrap 或 yarn.lock)来管理依赖树,确保依赖的版本一致性和可控性。这种方式可以有效降低因为上游版本变动而带来的风险。

  3. 重视模块设计:在进行模块设计时,尽可能地降低模块的耦合度,保持代码的简单和纯净。对于公共工具类代码,可以尝试将其设计为独立的模块,减少对外部依赖的需求。模块设计时的高内聚低耦合可以大大提高代码的可维护性和复用性,减少外部依赖带来的不稳定因素。

  4. 支持开源社区:对于那些在开源项目中付出大量精力的个人开发者,企业和社区应当给予更多的支持,不论是通过捐赠、赞助,还是雇佣他们来维护这些关键模块。这样可以确保这些库得到持续的维护与更新,降低项目因依赖中断而崩溃的风险。支持开源开发者不仅是对他们劳动的认可,也是对整个开源生态的维护和保护。

  5. 建立更好的依赖审查机制:公司和团队应当对项目中的依赖进行定期审查,尤其是对那些长期没有更新或维护的库要格外关注。可以考虑用自动化工具来扫描依赖的安全漏洞和更新状态,以便及时采取措施来替换不再可靠的依赖。

总结

前端项目中的依赖管理问题需要引起更多开发者的重视。通过 “left_pad” 事件以及最近个站因 CDN 包被删除而崩溃的案例,我们应该意识到依赖管理中的风险与隐患。减少不必要的依赖、重视模块设计、合理管理版本,是提升前端项目稳定性的重要手段。同时,我们也应当关注开源库的所有权和维护问题,支持那些为社区作出贡献的开发者,让开源生态变得更加健康和可持续。

发布包、使用第三方包的时候,好好管理下依赖,不要一股脑的安装,最好选择0运行依赖的开源库。


http://www.mrgr.cn/news/56079.html

相关文章:

  • 10月24日程序员节!GameViewer远程体验副屏串流和远程办公功能
  • 打包使用pythn编写的maya插件,使用pyeal打包
  • 京准电钟:NTP网络校时服务器应用计算机大数据
  • 音频分割:长语音音频 分割为 短语音音频 - python 实现
  • Vim使用与进阶
  • WSL2 构建Ubuntu系统-轻量级AI运行环境
  • UI Manifold 概览
  • 【IEEE独立出版 | 厦门大学主办】第四届人工智能、机器人和通信国际会议(ICAIRC 2024)
  • 安卓开发例程之计算器项目
  • springboot 同时上传文件和JSON对象
  • RHCE--nginx实现多IP访问多网站
  • 一文搞定栈与队列
  • [AOSPXRef]看安卓源码搜索使用解释
  • 设置虚拟机与windows间的共享文件夹
  • 每日一题|1497. 检查数组对是否可以被 k 整除|两数之和的模运算
  • 在分类内用最大最小值筛选(每个分类找出一个)
  • 振弦式传感器在高边坡监测中发挥哪些优势?
  • 文心一言 VS 讯飞星火 VS chatgpt (375)-- 算法导论24.4 7题
  • WPS电信定制版 v12.8.2.18205 自带 VBA\无广告
  • 【Linux】进程优先级
  • 大模型LLM算法工程师技术面试指南
  • 如果你不幸成为家里第一个GIS专业的学生
  • Active Directory(活动目录)密码审核工具
  • Macos m系列芯片环境下安装python3以及mysqlclient流程以及遇到的一系列问题
  • 进程控制 -- 详解
  • 13.5 Linux_网络编程_域名解析