npm 文件夹
npm 使用的文件夹结构
描述
npm 将各种东西放在你的计算机上。这就是它的工作。
这份文件会告诉你它放在什么地方.
tl;dr
- 安装(默认):将东西放入
./node_modules
当前包根目录。 - 安装(带
-g
):将东西放在 /usr/local 或安装节点的任何地方。 - 您要使用它,请在本地安装
require()
它。 - 要在命令行上运行它,请全局安装它。
- 两者都需要,则在两个地方都安装它,或者使用
npm link
. 前缀配置 的prefix
配置默认为在安装节点的位置。在大多数系统上,这是/usr/local
. 在 Windows 上,它是%AppData%\npm
. 在 Unix 系统上,它是一个级别,因为节点通常安装在{prefix}/bin/node
而不是{prefix}/node.exe
.
global
标志设置,NPM安装的东西到这个前缀。如果未设置,则使用当前包的根目录,如果不在包中,则使用当前工作目录。
节点模块
包被丢弃到node_modules
文件夹下prefix
。在本地安装时,这意味着您可以 require("packagename")
加载其主模块,也 require("packagename/lib/path/to/sub/module")
可以加载其他模块。
Unix 系统上的全局安装转到{prefix}/lib/node_modules
. Windows 上的全局安装转到{prefix}/node_modules
(即,没有 lib
文件夹。)
作用域包的安装方式相同,不同之处在于它们被组合在相关node_modules
文件夹的子文件夹中,该文件夹的名称由 @ 符号组成,例如npm install @myorg/package
将包放在{prefix}/node_modules/@myorg/package
. 有关scope
更多详细信息,请参阅 。
如果你想要require()
一个包,然后在本地安装它。
可执行文件
在全局模式下,可执行文件{prefix}/bin
在 Unix上链接到,或{prefix}
在 Windows 上直接链接到。确保路径在您的终端PATH
环境中以运行它们。
在本地模式下,可执行文件被链接, ./node_modules/.bin
以便它们可用于通过 npm 运行的脚本。(例如,当您运行时,测试运行器将位于路径中npm test
。)
手册页
在全局模式下,手册页链接到{prefix}/share/man
.
在本地模式下,不安装手册页。
手册页未安装在 Windows 系统上。
缓存
见npm cache
。缓存文件存储在~/.npm
Posix 或 %AppData%/npm-cache
Windows 上。
这是由cache
配置参数控制的。
临时文件
临时文件默认存储在tmp
配置指定的文件夹中 ,默认为 TMPDIR、TMP 或 TEMP 环境变量,或者/tmp
在 Unix 和c:\windows\temp
Windows 上。
每次运行程序时,都会在此根目录下为临时文件指定一个唯一文件夹,并在成功退出后删除。
更多信息
在本地安装时,npm 首先尝试寻找合适的 prefix
文件夹。这样npm install foo@1.2.3
即使您碰巧cd
进入了其他文件夹,它也会安装到您的软件包的合理根目录中。
从 $PWD 开始,npm 将沿着文件夹树检查包含package.json
文件或node_modules
文件夹的文件夹。如果找到这样的东西,那么为了运行 npm 命令,它被视为有效的“当前目录”。(此行为的灵感来自并类似于在工作目录中运行 git 命令时 git 的 .git-folder 查找逻辑。)
如果未找到包根目录,则使用当前文件夹。
当你运行时npm install foo@1.2.3
,包被加载到缓存中,然后解压到./node_modules/foo
. 然后,任何 foo 的依赖项都类似地解压到 ./node_modules/foo/node_modules/...
.
任何 bin 文件都被符号链接到./node_modules/.bin/
,以便在必要时可以通过 npm 脚本找到它们。
全球安装
如果global
配置设置为 true,则 npm 将“全局”安装软件包。
对于全局安装,软件包的安装方式大致相同,但使用上述文件夹。
循环、冲突和文件夹简约
循环使用节点的模块系统的属性处理,它会在目录中查找node_modules
文件夹。因此,在每个阶段,如果一个包已经安装在祖先node_modules
文件夹中,那么它不会安装在当前位置。
考虑上面的情况,其中foo -> bar -> baz
。想象一下,除此之外,如果 baz 依赖于 bar,那么您将拥有: foo -> bar -> baz -> bar -> baz ...
. 但是,由于文件夹结构是:foo/node_modules/bar/node_modules/baz
,因此无需将 bar 的另一个副本放入.../baz/node_modules
,因为当它调用 require("bar") 时,它将获得安装在 foo/node_modules/bar
.
仅当在多个嵌套node_modules
文件夹中安装完全相同的版本时才使用此快捷方式。a/node_modules/b/node_modules/a
如果两个“a”包是不同的版本,仍然有可能。但是,如果不多次重复完全相同的包,将始终防止无限倒退。
另一种优化可以通过在本地化的“目标”文件夹下的最高级别安装依赖项来进行。
例子
考虑这个依赖图:
+-- blerg@1.2.5
+-- bar@1.2.3
| +-- blerg@1.x (latest=1.3.7)
| +-- baz@2.x
| | `-- quux@3.x
| | `-- bar@1.2.3 (cycle)
| `-- asdf@*
`-- baz@1.2.3
`-- quux@3.x
`-- bar
在这种情况下,我们可能会期望这样的文件夹结构:
foo
+-- node_modules
+-- blerg ( 1.2.5 ) < --- [ A ]
+-- bar ( 1.2.3 ) < --- [ B ]
| ` -- node_modules
| +-- baz ( 2.0.2 ) < --- [ C ]
| | ` -- node_modules
| | ` -- quux ( 3.2.0 )
| ` -- asdf ( 2.3.4 )
` -- baz ( 1.2.3 ) < --- [ D ]
` -- node_modules
`--quux ( 3.2.0 ) < --- [ E ]
由于 foo 直接依赖于bar@1.2.3
and baz@1.2.3
,所以它们安装在 foo 的node_modules
文件夹中。
尽管 bleger 的最新副本是 1.3.7,但 foo 对版本 1.2.5 有特定的依赖性。因此,它安装在[A] 处。由于 blerg 的父安装满足 bar 对 的依赖blerg@1.x
,因此它不会在[B]下安装另一个副本。
Bar [B]还依赖于 baz 和 asdf,因此它们安装在 bar 的node_modules
文件夹中。因为它依赖于baz@2.x
,它不能重复使用baz@1.2.3
父node_modules
文件夹中安装的[D] ,而必须安装自己的副本[C] 。
在 bar 下方,baz -> quux -> bar
依赖项创建了一个循环。但是,因为 bar 已经在 quux 的祖先[B] 中,所以它不会将 bar 的另一个副本解压缩到该文件夹中。
在foo -> baz
[D]下方,quux 的[E]文件夹树是空的,因为它对 bar 的依赖由安装在[B]的父文件夹副本满足。
有关安装位置的图形细分,请使用npm ls
.
出版
发布后,npm 将在node_modules
文件夹中查找。如果bundledDependencies
数组中没有任何项目,则它们将不会包含在包 tarball 中。
这允许包维护者在本地安装他们的所有依赖项(和开发依赖项),但只重新发布那些在其他地方找不到的项目。有关package.json
更多信息,请参阅。foo