深入了解 npm!前面章节我们已经学习了 Node 和包管理器,甚至安装了 Node 和 npm 并熟悉了 Node 版本管理器 (nvm)。本 npm 初学者指南的下一部分将介绍您可能最关心的内容:安装 npm 包。
我们可以使用 npm install
命令(或简写为 npm i
)以及要添加到项目的包名称来安装我们的第一个包。例如,Sass 的 Node 包简称为“sass”,这意味着我们可以像这样将其添加到项目中(请确保您首先在一个为这个小项目创建的新文件夹中):
npm install sass
就是这样!输入此命令后,npm 将立即开始工作:
幕后发生的情况是,npm 尝试在 npm 包注册表中查找名为 sass 的包。如果找到该包(确实会找到),npm 会将其安装到项目中自动生成的 node_modules
文件夹(稍后会详细介绍)中(位于项目根文件夹中),包括该包运行所需的一切。(这就是为什么您看到 npm 添加了 16 个包并审核了总共 17 个 npm 包,而不是仅 Sass 包本身——它也有依赖项!)
运行安装命令后,您可能会注意到,您在项目文件夹中没有看到名为“sass”的任何内容,这与您可能预期的不同。然而,奇怪的是,我们确实在项目文件夹中看到了三个新项目:两个名为 package.json
和 package-lock.json
的 JSON 文件,以及一个全新的 node_modules
文件夹。
这些是什么?我们要求 npm 安装 Sass,而不是所有这些东西。这不是 Sass 的一部分……对吧?是的,这是正确的,但是为什么在项目文件夹中生成这些新项目有一个很好的解释。让我们看看刚刚发生了什么。
安装(或卸载或更新)包时,npm 会执行以下四件事中的大部分甚至全部:
package.json
文件;package-lock.json
文件(称为“锁文件”);node_modules
文件夹内);以及让我们逐一进行介绍。
这两个 JSON 文件协同工作,以确保准确记录项目中的所有依赖项(以及所有它们的依赖项,以及所有它们的依赖项的依赖项,依此类推)。两者之间的区别有点技术性,但简单来说:锁文件是项目依赖项树的深入、精确的快照,而 package.json
是一个高级概述,它还可以包含其他内容。您安装的主要包可能列在 package.json
中,但 package-lock.json
是跟踪整个依赖项树的位置。
锁文件也不应该手动更新;只能由 npm 更新。因此,请务必避免将锁文件与 package.json
文件混淆。
当您与他人共享或协作处理项目时,npm 通过这两个文件知道项目的来源以及项目中安装的内容。由于这些信息,它可以精确地在任何其他人的机器上复制该环境。这两个文件都应该提交到您的 Git 仓库,并作为项目的依赖项蓝图。这样,当您的团队中的另一位开发人员克隆仓库并运行 npm install
命令时,npm 确切地知道要安装哪些包,从而使您和您的同事保持同步。
如果您打开 package.json
,您不会看到太多内容,但值得一看一下,看看发生了什么:
{ "dependencies": { "sass": "^1.43.4" } }
您可能不会看到确切的版本号(因为自撰写本文以来该包已更新),但您应该在 JSON dependencies
对象内看到 sass。数字本身(在本例中为 1.43.4)指示已安装的 Sass 的特定版本。
作为简短但重要的旁注:版本号开头的脱字符 (^) 允许 npm 安装对包的次要更新。换句话说,它告诉 npm 已安装的 Sass 包必须至少为 1.43.4 版本,但可以是任何更高的 1.x.x 版本,只要它仍在 2.0.0 以下即可。npm 通常在安装包时选择最新的稳定版本,但添加此内容是为了允许进行非破坏性更新。这部分称为“语义版本控制”,它本身就是一个博文主题,但并非 npm 独有。
总之,这就是这两个 JSON 文件。接下来让我们讨论 node_modules
文件夹。
node_modules
是所有实际包代码所在的位置;这是已安装的 Node 包以及使它们运行的所有内容的实际安装位置。如果您现在在按照说明操作时打开该文件夹,您会找到一个 sass 文件夹,但也会找到其他几个文件夹。
出现其他文件夹的原因是,安装包时,它可能需要其他包才能正常运行(Sass 显然需要)。因此,npm 会自动完成查找和安装所有这些依赖项的工作。正如您可能猜到的那样,这些依赖项也可能拥有其他自己的依赖项,因此该过程会重复进行,依此类推,直到我们完成对依赖项树到其最远分支的爬取,并且我们所需的一切都已安装(或者直到我们遇到某种错误,尽管希望不会)。
因此,项目通常会有数百个甚至更多的 node_modules
子文件夹,这些文件夹在磁盘空间方面会迅速累积。node_modules
通常会变得非常庞大。
如果您想知道如何将像 node_modules
这样的大型文件夹提交到项目的存储库,请注意:与 JSON 文件不同,node_modules
文件夹不应提交到 Git,甚至不应共享。事实上,几乎每个 .gitignore
文件(告诉 Git 在跟踪文件时应跳过哪些文件的文件)的示例都包含 node_modules
,以确保 Git 从不接触或跟踪它。
那么,您的团队中的其他人如何获得这些包呢?他们从命令行运行 npm install
(或简写为 npm i
)以直接从源下载依赖项。这样,无需将大量数据提交到或从原始仓库中提取。
这个庞大的依赖项网络及其远亲依赖项可能会导致这种情况:某种提供有用服务的实用程序库可能会被许多其他包采用,而这些包又会被许多其他包使用,直到最终原始代码最终悄无声息地安装在很大一部分站点和应用程序上。
在安装一个包的过程中,您实际上可能会让很多其他东西进入,这听起来可能很奇怪(如果不是非常可怕的话)。这感觉就像邀请一位新朋友参加您的家庭聚会,然后这位朋友带着 20 位不速之客出现。但这并没有看起来那么奇怪或可怕,原因如下:
当然,在可以安装和执行任意代码的任何环境中,谨慎程度都是一个好主意。请不要误解我的意思。如果我说坏人从未成功利用过此系统,我会撒谎。但是要知道,有很多流程可以防止事情出错。如有疑问,请坚持使用最流行的包,这样您就没事了。
另请注意,npm 会为您运行自动安全审核,这将我们带到本节的最后一点。
当我们之前安装 sass 时,我们在终端完成时看到了以下消息:
<code>found 0 vulnerabilities</code>
但是,您可能会看到一些警告——就像我下面的旧项目一样。我决定启动它并在它至少闲置了几年后运行 npm install
(npm i
)。让我们看看它的表现如何:
npm audit 会指出具有已知漏洞的包,该审核会在您安装包时自动运行。如果您看到这样的消息,请不要太担心;许多漏洞,尤其是在“中等”类别中的漏洞,带来的实际风险非常低,并且可能仅与非常具体的情况相关。(例如,可能只有包中的一个方法在以特定方式使用时才会使其变得脆弱。)
尽管如此,最好还是解决我们所能解决的问题,这就是 npm audit fix
命令的作用。在末尾添加 fix
会告诉 npm 继续并更新具有某种已知漏洞的任何包的新的次要版本。“次要版本”部分很重要;次要版本不应包含重大更改,而应仅包含更新。这意味着应该安全地以这种方式运行更新,而不会出现破坏项目风险。
如果将包的版本号提高一个次要版本号不起作用,您可以将 --force
标志添加到原始命令中:
npm audit fix --force
但是,这是一个危险的操作。授予 npm “使用强制”权限意味着它现在可以安装主要版本更新以解决漏洞——这意味着它可能会进行重大更改或引入不兼容性。除非存在 npm audit fix
无法解决的关键漏洞,并且您愿意并且能够在之后花费大量时间进行故障排除(如有必要),否则我不建议这样做。
关于此主题的最后一点说明:有时您可以通过删除 node_modules
并重新运行 npm install
来修复 npm 项目中的一些意外问题。这是 npm 的“反复开关”方法,我自己也做过很多次。
既然我们已经彻底探索了 npm 幕后工作原理的兔子洞,那么让我们回到实际操作中来,好吗?
← 第 6 章 第 8 章 →
以上是如何安装NPM软件包的详细内容。更多信息请关注PHP中文网其他相关文章!