news 2026/10/15 6:42:35

Node.js 16 安装指南:Windows、macOS、Linux 全覆盖与踩坑实录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Node.js 16 安装指南:Windows、macOS、Linux 全覆盖与踩坑实录

最近好几个同行都在问同一个问题:那些还跑在 Node.js 16 上的老项目,到底怎么干净利落地装好这个版本?官方明明已经宣布停止维护,可手里一堆存量代码就是用 16 写的,跑在 CI 上、跑在客户的服务器上,没人敢轻易动。我前前后后在各种机器上装过不下二十次 Node.js v16,Windows、macOS、Linux 都踩过坑,今天干脆把整个安装过程、版本管理、常见坑位一次性盘清楚,省得大家再走弯路。

先说清楚一件事:Node.js 16 在 2023 年 9 月已经结束了生命周期,官方不再打安全补丁。如果你是在评估新项目,我建议直接上最新的 LTS 版本。但如果你的场景是“老项目必须锁死 16”,或者某个供应商 SDK 只兼容 16,那么本文讲的所有安装方法、版本切换方案、踩坑经验,你都能直接用上。

1. 为什么还要装 Node.js 16:不是怀旧,是现实约束

1.1 Node.js 16 的生命周期回顾

Node.js 16 发布于 2021 年 4 月,同年 10 月进入 LTS(长期支持)阶段,一直维护到 2023 年 9 月。这个版本在国内外面向企业级应用的生态里存量非常大,很多基于它开发的电商中台、后端服务、工具链项目,至今还在生产环境里稳定运行。最后一个补丁版本是 16.20.2,如果你必须用 16,这个版本号就是终点,不用再等更新了。

我见过不少团队因为“官方停止维护”就想立刻升级,结果一升级依赖树就崩,尤其是那些依赖原生模块的老项目,node-gyp 一编译就是一堆兼容性报错。所以现实中“继续用 16”不是一个技术上的最优解,而是一个成本和风险控制上的务实选择。

1.2 选型判断:哪些场景必须锁定 Node 16

根据我的经验,下面几类场景基本上躲不开 Node 16:

  • 老项目锁定了 npm 依赖版本,依赖树里某些包在 18 以上会有 deprecation 警告,甚至直接跑不起来。
  • 项目里用了 C++ 原生模块,编译好的二进制文件只在 Node 16 的 ABI 版本下可用。Node 的 ABI 版本在 16 和 18 之间不兼容,重新编译又面临工具链升级,成本很高。
  • CI/CD 流水线里的镜像和缓存全部基于 Node 16 构建,临时改基础镜像会影响发布流程稳定性。
  • 外接的第三方 SDK 或内部私有包明确写明 engines 字段只能支持 Node 16。

这个判断很重要,因为安装本身不难,难的是搞清楚“你究竟需不需要装 16”。我给自己的一个原则是:能升级的项目尽快升级,不能升级的项目锁定版本并做好安全隔离,比如只在内网环境运行,不暴露公网端口。

1.3 先看清当前环境再动手

安装之前先把系统现状摸清楚,这条建议价值千金。我在帮别人排查问题时,发现很多人装了半天装不上,其实是因为机器里已经存在另一个 Node 版本,导致 PATH 优先级混乱。

建议先执行以下检查:

node -v which node npm -v

如果机器里已经有 Node 在跑,先记下当前版本、安装路径和 npm 全局包列表。后面无论是覆盖安装还是用版本管理工具并行管理,都要基于这个现状来操作,不能一上来就蛮干。

2. Windows 环境下安装 Node.js 16:两种方式按需选

2.1 官方安装包方式的完整步骤

Windows 装 Node.js 最简单的方式是直接下载安装包。官方历史版本列表里可以找到 16.20.2 的安装包,文件名类似node-v16.20.2-x64.msi,下载后双击运行。

安装过程中有几步需要特别注意:

第一,安装路径不要带空格,也不要用中文目录,我见过太多因为路径带空格导致 node-gyp 编译失败的案例。建议直接安装到C:\nodejs\这种简单路径。

