Node包管理有关的工具以及命令和环境变量

406 阅读11分钟

# 前言

一直以来使用npm来安装node包依赖,但对命令行、环境变量和各自包管理工具都模棱两可,现在梳理一下。

安装 node.js 会自带 npm 这个默认的包管理器。

安装完后执行一下查看版本:

node -v
npm -v

命令和环境

首先,我们可以查看一下node的目录
where node

打开目录我们能看到有 node.exenpm 等文件,这就是你在命令行执行时执行的文件程序;

其中npm 有 .cmd后缀的,还可能有 .ps1后缀 的,分别是 cmd命令 和 powerShell命令对应的执行文件;

你还可能看到npx相关的执行文件,这个是node@5.2版本之后添加的命令,后面再具体描述。

下面我们介绍一下window的环境变量

环境变量分别有系统环境变量(所有计算机用户共享)、用户环境变量、临时环境变量(只在当前会话有效);

  • 右键点击“计算机”或“此电脑”,选择“属性”;
  • 点击“高级系统设置”;
  • 在“高级”选项卡下,点击“环境变量”按钮。
  • 在这里你可以添加、编辑和删除系统和用户环境变量。

其中有一个环境变量叫 Path,双击打开是一个可编辑的列表,每一条记录都是一个目录,其中类似 %USERPROFILE% 是一个环境变量的引用;

你会发现node存放的目录就在这里,只有配置在这里,node、npm等才能成为全局命令;

接下来我们使用npm来安装依赖包

新建一个目录当中项目,并用cmd 打开它,我们安装一下 yarn

npm i yarn

安装完后发现项目下多了 package.json文件 和 node_modules文件夹,打开node_modules会有 yarn文件夹 和 .bin文件夹;

打开.bin 文件夹发现有yarn文件和yarn.cmd文件,此时我们尝试执行 yarn -v 发现报错: 'yarn' 不是内部或外部命令,也不是可运行的程序或批处理文件 ,因为我们并没有把这个 node_modules/.bin 添加到环境变量Path里面,故此不是全局命令。

那怎样才能够使用yarn呢,有以下几种方案:

  • 执行npm i yarn -g 全局安装,此时会在node.exe所在文件夹这个全局目录中进行安装yarn包,这个目录下会多出yarn和yarn.cmd 等执行文件,node_modules里面也会多出yarn的文件夹;

  • 在项目的cmd下执行node_modules\.bin\yarn.cmd -v 进行指定文件执行

  • 在项目的 package.json 文件中的 scripts 部分添加一个脚本:

"scripts": { "yarn": "yarn" }

然后运行

npm run yarn -v
  • 直接使用npx执行
npx yarn -v
这里讲下npx是什么:

npx 是 npm 5.2.0 及更高版本中附带的一个工具,它的目的是帮助你执行项目中安装的 npm 包中的可执行文件。npx 的执行规则如下:

  1. 本地查找: 首先,npx 会在当前目录或父级目录的 node_modules/.bin 目录下查找可执行文件。这样可以确保你能够在项目中执行安装在本地的 npm 包。
  2. 全局查找: 如果在本地没有找到相应的可执行文件,npx 会查找全局安装的 npm 包。
  3. 下载执行: 如果在本地和全局都没有找到,npx 会下载相应的 npm 包(如果不存在的话)到临时目录(定期清理)并执行其中的可执行文件。这就意味着你可以在不全局安装工具的情况下运行它们。
  4. 指定版本: 通过 npx package@version 的形式,你可以执行特定版本的包,而不需要全局安装该版本。
  5. 执行 npm 脚本: 除了执行可执行文件,npx 还可以用于执行项目中的 npm 脚本,例如 npx npm run scriptName

OK,此时我们就可以使用yarn来执行了

yarn对比npm的优势是什么

