如果你对 npm、yarn 全局安装路径存疑,很混乱分不清,那么这篇文章应该能帮到你。本文以 macOS 为例,不同操作系统可能略有差异。
若无特殊说明,下文安装依赖均指「全局安装」。
一、Node 路径
其实在安装完 Node 之后,便有类似提示:
This package has installed:
- Node.js v16.15.1 to
/usr/local/bin/node
- npm v8.11.0 to
/usr/local/bin/npm
Make sure that
/usr/local/bin
is in your$PATH
.
可以得知 Node 和 NPM 的默认安装路径是 /usr/local/bin
。如果 /usr/local/bin
路径并不存在于环境变量 PATH
中,需在配置文件中写入。比如:
$ echo 'export PATH=$PATH:/usr/local/bin' >> ~/.zshrc
$ source ~/.zshrc
具体配置文件是 ~/.bash_profile
还是 ~/.zshrc
,取决于你当前使用哪一种 Shell 解析器。
使用 which
命令可查看「可执行文件」的路径,比如:
$ which node npm
/usr/local/bin/node
/usr/local/bin/npm
其中 /usr/local/bin
目录下的可执行文件多是软链接,并非文件真正所在路径。
说明一下,本文将以这种方式安装的 Node 称为系统版本的 Node,用于区别使用 nvm 安装的 Node。
二、npm 路径
从 npm Docs 官方文档中,对「全局安装」如何存放文件都有比较清晰的描述(详看),翻译过来就是:
- 依赖包将会下载至
{prefix}/lib/node_modules
目录下。- 依赖包的可执行文件被软链接至
{prefix}/bin
目录。
其中 prefix
是 npm 的一个配置项(详见),它的默认值与 Node 的安装位置有关。在 Unix/Linux/Mac 操作系统中,通常是 /usr/local
。在 Windows 操作系统上通常是 %AppData%\npm
。其中「可执行文件」是指 package.json
中 bin
字段的配置项。
使用 npm config
命令可对 prefix
配置进行操作:
# 查看
$ npm config get prefix
/usr/local
# 设置/更新
$ npm config set prefix <value>
# 移除
$ npm config delete prefix
也可在配置文件 ~/.npmrc
直接进行修改(详见 )。
若你在使用 nvm 来管理 Node 版本,不建议主动配置
prefix
。如果它存在的话应将其移除,否则可能会导致无法「合理地」安装依赖包到相应目录,具体原因下文会介绍。
因此,
- 依赖包存放于
/usr/local/lib/node_modules
目录。- 依赖包可执行文件将被软链接至
/usr/local/bin
目录。
可通过以下命令查看:
$ npm root -g
/usr/local/lib/node_modules
$ npm bin -g
/usr/local/bin
可通过 npm ls
命令查看全局安装的依赖包,个人更喜欢使用其别名 npm list
,原因是它跟 yarn list
一致。
$ npm list -g
/usr/local/lib
├── corepack@0.10.0
├── jest@28.1.1
├── npm@8.3.1
└── yarn@1.22.10
其打印结果为树状形式,可配合 --depth=n
参数使用以查看包的依赖信息,其中 n
表示树状深度。上面的 npm list -g
相当于 npm list -g --depth=0
。
更多请看 npm Docs。
三、yarn 相关路径
本文涉及的 yarn 均指 v1 版本。
插个话,在 v2 版本有着较大的差异,比如在 v2 版本将 yarn global
移除,其替代者是 yarn dlx
,更多请看,这里不展开赘述了。
yarn 全局安装路径与 npm 不同,默认情况下:
- 依赖包存放于
~/.config/yarn/global/node_modules
目录。- 依赖包可执行文件将被软链接至
/usr/local/bin
目录,
可通过以下命令查看:
$ yarn global dir
/Users/frankie/.config/yarn/global
$ yarn global bin
/usr/local/bin
若要修改以上配置,可通过 yarn config
命令处理:
# 修改依赖包安装路径
$ yarn config set global-folder <value>
# 修改依赖包可执行文件软链接路径
$ yarn config set prefix <value>
需要注意的是,修改全局安装路径的配置 key
是 global-folder
,可执行文件的 key
为 prefix
。别跟 npm 混淆了。
也可以在配置文件 ~/.yarnrc
直接修改:
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
registry "https://registry.npmmirror.com/"
lastUpdateCheck 1656144727204
需要注意的是,其中 npm 配置文件使用的是 ini-formatted 格式,也就是 key=value
形式,而 yarn 则是 key "value"
形式。
三、使用 nvm
我们知道 npm(Node Package Manager)是 Node 包管理工具,而 nvm(Node Version Manager)则是 Node 版本管理工具。它可以通过命令行快速安装、使用不同版本的 Node。
假设有多个项目使用了不同版本的 Node,或者需要在不同版本的 Node 下测试我们开发的 npm 包,那么使用 nvm 将会很高效。其安装不展开细说,请看官方文档。
第一节已经介绍了,使用「传统」的方法安装其路径如下:
- Node 被安装到
/usr/local/bin/node
;- npm 被安装到
/usr/local/bin/npm
;- npm 全局依赖包默认存放于
/usr/local/lib/node_modules
目录。
但如果使用 nvm 来管理 Node,这些都将会发生变化。当使用官方指引来安装 nvm,相关内容将会默认存放至 ~/.nvm
目录。
当使用 nvm install
来安装 Node,比如:
$ nvm install 16.14.0
它将会存放于 ~/.nvm/versions/node/v16.14.0
目录下。
切换 system Node 与 nvm Node,只要通过以下方式即可:
# 使用系统版本
$ nvm use system
# 使用 nvm 的 Node 版本,还有更多写法,请看:https://github.com/nvm-sh/nvm#usage
$ nvm use 16.14.0
我们观察一下 prefix
的变化就知道其安装路径了:
$ nvm use system
Now using system version of node: v16.14.0 (npm v7.24.2)
$ npm config get prefix
/usr/local
$ npm bin -g
/usr/local/bin
$ which node
/usr/local/bin/node
$ nvm use 16.14.0
Now using node v16.14.0 (npm v8.3.1)
$ npm config get prefix
/Users/frankie/.nvm/versions/node/v16.14.0
$ npm bin -g
/Users/frankie/.nvm/versions/node/v16.14.0/bin
$ which node
/Users/frankie/.nvm/versions/node/v16.14.0/bin/node
因此,在使用 nvm 管理的情况下:
- 全局依赖包将会安装至
~/.nvm/versions/node/vX.X.X/lib/node_modules
目录。- 依赖包可执行文件将被软链接至
~/.nvm/versions/node/vX.X.X/bin
目录。
前面提到过,prefix
的默认位置与 Node 的安装路径有关。比如,在 Unix/Linux/Mac 操作系统中,prefix
通常是 Node 安装路径的上一级,也就是 ~/.nvm/versions/node/vX.X.X
目录。因此,当我们在切换 Node 版本中,它总能正确地安装到 /usr/local/lib/node_modules
或 ~/.nvm/versions/node/vX.X.X/lib/node_modules/
目录。
更多请看 npm Docs。
但是,如果在 ~/.npmrc
中配置了 prefix
,无论你如何切换 Node 版本,它总是被安装至所配置的路径下。
$ npm config set prefix "~/.npm-packages"
$ npm i -g jest
$ tree ~/.npm-packages -L 3
/Users/frankie/.npm-packages
├── bin
│ └── jest -> ../lib/node_modules/jest/bin/jest.js
└── lib
└── node_modules
└── jest
这样就违背了用 nvm 的初心,自定义 prefix
配置与 nvm 不兼容。nvm 在其官方文档中用指出(详见):
If you have an
~/.npmrc
file, make sure it does not contain anyprefix
settings (which is not compatible withnvm
)
如果你此刻用着 nvm,同时没有意识到这个问题,建议立刻去检查并将其移除。
四、总结
目前,我同时使用着 nvm、npm、yarn(v1)三个工具,那么平常是这样管理它们的:
- 一概不主动修改 npm、yarn 默认安装路径,采用默认即可;
- npm 配置中一概不设置
prefix
,以避免 npm 全局依赖包被安装至「不正确」的路径下;- 与 Node 版本有关的全局依赖包,统一用 npm 进行安装,比如 Taro CLI 等;
- 与 Node 版本无关的全局依赖包,统一用 yarn 进行安装。
基于这种原则下,全局安装的依赖包将有这些路径:
/usr/local/lib/node_modules
~/.config/yarn/global/node_modules
~/.nvm/versions/node/vX.X.X/lib/node_modules
使用以下命令,可查看全局依赖包所在路径:
npm root -g
yarn global dir
使用以下命令,可查看已安装的全局依赖包:
npm list -g
yarn global list
到此,本文结束。以上希望可以帮你厘清个中混淆之处。
The end.