第二,安装向导里有个“Add to PATH”选项,必须勾上。很多人安装完成后在 cmd 里敲node -v提示找不到命令,就是因为这一步没勾。

第三,如果系统里已经装了其他版本,MSI 安装包会直接覆盖或报冲突。稳妥的做法是先卸载旧版本,再装 16,或者干脆用后面的 nvm-windows 方式。

安装完成后,重新开一个 cmd 窗口,执行:

node -v npm -v

输出v16.20.2和对应的 npm 版本(Node 16 自带 npm 8,如果你看到 npm 6,说明 PATH 里优先命中了其他版本,需要检查环境变量)。

2.2 安装过程中那些容易忽略的选项

MSI 安装包除了 PATH 之外,还有几个组件选项值得关注。

  • npm 包管理器:默认会装上,不要取消。
  • 在线文档和附加工具(比如在 Windows 上调试用的一些工具链):如果磁盘压力大可以不装,对日常使用没影响。
  • “Download additional tools” 选项:它会给 Visual Studio Build Tools 和 Python,主要是为了编译原生模块用的。如果老项目里没有 node-gyp 依赖,可以跳过;如果有,建议后面单独装一套 Build Tools,而不是让安装器自动下载,因为自动下载在国内网络环境下经常卡住。

安装包方式的优点是省心,缺点是版本切换不灵活。如果机器上只跑一个 Node 16,这种方式完全没有问题。

2.3 用 nvm-windows 管理版本:更推荐的做法

如果你预感到将来还要切回 Node 18 或 20,那就在 Windows 上用nvm-windows吧。这是一个独立的工具,和 macOS/Linux 上的nvm不是同一个项目,但使用习惯上很接近。

安装 nvm-windows 的步骤:

  1. 先去官方仓库下载nvm-setup.zip或者直接下载最新 release 里的nvm-setup.exe运行。
  2. 安装路径同样不能有空格,建议C:\nvm。
  3. 安装完成之后,nvm 会自动把自己的路径加到 PATH 里,并且会创建一个软链接目录C:\Program Files\nodejs,这个目录就是一个指向当前激活版本的入口。

接下来用 nvm 安装 Node 16:

nvm install 16.20.2 nvm use 16.20.2 node -v

这里有个细节:nvm-windows 会把已安装的版本存放在 nvm 安装目录下的v16.20.2文件夹里,然后通过修改符号链接的方式把node.exe映射到C:\Program Files\nodejs。所以如果你发现某些 IDE 找不到 Node,检查 IDE 的 Node 路径是否指向C:\Program Files\nodejs,改成这个路径就能解决。

nvm-windows 还支持设置默认版本:

nvm alias default 16.20.2

这样每次新开终端都会自动使用 16,省得反复切换。

3. macOS 下安装 Node.js 16:pkg 和 nvm 的取舍

3.1 pkg 安装包方式

macOS 上最简单粗暴的方式同样是官方 pkg 安装包。下载node-v16.20.2.pkg,双击安装,一路下一步,装完打开终端敲node -v就能看到版本。这种方式会把 Node 安装到/usr/local/bin/目录下,并且自动配置 PATH。

pkg 方式的优点是完全不用动脑,缺点是卸载比较麻烦,而且版本切换没有任何余地。如果只是在一台临时机器上跑个脚本,用它够了。但是作为主力开发机,我不推荐这种方式,因为 macOS 上最容易出问题的就是全局目录权限,而 pkg 安装的 Node 在访问全局 npm 包目录时经常出现 permission denied。

3.2 用 nvm 安装并切换版本:主力开发机推荐方案

macOS 上我更推荐的方式是先用 Git 拉取 nvm 安装脚本,或者直接通过命令安装:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

安装脚本会在用户目录下创建.nvm目录,并往 shell 配置文件(.bashrc、.zshrc)里写入环境变量加载逻辑。安装完成之后,需要重新打开终端或者source ~/.zshrc才能生效。

