前端工程化1——npm insatall背后的工作原理

我们想让前端代码跑动起来,要么开发环境运行或者打包后运行到服务器,都要经过nodejs相关的操作。而nodejs的包管理工具npm是这些命令的管理中心,而npm install是npm的一个核心的命令,是项目相关依赖安装的一个命令。

我们先用一个表格看看npm install 的大致过程:

总结 详细
解析 package.json 文件 当你在项目目录下运行 npm install 时,npm 首先会读取项目根目录下的 package.json 文件。这个文件定义了项目的元数据,包括项目名称、版本、依赖项等。
创建或更新 node_modules 目录‌ npm install 命令会在项目根目录下创建一个 node_modules 目录(如果之前不存在的话),或者更新这个目录中的内容。这个目录用于存放所有安装的 npm 包。
解析依赖树 npm 会解析 package.json 文件中的 dependencies 和 devDependencies(开发依赖)字段,构建出项目的依赖树。这个依赖树包括了直接依赖以及所有间接依赖。
‌下载和安装包 根据解析出的依赖树,npm 会从 npm 仓库(通常是 https://registry.npmjs.org/)下载相应的包。对于每个包,npm 会检查本地缓存(通常位于 ~/.npm),如果缓存中有对应的包版本,则直接使用缓存中的版本,否则会下载最新版本。
安装钩子执行 在安装完所有依赖后,npm 会执行每个包的 postinstall 脚本(如果有的话)。这些脚本通常用于执行额外的安装步骤,比如编译 C++ 扩展等。
生成 package-lock.json 文件 为了提高可重复性和安全性,npm 会生成或更新 package-lock.json 文件。这个文件记录了安装时确切的包版本号,确保团队成员使用相同版本的依赖项。
完成安装‌ 所有依赖安装完毕后,npm install 命令结束。此时,你的项目可以使用这些依赖包进行开发或运行。

其实上述是一个没有缓存的install过程。其实,我们npm install可以用下列图一探究竟的:

这是横放的图:

1、npm install 执行之后,首先,检查并获取 npm 配置

2、检查项目中是否有 package-lock.json 文件

若有: 检查 package-lock.json 和 package.json 中声明的依赖是否一致:一致就直接使用package-lock.json 中的信息,从缓存或网络资源中加载依赖;不一致,则依据npm的版本进行处理

若无:则根据 package.json 递归构建依赖树,按照构建好的依赖树下载完整的依赖资源,在下载时就会检查是否存在相关资源缓存:存在缓存,就会将缓存内容解压到node_modules 中;不存在缓存,就从npm远程仓库下载包,并会检验包的完整性,随后添加到缓存,解压到node_modules 中生成package-lock.json。

3、最后生成 package-lock.json

安装依赖时,使用的算法是广度优先遍历,在遍历依赖树时,npm会首先处理项目根目录下的依赖,然后逐层处理每个依赖包的依赖,直到所有依赖都被处理完毕。在处理每个依赖时,npm会检查该依赖的版本号是否符合依赖树中其他依赖的版本要求,如果不符合,则会尝试安装适合的版本。

这是某人的npmrc配置:

cpp 复制代码
registry=http://registry.npmjs.org/
# 定义npm的registry,即npm的包下载源
 
proxy=http://proxy.example.com:8080/
# 定义npm的代理服务器,用于访问网络
 
https-proxy=http://proxy.example.com:8080/
# 定义npm的https代理服务器,用于访问网络
 
strict-ssl=true
# 是否在SSL证书验证错误时退出
 
cafile=/path/to/cafile.pem
# 定义自定义CA证书文件的路径
 
user-agent=npm/{npm-version} node/{node-version} {platform}
# 自定义请求头中的User-Agent
 
save=true
# 安装包时是否自动保存到package.json的dependencies中
 
save-dev=true
# 安装包时是否自动保存到package.json的devDependencies中
 
save-exact=true
# 安装包时是否精确保存版本号
 
engine-strict=true
# 是否在安装时检查依赖的node和npm版本是否符合要求
 
scripts-prepend-node-path=true
# 是否在运行脚本时自动将node的路径添加到PATH环境变量中

package-lock.json 的作用

该文件是用来锁定版本记录依赖树的详细信息用的。
version: 包版本这个包当前安装在 node_modules 中的版本
resolved: 包具体的安装来源,通常是npm,也有是私有源
integrity: 包 hash 值,来判断安装的依赖包是否被改动过、是否已失效源
requires: 对应子依赖的依赖,与子依赖的 package.json 中 dependencies的依赖项相同
dependencies: 存储安装在子依赖 node_modules 中的依赖包。

我们打开package.lock.json文件看看内容:

package-lock.json 帮我们做了缓存,他会通过name + version + integrity信息生成一个唯一的key,这个key能找到对应的index-v5 下的缓存记录,也就是npm cache 文件夹下的。

如果发现有缓存记录,就会找到tar包的hash值,然后将对应的二进制文件解压到node_modules。

node_modules 中模块目录结构

npm3.x之前是嵌套结构,那时候如果我们的项目中依赖了公共库 A 和公共库 B,同时公共库 A 也依赖了公共库 B,那公共库 B 会被多次安装 结构如图

node_modules 的结构和 package.json 结构一一对应,层级结构明显,并且保证了每次安装目录结构都是相同的。但是一个项目中引用的模块非常多,嵌套层级很深这时候就出现:在不同层级的依赖中,可能引用了同一个模块,这样这个模块就存在多个地方。显然不符合编码简洁的思路。

扁平结构

为了解决以上问题,npm3版本进行了改造。把嵌套结构改为扁平结构: 安装模块时,不管其是直接依赖还是子依赖的依赖,优先将其安装在 node_modules 根目录。 还是上面的依赖结构,我们在执行 npm install 后将得到下面的目录结构

寻找模块的依赖的方式就成了如下的流程:

  1. 在当前模块路径下搜索
  2. 在当前模块 node_modules 路径下搜素
  3. 在上级模块的 node_modules 路径下搜索
  4. 直到搜索到全局路径中的 node_modules

我们项目中安装依赖的时候需要注意:

◆ 应对node_modules庞大性

面对node_modules的庞大性,我们需要了解扁平化是npm安装的常态,但版本冲突可能导致嵌套现象。为了查看包的实际位置和版本,我们可以使用npm lspackage_name>命令,或者借助工具如disk-usage来分析存储占用。

◆ 解决安装缓慢问题

推荐使用国内镜像源,通过修改.npmrc文件中的registry设置,确保网络连接的稳定性。在持续集成(CI)环境中,使用npm ci命令通常能获得更快的安装速度。

◆ 保持环境一致性

提交package-lock.json文件,以确保团队成员在相同环境下使用一致的依赖版本。推荐使用npm ci进行确定性安装,确保每次部署都能获得一致的结果。

◆ 手动处理依赖冲突

当需要进行手动干预时,可以通过使用npm updatepackage>命令或在package.json中添加overrides(npm v8+)或resolutions(Yarn字段)来强制指定版本,但需谨慎操作。

参考文章:

https://juejin.cn/post/7156041372678488072

https://blog.csdn.net/weixin_40629244/article/details/139582982

https://baijiahao.baidu.com/s?id=1840449964886370148\&wfr=spider\&for=pc

相关推荐
崔庆才丨静觅5 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60616 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了6 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅6 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅6 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅7 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment7 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅7 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊7 小时前
jwt介绍
前端
爱敲代码的小鱼7 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax