
我平时最烦看到新手一上来就搜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/ONode.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.x21.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/nodewget 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-components1然后把/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装了一个旧nodenvm又装了一个新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文件registryhttps://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的核心工作方式。CtrlC可以停掉服务。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环境很多莫名其妙的我这能跑你那跑不了的问题基本都能从源头掐掉。