yarnnpm 都是用于管理 JavaScript 包的工具,相比有以下优势:

  1. 性能(安装方式):yarn 在安装包时通常更快,因为它会并行下载多个包,而 npm 从 v7 开始支持并行安装,但默认情况下仍然是串行安装

  2. 离线模式(缓存机制):yarn 使用离线模式,可以在没有网络连接的情况下安装依赖,即使之前安装过的包,也可以通过缓存直接获取,不需要重新下载;而npm 也有缓存机制,但是它的离线模式相对较弱。

  3. 可靠性(版本解析): yarn 使用精确的版本解析,可以确保在不同的环境中安装相同的依赖;而npm 的版本解析相对宽松一些,这可能导致在不同环境中安装不同的依赖版本。

  4. 易于理解的 CLI: yarn 的命令行接口相对直观,提供了更一致和易于理解的命令;npm 从 v7 开始 改进了 CLI,使其更加现代化和易用。

全局安装的话建议更改以下目录:

yarn global bin //查看全局bin目录路径
yarn config set prefix "自定义的全局bin目录路径" //设置yarn全局bin目录的路径,用npm安装的话其实可以无需理会

yarn global dir //查看全局global目录路径,就是全局node_modules所在目录
yarn config set global-folder "自定义的全局项目路径" //建议设置到非C盘

yarn cache dir //查看全局缓存路径
yarn config set cache-folder "自定义的全局cache目录路径" //建议设置到非C盘
关于镜像源

镜像源(Mirror Source) 是指在互联网上存在的一份主机的拷贝,通常用于提供更快速的访问速度。在软件开发中,特别是在包管理工具中,镜像源的作用是为了加速软件包的下载和安装过程。

cnpm 是淘宝提供的 npm 镜像源,使用 cnpm 可以加速包的下载,尤其对于在国内访问 npm 官方源较慢的情况。

你可以使用以下命令来安装 cnpm

npm install -g cnpm --registry=https://registry.npmmirror.com

然后,你就可以使用 cnpm 代替 npm 来安装和管理包,例如:

cnpm install package-name

可以使用以下命令查看镜像源地址:

特别说明:

  • 旧的淘宝镜像源 registry.npm.taobao.org 已经过期,请切换
  • 不推荐cnpm,因为cnpm不会根据 package-lock.json 进行初始化安装,安装的包也不会更新package-lock.json,容易导致项目不稳定,还是推荐 nrm 进行镜像切换
使用nrm切换镜像源

nrm(npm registry manager)的主要功能是管理和切换 npm registry(镜像源),可以使用nrm test 命令可以测试当前所有 registry 的访问速度,再切换到速度快的镜像源。

npm install -g nrm
nrm test
nrm use 镜像名称(例如taobao)

当你使用 nrm use 切换源时,nrm 实际上是通过调用 npm config set registry 命令来更改 npm 的 registry 配置

如果你平常习惯使用yarn来执行命令,则可以使用 yrm,用法和nrm一样,但yrm会 同时更新npm和yarn的镜像源

关于node多版本管理

当开发多个项目,但项目对应的node版本不一样时,我们可以使用nvm切换node版本。

  • 点击 nvm下载地址,一般选择 最新版本 (latest标志)中 nvm-setup.zip 进行下载安装就行。
  • 安装完,环境变量会默认都给你添加,你可以前往环境变量查看多了 NVM_HOMENVM_SYMLINK 这两个变量,并添加至Path变量列表中了。
  • 需要切换安装node版本的镜像源的,打开安装目录下的 settings.txt 文件,node_mirror和npm_mirrord对应下载的镜像源地址,例如最新的淘宝镜像源地址:
node_mirror: https://npmmirror.com/mirrors/node/
npm_mirror: https://npmmirror.com/mirrors/npm/

nvm常见命令:

