掘力计划第25期 npm 包管理性能优化实践

9月23日,"掘力计划"第25期沙龙活动在北京举行。本期活动的主题为"性能专场",旨在探讨前端性能优化的实践方案。活动邀请到字节跳动 Node.js Infra 团队的研发工程师李世民进行题为《npm 包管理性能优化实践》的技术分享。

李世民讲师有 7 年工作经验,2019 年加入字节跳动,在 Node.js Infra 组负责 Node.js 包管理方向,参与基础库、框架插件等研发。本次分享首先介绍了 npm的组成,以及 npm CLI 和 npm registry 之间的交互过程。然后重点介绍了npm 性能优化的五点实践:压缩 metadata 加速下载,利用缓存避免重复请求,优化存储结构减少查询,使用全球 CDN 提高下载速度,应用搜索引擎实现模糊搜索。最后表示虽然各种 npm 客户端都在优化性能,但 npm 官方更关注安全性和生态系统的可持续发展。

视频回放:juejin.cn/live/jpower...

npm 的组成与概念

npm 由三个关键部分组成,分别是 npm CLI、npm registry 和 npmjs.org 网站。

首先介绍 npm CLI。它是一个命令行界面工具,开发者可以通过它来安装和管理 node.js 中的代码包。通过 npm CLI,我们可以进行包的搜索、安装、升级、删除等操作。npm CLI 会与 npm registry 进行交互,来找到需要的包的元数据信息和代码包,然后安装到项目中。

然后是 npm registry。它是 npm 包的元数据和代码包存储在服务器端的地方。当 npm CLI 要安装一个包时,会从 npm registry 获取该包的信息,然后下载代码包。npm registry 存储了所有的公共 npm 包的版本信息和代码包,可以看作是一个巨大的 npm 包数据仓库。

最后是 npmjs.org 网站。这是 npm 的官方网站,开发者可以在上面搜索 npm 包,查看包的信息如版本、下载量、描述等。网站上也提供了包 README 文档的查看和搜索功能。npmjs 网站为开发者提供了一个可视化地浏览 npm 包的入口。其中, P、Q、M 三个指标分别代表了 Populartity(流行度)、Quality(质量)、Maintenance(维护)的分数,影响这些指标的相关因素如下所示

  • P(Populartity):总下载量、下载量增长趋势、Repo star 数、订阅人数等
  • Q(Quality):文档(README)、LICENSE、CHANGELOG、测试脚本、是否有漏洞、品牌特征(homepage、badge)等
  • M(Maintenance):issue 中 open/close 占比、github 代码提交频率、release 版本频率等

以上三个部分共同组成了 npm 的整个生态系统,开发者通过 npm CLI 使用 npm registry 来发现、获取和管理代码包, npmjs 网站提供友好的图形界面来辅助搜索和发现包。它们互为补充,共同推动了 npm 在 nodejs 社区中的流行。

npm CLI 与 registry 的交互

当我们执行 npm install 命令安装一个包时,npm CLI 和 registry 之间会进行复杂的交互。首先,CLI 会向 registry 的 metadata API 发起请求,获取目标包的完整 package.json。npm registry 收到请求后,会从数据库中查找该包的所有版本信息,并返回给 CLI。CLI 收到信息后,会根据指定的版本号或者 tag,解析出需要安装的具体版本号。

解析完成后,CLI 会再次向 registry 发起请求,通过 tarball API 下载对应的代码包。registry 这次会直接从对象存储中取出代码包文件,并传输给 CLI。CLI 收到代码包后,会进行验证,以确保内容完整正确。验证通过就会解压缩代码包,并将其保存到当前项目的 node_modules 目录中。

当我们执行 npm publish 发布一个包时,也会进行类似的交互。这时 CLI 会读取当前项目的代码文件,生成一个 tarball 包,并使用base64编码上传到 registry。registry 收到发布请求后,会解码保存代码包,并生成对应的package.json 元数据信息。发布完成后,registry 会返回一个成功的响应给 CLI。

这样,CLI 和 registry 之间的交互就完成了整个 npm 包的安装和发布流程。registry 扮演着存储和传输代码的角色,而 CLI 负责解析版本、验证完整性和管理本地文件。两者密切协作,共同完成了 npm 生态系统中的核心功能。

npm 性能优化的实践

npm 作为 node.js 生态系统中的包管理工具,其性能直接影响到前端工程师的开发效率。通过在 npm registry 层进行优化,能显著提升 npm CLI 与服务端交互的性能。