然后安装 Node 16:

nvm install 16.20.2 nvm use 16.20.2

nvm 的机制是:所有版本都下载到~/.nvm/versions/node/v16.20.2/,然后通过修改 PATH 的方式把当前目录切到你指定的版本。它和 nvm-windows 的符号链接方案思路不同,但效果一样。

nvm 还允许你给某个项目目录写一个.nvmrc文件,文件内容就一行:16.20.2。然后进入目录执行nvm use,它会自动读取.nvmrc并激活对应版本。这个功能对维护多个项目非常实用,每个项目各自的 Node 版本互不干扰。

3.3 处理 macOS 安装时的常见问题

macOS 上有两个高频问题:

第一,curl安装 nvm 显示command not found: nvm。这通常是因为 nvm 安装脚本写入 zsh 配置时没有生效。解决办法是检查~/.zshrc里是否包含以下三行:

export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"

没有就手动加上,然后source ~/.zshrc。

第二,安装 Node 16 失败,提示Binary download failed。这大概率是网络问题,nvm 会从 Node 官方服务器下载编译好的二进制包,某些网络环境下下载不稳定。解决方法是设置 nvm 的镜像地址:

export NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node/

然后重新安装。这里要提醒一下,如果公司内部有网络管控,镜像地址以团队实际可用的为准,不要在博客里死记某一个地址。

4. Linux 环境下安装 Node.js 16:发行版思路别搞混

4.1 用包管理器安装:简单但版本可能不灵活

不同的 Linux 发行版对 Node.js 的默认版本策略差异很大。Debian 11 默认 Node 12,Ubuntu 20.04 默认 Node 10,Ubuntu 22.04 默认 Node 12,CentOS 7 的默认源里甚至没有 Node。直接apt install nodejs装出来的一般版本很旧,跟 16 差得远,根本不能满足需求。

所以我不推荐直接用系统默认源装 Node,除非你已经把发行版源里的版本搞清楚了,并且确定默认源里正好有 16。大多数情况下是没戏的。

Debian/Ubuntu 系统上,可以尝试使用第三方维护的 NodeSource 仓库。安装方式网上有很多资料,核心思路是先导入仓库的 GPG 密钥,然后把仓库地址写入/etc/apt/sources.list.d/,最后执行apt update和apt install nodejs。不过要提醒一句,第三方仓库的可用性和安全性需要自己评估,尤其是在企业内网环境里,能不能访问这个仓库本身就是个变数。

4.2 直接下载二进制包解压安装:最可控的方案

Linux 上我个人最推荐的方式是下载官方编译好的二进制 tar.xz 包,直接解压到指定目录,然后用软链接把命令暴露到 PATH 里。这种方式完全不依赖系统包管理器,也不会污染系统全局环境。

操作步骤:

wget https://nodejs.org/dist/v16.20.2/node-v16.20.2-linux-x64.tar.xz tar -xf node-v16.20.2-linux-x64.tar.xz mv node-v16.20.2-linux-x64 /opt/node16 ln -s /opt/node16/bin/node /usr/local/bin/node ln -s /opt/node16/bin/npm /usr/local/bin/npm

这样装完后,执行node -v就是v16.20.2。顺带提一句:如果服务器要跑服务,建议把 PATH 写入/etc/profile.d/node16.sh,内容很简单:

export PATH=/opt/node16/bin:$PATH

这样每次登录 shell 都会自动加载,不会出现重启后 node 命令找不到的情况。

不过软链接方案有个问题:npm 全局安装的包里面会有很多node_modules/.bin/下的可执行文件,这些文件的 shebang 通常写的是/usr/bin/env node,所以只要 node 在 PATH 里就能运行,没问题。但如果你用npm install -g安装的包带有原生二进制,比如某些 CLI 工具在安装时会编译或者绑定 Node ABI,那这种手动解压的方式同样会遇到依赖问题。解决方案很简单:安装前先把编译工具链装齐,比如build-essential或python。

