梳理 node、npm、yarn 相关路径

配图源自 Freepik

如果你对 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.jsonbin 字段的配置项。

使用 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>

需要注意的是,修改全局安装路径的配置 keyglobal-folder,可执行文件的 keyprefix。别跟 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 any prefix settings (which is not compatible with nvm)

如果你此刻用着 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.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容