首先是压缩 metadata。npm 包的元数据中包含大量信息,直接返回完整的 metadata 文件会导致文件体积太大,下载时间过长。演讲者采用了压缩 metadata 文件的方法,保留版本、依赖等必要信息,移除描述、文档等文本字段。压缩后文件体积可降低90%以上。npm registry 支持在请求头中添加参数,返回压缩后的 metadata,这可大幅减少下载时间,提升获取包信息的速度。

然后是启用缓存。npm CLI 会在请求包信息时带上 if-none-match 头,registry 可检查缓存是否命中,直接返回 304 状态码。未命中时返回新的 metadata,CLI 将更新本地缓存。此举跳过了重复网络请求与数据处理,使得重复安装相同版本包的速度可达毫秒级。

存储结构的优化也可带来显著效果。避免每次查询数据库,直接通过可预测的 URL 从对象存储获取包文件,可减少查询和序列化的时间。此外,在发布包时就写入完整信息,避免重复序列化,可大幅减少处理时间。

最后,通过全球节点分发解决了网络延迟问题。根据地区解析 DNS 到就近节点,极大地减少了跨区域的网络损耗。此举使各地区的用户均可获得快速响应。

包管理器生态

除了 npm,社区中还存在众多包管理器,如 pnpm、yarn、cnpm 等。这些包管理器都在优化各自的性能,以期为开发者带来更快的安装速度。 pnpm 通过并发下载、缓存依赖图等方式提升性能。yarn 在工作区管理、缓存方面进行了优化。cnpm 由蚂蚁金服团队开发,用于解决国内网络环境下的安装问题。

这些包管理器优化性能的同时,也更加关注安全性。比如 npm 推动了两步验证,要求前 500 活跃开发者启用;不再支持 PGP 签名,而是直接对发布的代码进行签名。npm 还引入了依赖审查,可以提示依赖变更的风险。

除安全外,还有溯源的能力被引入。npm 允许提交代码时自动生成证书,记录代码从提交到发布的全链路。这为发现问题的根源提供了帮助。

fastify 作者 Matteo 在一次对 Bun1.0 发布的看法上表示,性能优化并不是 npm 的优先关注点,因为 Node.js 基金会没有太多预算,只有极小的团队在维护 npm registry。投资 npm 的企业更关注安全而不是速度,想从中获利也很困难。如果仅仅为了速度而优化,那些云服务提供商反而会不高兴,因为占用更少资源意味着没人会买更多云服务器。这说明在开源社区中,性能提升并不是唯一的目标。同时要考虑生态系统的安全可靠以及长期健康发展,这需要开发者、企业和基金会的共同努力。

总体来说,性能优化不是社区的唯一关注点。包管理生态要平衡性能、安全性、可靠性多个方面。过度追求速度可能导致依赖问题,从长远看不利于生态系统的健康发展。

总结

李世民讲师对 npm 包管理的性能优化进行了深入浅出的讲解,让我们对 npm 生态有了更全面和透彻的理解。npm 作为 node生态系统的核心,其性能直接影响着开发效率。通过压缩元数据、缓存优化、存储优化等方式可以显著提升 npm 的速度。但是我们也要注意,提升速度不是 npm 优化的唯一目标,更重要的是保证包的安全性和生态系统的可持续发展。npm 社区一直在努力推进这些方面的工作。我们也希望通过今天的分享,能够让大家对 npm 包管理有更深入的理解,在以后的开发中能够更好地使用 npm,构建健康的 node 应用。

掘力计划

掘力计划由稀土掘金技术社区发起,致力于打造一个高品质的技术分享和交流的系列品牌。聚集国内外顶尖的技术专家、开发者和实践者,通过线下沙龙、闭门会、公开课等多种形式分享最前沿的技术动态。

相关推荐
M_emory_17 分钟前
解决 git clone 出现:Failed to connect to 127.0.0.1 port 1080: Connection refused 错误
前端·vue.js·git
Ciito21 分钟前
vue项目使用eslint+prettier管理项目格式化
前端·javascript·vue.js
成都被卷死的程序员1 小时前
响应式网页设计--html
前端·html
mon_star°1 小时前
将答题成绩排行榜数据通过前端生成excel的方式实现导出下载功能
前端·excel
Zrf21913184551 小时前
前端笔试中oj算法题的解法模版
前端·readline·oj算法
明月与玄武2 小时前
关于性能测试:数据库的 SQL 性能优化实战
数据库·sql·性能优化
文军的烹饪实验室2 小时前
ValueError: Circular reference detected
开发语言·前端·javascript
Martin -Tang3 小时前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发3 小时前
解锁微前端的优秀库
前端
王解4 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js