4.3 Linux 上的 nvm 使用:和 macOS 基本一个套路

Linux 上同样可以装 nvm,安装命令和 macOS 一模一样,因为 nvm 本质上是 shell 脚本。安装完成后所有版本都在用户目录下,不需要 root 权限。这对服务器上多用户隔离的场景也比较友好,每个用户各管各的 Node 版本,互不干扰。

有个细节值得关注:在 Linux 服务器上,很多人习惯用 root 执行命令,导致 nvm 被装在 root 用户下,换个普通用户登录就找不到 nvm。我建议你在部署用户下安装,不要图省事用 root。Node 16 本身就停止维护了,跑在 root 下又叠加一层安全风险,不划算。

5. 安装完成后的验证与初始化:别急着 npm install

5.1 验证版本时要注意的细节

很多人验证安装就只敲一句node -v,这样不够。我习惯执行三条命令:

node -v npm -v which node

node -v看版本,npm -v看包管理器版本,which node看当前命中的 node 到底在哪。第三点特别重要,因为环境变量 PATH 里如果多个路径都有 node,你敲node -v未必是刚装的 16。which node能帮你立刻定位实际执行的文件路径。

补充一句:Node 16.20.2 自带的 npm 版本是 8.19.x,如果你装完发现 npm 版本显示 6.x,说明你的 PATH 里命中了某些自带 npm 的系统包,优先级把刚装的 npm 盖住了。排查方向是检查/usr/bin、/usr/local/bin、用户目录下的~/.nvm/versions/node/.../bin三个路径的排列顺序。

5.2 npm 的全局目录和缓存问题

Node 16 自带的 npm 8 在目录策略上有一个明显的侧重点:它更倾向于把全局包装在当前用户目录下,而不是系统级目录。很多从 npm 6 时代升级过来的老项目,会遇到全局包完全消失的“假象”。解决方案是重新npm install -g你需要的工具包,或者把全局目录改回原来的位置:

npm config set prefix /your/desired/global/path

这个配置写在~/.npmrc里,改之前建议先执行npm config ls看看当前都有哪些配置,避免误改。

另外,Linux 上如果之前用 apt 装过 Node,再手动装 16 后,npm 的缓存目录可能还指向旧路径,执行npm install时一直报错。遇到这种情况,直接清掉缓存:

npm cache clean --force

再重新安装依赖,基本能解决。

5.3 老项目的依赖检查

Node 16 自带 npm 8,而很多老项目是从 npm 6 时代传下来的,它们的package-lock.json文件格式可能相对旧。首次npm install时,npm 8 会自动升级 lockfile,这个过程通常无感,但如果项目里存在大量的 git 依赖或者私有仓库依赖,且认证方式比较老,npm 8 可能会拒绝非 HTTPS 的 git 协议地址。

如果你在这个环节报错,解决办法是检查package-lock.json里有没有git+ssh://或git://开头的依赖地址,把它们改成https://或者重新配置好 SSH key。别用那种“绕过校验”的歪招,老老实实修地址是正道。

还有一个非常经典的问题:Node 16 与 node-sass 的版本匹配。如果你的项目里还是 node-sass,而不是 sass(dart-sass),那 16 只能搭配 node-sass 6.x 以上。用 4.x 或 5.x 的话,install 阶段就会因为二进制下载失败而报错。换成 sass 是长期正解,临时方案则是锁定 node-sass 版本到匹配的版本。

6. 踩坑实录:Node 16 安装与使用中的高频问题

6.1 Windows 上 node 命令找不到

先说最常见的现象:安装完成后,新开的 cmd 里敲node -v提示不是内部或外部命令。

排查步骤:

  1. 检查系统环境变量里有没有C:\nodejs或你安装时指定的路径。
  2. 如果路径存在,检查这个目录里有没有node.exe。
  3. 如果路径不存在,手动添加系统环境变量 PATH,并把 node 所在目录加进去。