nvm list // 查看安装的所有node的版本
nvm list available // 查看当前可安装的版本,其中 LTS 表示长期稳定版本
nvm install xx.xx.xx  // 安装xx.xx.xx版本的node,如果想安装最新版本则执行 nvm install latest
nvm use xx.xx.xx // 使用(切换到)xx.xx.xx版本的node
nvm uninstall xx.xx.xx  // 卸载xx.xx.xx版本的node
nvm arch // 显示node是运行在32位还是64位。
nvm on // 开启node.js版本管理
nvm off // 关闭node.js版本管理
nvm proxy [url] // 设置下载代理。不加可选参数url,显示当前代理。将url设置为none则移除代理。
nvm node_mirror [url] // 设置node镜像。默认是https://nodejs.org/dist/。如果不写url,则使用默认url。设置后可至安装目录settings.txt文件查看,也可直接在该文件操作。
nvm npm_mirror [url] // 设置npm镜像。https://github.com/npm/cli/archive/。如果不写url,则使用默认url。设置后可至安装目录settings.txt文件查看,也可直接在该文件操作。
nvm root [path] // 设置存储不同版本node的目录。如果未设置,默认使用当前目录。

nvm是通过符号链接实现的,例如当你使用nvm install安装完某个版本A后,%NVM_HOME% 目录下会有A版本的文件夹;当你使用nvm use切换到A版本时,%NVM_SYMLINK% 这个符号链接会指向A版本的文件夹下;

%NVM_SYMLINK% 又因为添加到了环境变量的 Path变量 中,因此当你使用npm的时候调用的就是A版本文件夹下的npm文件,从而实现node的版本切换。

pnpm

pnpm( performant npm )指的是高性能的 npm

npm i pnpm -g

设置一下全局目录

pnpm config set global-bin-dir "pnpm全局bin目录" //如果用npm安装的,指向node目录路径,此路径下会存在可执行的pnpm二进制文件
pnpm config set cache-dir "pnpm的缓存路径" //建议设置到非C盘
pnpm config set state-dir "pnpm的安装状态信息路径" //尽量和缓存路径同一文件夹下
pnpm config set store-dir "pnpm的全局仓库路径" //一般会自动设置为磁盘的根目录的.pnpm-store文件夹,建议设置为非C盘的磁盘根目录下
pnpm config set global-dir "pnpm全局安装路径" //node_modules所在的目录,所有全局包都在这里

pnpm 通过硬链接(hark link)、符号链接(symbolic link,又叫软链接) + 全局存储(store)结合的依赖管理方式完全实现了依赖树结构的包管理方式

  • 全局存储(store)集中管理依赖:pnpm 会在磁盘根目录下生成一个 .pnpm-store 文件夹,安装的依赖文件在这里都会缓存一份;
  • 装包时命中缓存中有的依赖,会被硬链接到项目的 node_module 中的 .pnpm 文件夹 中;减少了 copy 的大量 IO 操作;
  • 同一版本的依赖共用一个磁盘空间;不同版本依赖,只额外存储 diff 内容;
  • 项目中的node_modules/.pnmp通过<package-name>@<version>来实现相同模块不同版本之间隔离和复用,由于它只会根据项目中的依赖生成,所以不会hoist(提升)到根目录;
  • 项目node_modules中已有依赖重复安装时,会被 软链接 到指定目录下

20240125-182555.jpg

使用npm会出现的问题:

  • npm没有全局存储store,不同项目下的依赖文件会重复创建;同一项目中,相同依赖不同版本的直接构建新的文件,不是只创建diff文件,会造成冗余的磁盘占用,拖慢装包速度;
  • 由于存在 hoist 机制,下载依赖会优先放置在node_modules这个根目录,如果有版本冲突才放置在子目录(一般只对比直接依赖和开发依赖的版本),会造成幽灵依赖;

幽灵依赖:某个包没有在 package.json 被依赖,但是用户却能够引用到这个包;

而pnpm的实现方式完美的解决了上面的问题

下面科普下:

硬链接: 操作系统有自己对应的文件系统,而文件系统会给磁盘中每个文件分配一个编号(inode index);我们设置B硬链接A,则A与B的inode index是相同的,A与B都直接指向同一个磁盘文件。

符号链接(软链接): 类似于window的快捷方式;设置C软链接A,A与C的inode index是不相同的,其中C存放了A的路径名,可以根据这个找到A;假如A被删除,C依然存在,但指向一个无效路径;优点是可以跨域不同操作系统。

点击 硬链接与软链接 可以进一步了解

题外话

了解完上面的,可以去了解一些前端架构的解决方案了,如: