我平时最烦看到新手一上来就搜"Node.js看我的就行了!!!”这种标题,点进去全是废话连篇的安装教程。但今天我自己用这个标题来讲,不是标题党,而是想用一篇真正能少走弯路的文章,把Node.js是什么、怎么装、装完怎么跑通第一个项目、踩过哪些坑,一次说清楚。Node.js说白了就是一个让JavaScript在服务器上跑起来的运行时,它解决的问题很直接:让你用同一门语言写前端也写后端,而且靠事件驱动和非阻塞I/O,能在高并发场景下扛住大量请求。这篇文章适合完全没接触过Node.js的小白,也适合装了几次都没成功、被各种版本报错折磨的老手,看完可以直接照着操作。
1. Node.js到底是干什么的?
1.1 它不是一个语言,而是一个运行时
很多人第一次接触Node.js都会有个误解,以为它是新的编程语言。我第一次接触也这么想过,后来才搞清楚:Node.js不是语言,JavaScript才是语言,Node.js是让JavaScript在服务端运行的一个环境。以前JavaScript只能在浏览器里跑,浏览器提供window、document这些对象,JavaScript靠它们操作页面。Node.js把JavaScript从浏览器里解放出来,内置了文件系统、网络、进程等能力,你写const fs = require('fs')就能读写文件,写const http = require('http')就能起一个Web服务。
理解这个区别很关键。因为很多安装报错、运行报错,根源就在于你用浏览器的那套思路去理解Node.js。比如你在Node里直接敲document.getElementById,它肯定报错,因为Node环境里没有DOM。它给你的是一套服务端API,核心包括fs、http、path、os这些模块。把Node.js当成一个"用JavaScript写后端程序的工具箱"来看,很多概念就顺了。
1.2 用餐厅点菜来理解事件驱动和非阻塞I/O
Node.js最核心的卖点是事件驱动、非阻塞I/O。这句话背的人多,真懂的人少。我用餐厅点菜来打个比方。
传统服务器处理请求,像一个服务员从头到尾接待一位客人:客人说要鱼香肉丝,服务员就站在厨房等鱼香肉丝出锅,期间别的客人喊他他也不理。这就是阻塞I/O,一次只能服务一个请求,并发高的时候系统就卡死。
Node.js的做法不一样:服务员收到客人点单后,把菜单贴在厨房窗口,然后立刻去接待下一位客人。厨房做完菜,喊一声"鱼香肉丝好了",服务员再端过去。这就是事件驱动和非阻塞I/O。CPU不傻等磁盘、网络这些慢操作,而是先去处理别的事,等慢操作完成了,通过事件通知回来,再继续后面的逻辑。
不是所有场景都适合这种模型。计算密集型的任务,比如视频转码、大规模数据运算,如果都放在Node的主线程里跑,反而会阻塞事件循环,性能并不理想。Node适合的是I/O密集型场景:Web API、聊天服务、实时推送、代理服务、接口网关。这一点选型的时候要想清楚,别什么项目都上Node,工具没有绝对好坏,只有适不适合。
1.3 用它能做哪些事
- 写后端接口:配合Express、Koa、Fastify这些框架,开发RESTful API或者GraphQL服务。
- 前端工程化:Webpack、Vite、Rollup都是基于Node.js构建的,前端开发者的日常工具链离不开它。
- 命令行工具:用Node写脚本处理文件、批量重命名、定时任务,比Shell更易读、更跨平台。
- 桌面应用:Electron用Node.js做底层,VS Code就是这么出来的。
- 物联网和嵌入式:Node.js对串口、GPIO的支持让它在树莓派等设备上也很活跃。
知道这些场景之后,你就明白为什么Node.js的生态这么大了:它不是只能做一件事,而是能覆盖从前端工具到后端服务的整条链路。
2. 安装前必须想明白的三件事
2.1 LTS还是Current?别一上来就装最新版本
打开Node.js官网,你会看到两个下载按钮:一个写LTS,一个写Current。新手十有八九会手滑点Current,因为看上去版本号更大、更新。这里必须先说清楚:生产环境、日常学习,都首选LTS。
LTS全称Long Term Support,长期支持版本,偶数版本号一般是LTS线,比如20.x、22.x。这类版本会有长达数年的维护期,修bug、补安全漏洞都很稳。Current是最新功能版,奇数版本号居多,能第一时间体验新特性,但迭代快、坑多、第三方依赖未必兼容。我在实际项目里见过有人图新鲜装了Current版本,结果某个老依赖编译不过去,最后只能把Node降级。所以除非你要尝鲜,否则老老实实装LTS。
| 对比项 | LTS版本 | Current版本 |
|---|---|---|
| 稳定性 | 高,长期维护 | 较低,迭代快 |
| 版本号示例 | 20.x、22.x | 21.x、23.x、24.x等 |
| 适合场景 | 生产环境、学习、工具链 | 新特性尝鲜、生态开发者 |
| 第三方依赖兼容性 | 好 | 不一定跟得上 |
2.2 系统包管理器、官网包还是版本管理器?
安装Node.js的常见方式有三种:用操作系统自带包管理器装、去官网下载安装包、用nvm这类版本管理器装。很多人的痛苦来源于这三种方式混着用,装完发现node命令指向的是这个版本,npm全局目录又残留着另一个版本的痕迹。
直接给结论:新学Node.js,优先用nvm;如果你只想在服务器上快速跑个服务,Ubuntu上用apt或者直接下载官方二进制包也可以;但千万不要已经用nvm了,又手痒去官网装一个覆盖,也不要明明apt装的,又拿官方包去解压覆盖。
为什么推荐nvm?因为它按用户维度的目录安装,不需要sudo,装错版本随时换,每个shell都能切换。这样你在不同项目里切换Node版本,代价几乎为零。而那些一上来就骂"Node.js 装不上"的人,八成是直接把别人博客里的命令apt install nodejs和curl安装nvm混着执行了,最后PATH里全是坑。
2.3 为什么Ubuntu 20+要看准版本
很多人搜"ubuntu安装node.js 20+",是因为Ubuntu自带的软件源仓库里,Node.js版本往往很旧。比如Ubuntu 20.04的默认源里,apt install nodejs装出来可能还是10.x甚至更老。十年前的老项目也许够用,但放到今天,很多npm包已经不再兼容了。
所以如果你在Ubuntu上用apt装Node,一定要考虑添加NodeSource源,或者直接用nvm安装指定版本。热搜里的"ubuntu安装node.js 20+"就是这么来的:不是用户挑版本,而是系统源里的版本太旧,满足不了现代项目需求。装完之后用node -v一看,如果版本是v10.x、v12.x,别急着说"装好了",先确认它是不是你真正想要的版本。
3. 三种主流安装方式实操
3.1 方式一:Ubuntu 20+用apt安装
在Ubuntu上用apt快速装Node,最简单的办法是先用apt更新索引,然后直接安装。但你会发现装出来的版本老旧,于是推荐用NodeSource的方式装指定版本。NodeSource是社区维护的安装脚本源,可以指定安装20.x这样的LTS版本。
先执行:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt-get install -y nodejs这个脚本会帮你把NodeSource的软件源写入系统,然后从该源安装20.x。装完执行:
node -v npm -v你会看到v20.x.x和对应的npm版本。这个安装方式的优点是系统级安装,全局命令对所有用户都可用;缺点是升级时要走apt,且版本切换不方便。如果你只是一个服务器,只运行一个项目,这种方式其实够用了。
3.2 方式二:官网下载Node.js二进制包
如果你不想用脚本,想要完全掌控目录结构,可以直接从Node.js官网下载二进制压缩包。在官网下载页选择LTS版本,选Linux x64的.tar.xz文件。下载后解压到你想要的目录,比如/opt/node:
wget https://nodejs.org/dist/v20.12.0/node-v20.12.0-linux-x64.tar.xz sudo mkdir -p /opt/node sudo tar -xJf node-v20.12.0-linux-x64.tar.xz -C /opt/node --strip-components=1然后把/opt/node/bin加入PATH。可以临时执行:
export PATH=/opt/node/bin:$PATH永久生效的话,编辑~/.bashrc,在末尾加上这一行,然后source ~/.bashrc。这种方式的优点是你完全知道 Node装在哪、版本是什么,卸载就是删目录。缺点是需要手动管理PATH,容易和系统其他安装方式冲突。
3.3 方式三:用nvm安装和切换版本
nvm全称Node Version Manager,专门用来管理多个Node版本。它的安装方式很标准,用官方install脚本:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash装完后,可能需要重新打开终端或者source ~/.bashrc,然后使用:
nvm install 20 nvm use 20nvm install默认会装最新的20.x版本,你不用精确指定补丁号。装完node -v一下就看到版本。如果以后想切换其他版本:
nvm install 18 nvm use 18 nvm lsnvm ls会列出所有已安装版本,nvm use切换当前shell的默认版本,nvm alias default 20设置默认版本。你还能在项目目录里创建一个.nvmrc文件,写上版本号,然后别人用nvm use就能自动切到对应版本。这个功能在团队协作时特别实用,解决"我本地能跑,你本地跑不了"的经典问题。
3.4 装完怎么确认真的装好了
很多人执行完安装命令就以为大功告成,直到运行项目才发现命令不对。装完后至少做三件事验证:
- 执行
node -v,确认Node版本。 - 执行
npm -v,确认npm能跑。 - 执行
which node,确认当前node命令的路径,尤其当你混用了多种安装方式时,这个命令能帮你一眼看出问题所在。
另外,新建一个临时目录,执行node -e "console.log('hello node')",如果能输出hello node,说明环境基本可用。不要小看这步,我有次装完nvm之后,node -v正常,但一执行npm install就报cannot find module,最后发现是npm的全局前缀目录有问题。顺手验证一下也是好的习惯。
4. 安装和运行时最容易踩的坑
4.1 "error installing 24.21.0: node.js v24.21.0 is not yet released or is not available"是怎么回事
这个报错经常出现在用nvm或者某个版本管理工具安装Node时。字面意思是"24.21.0这个版本还没发布或者不可用"。遇到这个报错,先别急着谷歌乱搜,按以下顺序排查:
- 检查版本号是否真实存在。去Node.js官网 Releases页面看一眼版本列表,如果压根没有这个版本号,那就是手滑或者工具索引过期。
- 检查版本切换工具的索引。nvm依赖远程版本列表,旧版本的工具可能缓存了过期的元数据。执行
nvm ls-remote刷新列表,再重新安装。 - 检查公司代理、镜像源是否同步。很多团队内部使用私有npm源或Node二进制镜像源,如果镜像没有同步最新版本,也会提示"not available"。
- 检查是否多字节拼写错误。比如写
nvm install v24.21.0时多写了个v,部分工具不兼容这种写法,去掉v再试。
这个报错十有八九是版本号写错或者源不同步,少部分情况是工具自身有bug。调整策略:要么换用LTS版本,要么升级nvm到最新版。
4.2 npm install报权限错误
新手在Linux或macOS上跑npm install -g某个包,经常会出现EACCES: permission denied。这是因为npm的全局安装目录默认在系统目录下,普通用户没有写权限。错误解法是直接在命令前加sudo。用sudo装全局包,当时眼瞅着成功了,过阵子另一个用户运行这个命令,又报权限错误,而且全局目录一旦被root占用,后续清理很麻烦。
正确解法有两个。第一,用nvm装Node,这样npm全局目录就在你的用户目录下,压根没有权限问题。第二,如果是系统级Node,可以考虑给npm配置一个用户级的前缀目录:
mkdir ~/.npm-global npm config set prefix '~/.npm-global'然后在~/.bashrc里加export PATH=~/.npm-global/bin:$PATH,再source ~/.bashrc。这样全局安装的包都会落到用户目录,不再需要sudo。记住一句话:能用用户目录解决的问题,不要碰sudo。
4.3 node和npm版本对不上?多半是混装了
你有没有遇到过这种场景:node -v显示v20.x,但npm -v提示的npm版本却是很老的6.x,或者执行npm install时警告npm和Node不兼容。原因十有八九是你混装了多个Node来源。比如系统apt装了一个旧node,nvm又装了一个新node,当前shell的node走的是nvm的目录,npm却还指向系统目录。
排查步骤:
which node which npm head -1 $(which npm)npm其实是一个shell脚本,它的第一行shebang会指定用哪个node来执行。如果which node和which npm指向不同目录,就说明系统里有两套Node。解决办法是清理干净,保住一套。如果是nvm用户,完全卸载apt装的nodejs相关包,或者至少调整PATH,让nvm的bin目录排在前面:
export PATH="$(nvm dir)/current/bin:$PATH"在大团队里,这种问题特别常见,因为大家各自按照不同博客的教程装Node,每个人环境都不同。统一用nvm或统一用apt,至少能减少同类问题。
4.4 下载慢的解决办法:npm镜像源
npm install拉取依赖时慢到怀疑人生,这是国内开发者绕不开的痛。慢多数来源于网络链路到官方registry的延迟,而不是Node本身的问题。解决办法是把npm registry切到国内的公共镜像源。比如使用npmmirror源:
npm config set registry https://registry.npmmirror.com执行完npm config get registry确认一下。这个镜像源访问速度快,同步频率也算及时。但要注意,有些私有npm包或者公司内部registry,不能全局改这个配置,正确做法是项目级配置。在项目根目录写一个.npmrc文件:
registry=https://registry.npmmirror.com这样只对当前项目生效,不影响全局。这里要提醒一句:如果你通过某些特殊手段加速下载,务必确保使用的是公开、合规的镜像服务。
5. 装好之后先跑一个能用的东西
5.1 不用框架,用http模块起一个服务
很多人装完Node.js,不知道接下来该干嘛。我建议先别急着上Express,先用Node内置的http模块起一个最小的服务,理解请求和响应是怎么回事。
const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello Node.js'); }); server.listen(3000, () => { console.log('Server is running at http://localhost:3000'); });保存为server.js,执行node server.js,然后浏览器打开http://localhost:3000,看到Hello Node.js就说明你的环境已经能跑服务了。别看这段代码简单,它揭示了一件重要的事:你写的JavaScript正在一个独立的进程里监听端口、处理网络请求,这就是Node.js的核心工作方式。Ctrl+C可以停掉服务。
5.2 建一个package.json管理依赖
手动管理npm包是一件很痛苦的事,于是有了package.json。在项目目录执行:
npm init -y它会生成一个默认的package.json。里面最重要的几个字段是name、version、scripts和dependencies。scripts这个字段很实用,比如你不想每次都敲node server.js,可以在package.json里配置:
"scripts": { "start": "node server.js" }然后执行npm start就能启动服务。npm install安装的依赖会写入dependencies,别人拿到项目后执行npm install就会按文件下载安装,保证环境一致。这也是Node生态如此强大的基础:一个项目依赖声明清晰,换台机器就能跑起来。
5.3 用npx跑工具,别乱全局装
提到npm install,就得讲一个实用工具:npx。以前我们要用某个命令行工具,习惯先全局安装,比如npm install -g some-tool,然后直接用命令。这样很容易污染全局目录,还容易版本冲突。npx的出现改变了这个习惯:它可以直接运行npm包,而不需要全局安装。
举个例子,你想在项目里用某个工具格式化代码:
npx prettier --write .npx会临时下载并执行prettier,用完就丢。这样不会污染全局环境,也保证了工具版本跟随项目。npx create-vite这类初始化命令也是一样,它帮你执行脚手架的初始化流程,不需要你提前全局安装脚手架。所以新项目里,能不用全局安装就不用,优先npx。
5.4 一个实际项目的目录和起步命令
把上面的知识点合起来,一个稍微有点实际感的小项目结构可以是:
project/ package.json server.js node_modules/你在server.js里写上面那段HTTP服务代码,然后用npm init -y生成package.json,再在scripts里配置"start": "node server.js"。执行npm start,打开浏览器看到页面。接着再体验一下npm install axios,在代码里尝试调用一个公共API,比如天气接口,输出JSON数据。node_modules会变厚,package.json的dependencies里会多出axios,这就是Node项目最典型的起步流程。
跑通了这一步,你就不再是"装完就卸载"的围观群众了,而是真正把Node.js用了起来。
6. 装完Node之后,我特别想说的几句话
这些年我在各种环境里装过Node.js,从Windows到macOS再到Ubuntu服务器,踩过的坑绝大多数不是技术难,而是来源太多、环境太杂。我的建议一直是:个人电脑用nvm,服务器上要想省事就用apt配NodeSource,或者也用nvm,关键是一台机器只保留一种安装来源。遇到报错不要急着搜那句错误信息,先跑which node、node -v、npm -v,把基础信息确认清楚,问题往往就解决了一半。
有个习惯特别值得养成:换新机器时,第一时间安装nvm,然后用nvm装LTS版本,再配置npm镜像源和用户级全局目录。这一套做完,你后面几年装任何Node工具都会很顺。最后再分享一个小技巧,如果你经常忘记Node版本,可以在项目的package.json里写上"engines": { "node": ">=20" },然后在执行npm install之前用nvm use配合.nvmrc固定版本,这样同一个项目在谁的机器上都用同一个Node环境,很多莫名其妙的"我这能跑你那跑不了"的问题,基本都能从源头掐掉。