还有一个隐蔽原因:MSI 安装包默认给当前用户和所有用户两种选项,如果你只在当前用户下安装了,而 cmd 是以另一个用户身份打开的,就会出现 PATH 有配置但 node 找不到的情况。用“管理员身份打开 cmd”重跑一次安装包,选择安装到所有用户,就能解决。

6.2 macOS 上安装后 version 还是旧版本

一台 Mac 上如果既用过 Homebrew,又试过 nvm,极容易出现 node 版本混乱。最常见的是 Homebrew 的 node 在/usr/local/opt/node/bin,nvm 的版本在~/.nvm下,两个路径在 PATH 里互相抢。

处理方案是把 Homebrew 的 node 卸载掉,或者调整 PATH 顺序,确保 nvm 的 shim 路径排在前面。推荐先brew uninstall node,因为如果你要长期用 nvm 管理版本,留着 Homebrew 的 node 只会制造麻烦。

6.3 Linux 上升级后 npm 彻底失效

这种情况多发生在把系统自带的 node 卸载后,又手动解压 Node 16 的时候。系统的npm可能在/usr/bin/npm里,而新解压的 npm 在/opt/node16/bin/npm,两个文件指向完全不同的内部逻辑。强行卸载旧 npm 可能导致系统的某些包管理器脚本失效。

我的做法是:不强行卸载系统自带 npm,而是用软链接把/usr/bin/node和/usr/bin/npm指到新版路径。这样系统脚本调用时也能兼容,'升级'也相对平滑。

6.4 原生模块编译失败

Node 16 环境下,node-gyp 编译原生模块时对工具链有明确要求:

  • Windows 上需要 Visual Studio 2019 或更新版本,且安装 C++ 桌面开发工作负载。
  • Linux 上需要python3、make、g++。
  • macOS 上需要 Xcode Command Line Tools。

如果编译报错信息里出现gyp ERR! find Python,直接检查 Python 是否在 PATH 里。很多坑都是因为系统只有 Python 3,而老版本的 node-gyp 在找 Python 2。Node 16 自带的 npm 8 内嵌的 node-gyp 兼容性已经很好了,但项目如果单独锁定了 node-gyp 版本,建议升级到一个较新的 9.x 或 10.x 版本。

6.5 常见问题速查表

现象可能原因解决方向
node -v 不显示 16PATH 中其他版本优先级更高用 which node 定位,调整 PATH 顺序
npm install 卡在 idealTree缓存损坏或网络波动npm cache clean --force,重试
node-sass binding 报错node-sass 版本不匹配升级 node-sass 到 6.x+,或改用 sass
gyp ERR 编译失败缺少编译器或 Python按平台安装编译工具链
nvm 命令找不到nvm 未加载到 shell 配置手动添加 NVM_DIR 相关三行到 rc 文件
运行老脚本报 OpenSSL 错误Node 16 的 OpenSSL 1.1.1 已到生命周期评估升级项目或做网络隔离

6.6 一个补丁细节:16.20.2 是哪个版本

工作中有人会问,到底要装 16 的哪个小版本。我统一建议装16.20.2,因为这是官方发布的最后一个补丁版,包含 16 生命周期内所有修复。不要装 16.0.x 这种首发版,越早的版本问题越多。

7. 版本切换与长期维护的一些实操心得

7.1 团队统一版本比个人方便更重要

Node 16 安装本身不复杂,真正复杂的是让团队所有成员都用同一个版本。我在团队里推行.nvmrc+ nvm/nvm-windows 的组合方案,每个项目根目录放一个.nvmrc文件,内容写死 16.20.2。任何成员进入项目目录后,一行命令就切换到正确版本:

nvm use

CI 里也同步处理,构建镜像时先执行nvm install 16.20.2 && nvm use,再跑npm ci。这一步能避免大量“本地跑得好好的,构建机上就崩”的经典纠纷。

7.2 关于 EOL 之后该不该继续用的判断

说完安装和维护,必须补一句大实话:Node 16 已经停止维护,这是事实。我的建议不是让大家赶紧升,也不是让大家永远留在 16,而是分三步走:

第一步,先把团队所有项目的 Node 版本都统一管理起来,至少做到可复现。 第二步,盘点项目依赖里最顽固的阻塞项,通常就是原生模块,针对性升级或替换。 第三步,找低峰期做一次 16 到 18 或 20 的切换演练,不要等安全漏洞被迫上线才开始动。

7.3 几个能提升幸福感的小技巧

  • 全局安装n这个包来做快速切换,虽然它不如 nvm 管理得彻底,但胜在命令简洁:n 16.20.2就能切换版本。
  • Windows 用户如果嫌 nvm-windows 操作不够顺滑,可以试试用命令行脚本批量封装安装和切换逻辑。
  • Linux 服务器上,给 node 命令加个 shell 别名,比如在.bashrc里写alias node16='nvm use 16.20.2',日常操作会舒服很多。

最后分享一个我自己很受用的小习惯:每次装完 Node 16,我都会顺手写一个 Markdown 备忘录,记录这台机器的安装方式、Node 路径、npm 全局包的列表。半年后再来看这台机器,你绝对会感谢当初记录的那几行文字。毕竟 Node 16 这种已经进入维护尾声的版本,机器越多,坑越深,有条理地管理版本比临时抱佛脚重要得多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 6:42:28

PS5串流新方案AnyPS5:网关部署、延迟调优与踩坑实录

家里这台PS5入手快一年,我遇到的最尴尬时刻,不是游戏打不过去,而是想接着玩的时候,客厅电视被家里人占了。躺在床上用手机玩、出差在酒店打开笔记本接着刷任务——这些需求听起来不复杂,实现起来却是一堆坑。于是我自己…

作者头像 李华
网站建设 2026/10/15 6:41:49

深入理解Spring Bean:原理、装配与生命周期

1. 为什么Spring要在IoC容器里托管对象接触Spring的第一课,几乎都会从Bean开始。但很多人对Bean的理解停留在“Spring帮我创建了一个对象”这种表面层次。实际上,Bean机制解决的是整个项目在构建过程中对象创建与依赖协调的全局问题,理解它&a…

作者头像 李华
网站建设 2026/10/15 6:41:46

JDK 10新特性深度解析:var、AppCDS与G1并行Full GC的实战价值

如果在搜索引擎里输入“JDK 10 新特性”,你看到的讨论热度大概率会被旁边的JDK 9模块化、JDK 11 ZGC压下去。很多人甚至把JDK 10当成一个“过渡版本”,看了个版本号就翻页。我最早也是这么想的,直到做了一次老项目从JDK 8向新版本迁移&#x…

作者头像 李华
网站建设 2026/10/15 6:41:10

C/C++ void* 从入门到工程实践:原理、应用与避坑指南

做C/C这些年,要说哪个关键字最让人又爱又恨,我第一个提名void*。很多新手看到它就觉得玄乎,觉得就是个“万能兜底”,什么都敢往里塞,但真到了项目里,又不太敢用,怕出事。而老手恰恰相反&#xf…

作者头像 李华
网站建设 2026/10/15 6:41:04

从零搭建MySQL监控:Prometheus + Exporter + Grafana实战

1. 监控方案落地前,先聊聊我踩过的坑先说个真实经历。早几年在一家做SaaS的公司维护线上数据库,MySQL实例跑得好好的,某天下午客户开始零星报障,说页面打开慢、数据保存失败。我们几个人手忙脚乱查应用日志、查网关、查中间件&…

作者头像 李华
网站建设 2026/10/15 6:40:27

Java入门第4天:方法、数组与引用传递的踩坑复盘

今天是学习Java第4天。说实话,前三天我一直在“跟着感觉走”:第一天装环境、配置JDK、敲了几个Hello World的变体;第二天啃变量、数据类型和运算符,练到逻辑运算符时一度怀疑自己小学数学没学好;第三天学会了if、switc…

作者头像 李华