Node.js入门指南:从环境安装到构建第一个Web应用

Node.js入门指南:从环境安装到构建第一个Web应用 Node.js 入门教程很多但真正能帮你在 1 小时内把安装、验证、编码、跑通全部走完的并不多。这篇文章以“从下载 Node.js 到写出第一个 Web 应用”为主线把 60 分钟拆成四段前 10 分钟搞清楚 Node.js 是干什么的、版本怎么选中间 15 分钟完成安装和 npm 基础配置接下来 20 分钟用 Node.js 自带模块写一个能访问的 Web 页面最后 15 分钟排查安装和运行时最常见的报错。这样做的好处是每一步都能验证结果不会出现“环境配了一下午代码一跑全是问题”的情况。1. 先搞清楚 Node.js 是干什么的再决定安装哪个版本1.1 Node.js 不是普通脚本工具而是一个 JavaScript 运行时Node.js 的官方定位是“基于 Chrome V8 引擎的 JavaScript 运行时”。通俗一点说浏览器给 JavaScript 提供了window、document、fetch等环境而 Node.js 给 JavaScript 提供了文件读取、网络请求、进程管理、操作系统交互等能力。这意味着你不再需要通过 HTML 页面来运行 JavaScript可以直接在终端执行node -e console.log(hello node)这行命令会创建一个 Node.js 进程执行字符串里的 JavaScript 代码然后把结果输出到控制台。对刚入门的人来说只要理解这一点就够了Node.js 让 JavaScript 从“只能操作页面”变成“可以操作文件和网络”的通用语言。1.2 事件驱动、非阻塞 I/O 到底影响什么很多资料会提到“事件驱动”“非阻塞 I/O”“单线程”。这里用一句更贴近实际的话解释Node.js 遇到耗时操作时不会一直卡住等待结果而是先继续处理其他请求等耗时操作完成后通过回调继续处理。看一个简单对比// 模拟耗时读取不推荐生产环境使用 fs.readFileSync const fs require(fs); console.log(1. 开始读取); const data fs.readFileSync(example.txt, utf8); console.log(2. 读取完成, data.length); console.log(3. 继续执行);上面这段用同步方式读文件执行到第二行时整个进程会等待文件读完才继续执行第三行。如果改用异步方式const fs require(fs); console.log(1. 开始读取); fs.readFile(example.txt, utf8, (err, data) { console.log(2. 读取完成, data ? data.length : error); }); console.log(3. 继续执行);执行顺序会变成“1、3、2”。异步 I/O 是 Node.js 能同时处理大量并发请求的重要原因。对于刚入门的第一个 Web 应用你不需要立刻精通它但必须理解fs.readFile的回调不会阻塞后续代码。1.3 LTS、Current、偶数版本号怎么选安装 Node.js 前最容易出错的是版本选择。官方发布版本大致分两类版本类型说明适合场景LTSLong Term Support长期支持版本会持续维护和修复漏洞推荐新手、生产环境、企业项目Current当前版本包含新特性但迭代快、可能不稳定尝鲜、特性验证、短期学习偶数版本例如 18、20、22通常更容易进入 LTS 周期稳定性优先的项目奇数版本例如 19、21、23通常是过渡版本不建议作为主力实际项目里建议安装当前最新 LTS而不是最新 Current。原因很直接很多 npm 包对 Node.js 版本有要求LTS 版本生态兼容更好遇到问题时搜索引擎能找到更多答案。1.4 安装前的环境检查清单安装前先检查操作系统、CPU 架构和是否已存在旧版本# Windows PowerShell systeminfo | findstr /C:OS # Linux / macOS uname -m # 检查是否已经安装过 Node.js node -v npm -vWindows 下尤其要注意架构绝大多数现代电脑使用 64 位系统应该下载x64安装包部分旧电脑是 32 位系统需要下载x86包。如果系统里已经安装了旧版 Node.js先确认版本避免安装新版本后 PATH 环境变量混乱。2. 安装 Node.js 的三种方式以及为什么推荐用 nvm2.1 Windows 图形化安装包最快但最不灵活进入 Node.js 官网下载页选择适合当前系统的.msi安装包双击运行即可。安装过程中默认已经包含“添加到 PATH”选项一般不需要修改一直下一步即可。安装完成后重新打开一个终端窗口执行node -v npm -v如果输出类似v22.13.1 10.9.2说明安装成功。需要注意安装完成后必须新开终端窗口否则当前终端的 PATH 不会刷新仍然提示找不到node命令。这种方式适合只跑一次 Node.js、不打算切换项目的用户。缺点是当某个项目依赖 Node.js 20另一个项目依赖 Node.js 22 时图形化安装包无法灵活切换版本。2.2 Windows 下使用 nvm-windows 管理多版本跨项目开发时推荐使用 nvmNode Version Manager管理 Node.js 版本。Windows 上没有直接移植原版 nvm常用的是 nvm-windows。安装方式从 nvm-windows 的发布页面下载安装包。安装到一个不含中文和空格的目录例如C:\nvm。安装完成后终端执行nvm version然后安装并切换 Node.js 版本nvm install 22.13.1 nvm use 22.13.1 node -v执行nvm use后node命令会指向 nvm 管理目录下的对应版本。这里的关键点是不要直接到官网下载安装包和管理器混用那会让node命令的来源不确定。我的建议是Windows 新项目统一用 nvm-windows即使以后需要升级 Node.js 或同时维护旧项目也不会被版本问题卡住。2.3 macOS/Linux 下的 nvm 安装macOS 或 Linux 用户可以使用官方脚本安装 nvm但不要直接复制网上来路不明的curl脚本应该先检查内容再执行。安装 nvm 后shell 配置文件通常是.zshrc或.bashrc会追加 nvm 初始化脚本。安装完成要重新加载配置source ~/.zshrc然后安装 Node.jsnvm install --lts nvm use --lts node -v--lts会安装当前最新的长期支持版本避免手动指定容易过时的版本号。2.4 安装完成后的检查点无论使用哪种方式都要完成以下检查检查项命令预期结果Node.js 可用node -v输出类似v22.13.1npm 可用npm -v输出类似10.9.2nvm 可用nvm version输出 nvm 版本号全局路径npm root -g输出存在的全局 node_modules 目录缓存路径npm config get cache输出 npm 缓存目录如果node -v能正常输出但npm -v报错通常是因为安装包损坏、PATH 中存在多个 Node.js 目录或旧版残留。不要急着重装先运行where nodeWindows或which nodeLinux/macOS确认实际执行路径。3. 用 npm 做基础配置镜像源、全局路径和缓存目录3.1 npm 的职责与版本npm 是 Node.js 自带的包管理器负责下载、安装、卸载第三方依赖并维护项目的依赖关系。它和node是两套程序Node.js 负责运行 JavaScriptnpm 负责管理 JavaScript 需要的库。npm 的版本通常不等同于 Node.js 版本。安装 Node.js 后npm 也一并安装。日常使用中不要只关注node -v还要关注npm -v。某些 CLI 工具会要求 npm 版本达到阈值如果版本过旧可以通过以下命令升级 npmnpm install -g npmlatest3.2 配置镜像源避免安装依赖超时在实际网络环境里直接从官方源安装依赖可能很慢常见表现是npm install长时间停留在idealTree阶段或者直接超时。可以把 npm 的 registry 切换到国内镜像npm config set registry https://registry.npmmirror.com/验证是否生效npm config get registry也可以直接查看配置文件位置npm config ls -l这里要注意的是全局使用镜像源会影响所有项目。如果某些项目必须使用官方源或公司内网源可以只在项目根目录创建.npmrc写入registryhttps://registry.npmjs.org/项目级配置会覆盖全局配置。这样就能做到“全局用镜像个别项目用官方源”。3.3 全局安装路径和权限使用全局安装命令时npm install -g npm-check-updates全局包会安装到npm root -g指向的目录。Windows 下全局命令通常会被软链到 npm 前缀目录如果没有正确配置会出现“命令安装成功但终端找不到”的问题。Linux/macOS 下如果直接使用npm install -g遇到权限错误不要用sudo强行安装更推荐修改 npm 的全局目录到用户目录下mkdir -p ~/.npm-global npm config set prefix ~/.npm-global然后在 shell 配置文件中添加export PATH~/.npm-global/bin:$PATH这样全局安装的 CLI 工具都可以直接用也避免了权限污染。3.4 验证 npm 配置配置完成后创建一个临时目录测试 npm 是否能正常安装依赖mkdir npm-config-test cd npm-config-test npm init -y npm install lodash看到node_modules目录生成并出现package-lock.json说明安装链路正常。检查点有npm config get registry输出镜像地址。npm root -g输出一个可写目录。npm install没有权限和超时报错。注意不要在生产环境随意使用npm cache clean --force。多数安装问题不是缓存损坏而是镜像源或版本不对。强行清理缓存反而会拖慢下一次安装。4. 创建第一个 Web 应用使用内置 http 模块4.1 初始化项目和目录结构先创建项目目录mkdir node-first-app cd node-first-app npm init -ynpm init -y会生成一个默认的package.json内容类似于{ name: node-first-app, version: 1.0.0, description: , main: index.js, scripts: { test: echo \Error: no test specified\ exit 1 } }对于第一个 Web 应用这个文件不是必须修改的但要理解它记录了三类信息项目名称与版本、入口文件、启动脚本。后续添加第三方依赖时dependencies也会写到这里。4.2 最小可运行的 HTTP 服务器新建server.js文件写入const http require(http); const hostname 127.0.0.1; const port 3000; const server http.createServer((req, res) { res.statusCode 200; res.setHeader(Content-Type, text/plain; charsetutf-8); res.end(Hello Node.js Web App); }); server.listen(port, hostname, () { console.log(Server running at http://${hostname}:${port}/); });这段代码的每一行都有明确作用require(http)导入 Node.js 内置的 HTTP 模块。http.createServer接收一个回调函数每次有请求进来都会执行。req是请求对象包含 URL、请求方法、请求头。res是响应对象用来设置状态码、响应头和响应体。listening是网络层面的监听端口这里指定127.0.0.1:3000。4.3 解析请求参数和返回 JSON第一个 Web 应用如果只有“Hello World”还看不出实用价值。扩展一下根据 URL 返回用户信息。const http require(http); const url require(url); const server http.createServer((req, res) { const parsedUrl new URL(req.url, http://${req.headers.host}); const pathname parsedUrl.pathname; res.setHeader(Content-Type, application/json; charsetutf-8); if (req.method GET pathname /user) { const name parsedUrl.searchParams.get(name) || anonymous; res.statusCode 200; res.end( JSON.stringify({ code: 0, data: { name, time: new Date().toISOString() } }) ); return; } res.statusCode 404; res.end(JSON.stringify({ code: 404, message: Not Found })); }); server.listen(3000, 127.0.0.1, () { console.log(Server running at http://127.0.0.1:3000/); });访问http://127.0.0.1:3000/user?namenode返回{code:0,data:{name:node,time:2025-01-01T12:00:00.000Z}}这里用到了URL对象是 Node.js 内置的 URL 解析方式。比手动拆分字符串更可靠也能处理中文参数、编码问题。4.4 启动服务和验证接口执行node server.js输出Server running at http://127.0.0.1:3000/然后打开浏览器访问http://127.0.0.1:3000/user?namenode或者用命令行验证curl http://127.0.0.1:3000/user?namenode注意curl在 Windows PowerShell 中默认可能是Invoke-WebRequest的别名。如果输出格式不同可以改用curl.exe或者使用curl.exe -v查看详细请求过程。验证成功后按Ctrl C终止服务器。这里最容易犯的错误是修改server.js后没有重启进程。Node.js 不会自动加载代码修改必须结束旧进程再启动。5. 让开发更顺手脚本、自动重启和调试5.1 package.json 的 scripts把启动命令写进package.json项目就会更规范{ name: node-first-app, version: 1.0.0, main: server.js, scripts: { start: node server.js, dev: nodemon server.js } }保存后执行npm startnpm run dev需要先安装 nodemon下面继续讲。5.2 使用 nodemon 自动重启开发时反复手动停止、启动服务器很低效。可以用 nodemon 监听文件变化文件被保存时自动重启进程npm install -D nodemon安装后启动npx nodemon server.js这个依赖是开发依赖只有开发环境需要。打包或部署生产环境时不应该依赖 nodemon而应该使用进程守护工具或容器管理。5.3 命令行调试与内置调试器最简单的故障定位方法是加日志const server http.createServer((req, res) { console.log(${req.method} ${req.url}); // ... });每来一个请求终端都会输出请求方法和 URL。遇到浏览器请求/favicon.ico、请求路径不对、参数丢失时日志是最快的证据。如果日志不够可以使用 Node.js 内置调试器node --inspect server.js然后打开 Chrome 的chrome://inspect对 Node.js 进程进行断点调试。不过这个操作对刚入门的人可能略重先从日志排查更实际。5.4 通过日志和 curl 定位问题下面是一个简单排查顺序先看终端有没有报错。没有报错再用curl验证接口而不是只看浏览器。比较浏览器和curl的响应差异定位请求方法、请求头、请求参数问题。如果接口返回 404先打印req.url。如果接口返回乱码检查Content-Type是否带charsetutf-8。如果请求一直超时检查端口是否被占用、server.listen是否配置正确、防火墙是否拦截。6. 常见安装和运行问题排查6.1 Windows 安装报错或缺少 Visual C Runtime在 Windows 安装某些 Node.js 安装包时可能输出“需要 Microsoft Visual C 2015-2022 Redistributable”相关提示。这不是 Node.js 本身损坏而是操作系统缺少运行库。处理方式安装微软官方提供的 Visual C Redistributable 包。安装完成后重启电脑再重新安装 Node.js。不要在同一个系统里反复安装多个.msi和.zip版 Node.js容易导致 PATH 混乱。6.2 输入 node -v 提示不是内部或外部命令常见原因有三个安装完成后没有新开终端窗口。安装时没有勾选“添加到 PATH”。系统存在旧版本残留多条 PATH 互相干扰。排查方式where node echo %PATH%如果where node找到多个路径通常说明旧版本或不同架构的 Node.js 混在一起。建议先卸载所有不用的 Node.js只保留 nvm 管理的一个版本再重新配置 PATH。6.3 nvm install 提示 not yet released 或 not available使用 nvm 安装具体版本时可能看到error installing 22.13.1: Node.js v22.13.1 is not yet released or is not available这通常有两个原因nvm 本地的版本列表太旧还没有同步到最新版本。你指定的版本号不正确或者该版本不在当前 nvm 兼容列表中。处理方式nvm list available先查可用版本再选择列表中存在的版本号安装。如果列表里仍然没有尝试升级 nvm-windows 到最新版本。不要凭感觉手写版本号版本号必须和官方发布列表一致。6.4 npm install 很慢或超时优先检查 registrynpm config get registry如果地址是官方源导致速度慢按前面 3.2 节配置镜像源。如果已经是镜像源仍然慢检查是否项目依赖了非常多的大型包以及网络是否不稳定。不要频繁删除node_modules那不是解决慢的首选方法。6.5 端口被占用启动服务器时出现Error: listen EADDRINUSE: address already in use :::3000说明 3000 端口已经被占用。查看占用进程# Windows netstat -ano | findstr :3000 # Linux / macOS lsof -i :3000找到 PID 后确认进程可以结束再清理# Windows taskkill /PID 1234 /F也可以直接把server.js里的端口改成其他值比如3001。实际开发中端口应该通过环境变量配置不写死在代码里。6.6 修改代码后页面没变化Node.js 不会热更新。如果修改了server.js但浏览器页面还是旧内容优先确认终端里是否重启了服务器。如果使用 nodemon 却仍然没变化检查正在执行的是不是nodemon server.js以及文件保存位置是否在 nodemon 监听范围内。注意浏览器自带缓存也会造成“代码改了但页面没变”的假象。先用curl请求接口如果curl返回新内容问题在浏览器缓存如果curl也返回旧内容问题在服务进程没有重启。7. 把第一个 Web 应用扩展到接近生产形态7.1 使用 Express 重写接口内置http模块适合理解原理但真实项目很少直接用它写业务接口。更多项目会使用 Express。先安装npm install express然后创建app.jsconst express require(express); const app express(); const port process.env.PORT || 3000; app.get(/, (req, res) { res.send(Hello Node.js Web App); }); app.get(/user, (req, res) { const name req.query.name || anonymous; res.json({ code: 0, data: { name, time: new Date().toISOString() } }); }); app.listen(port, () { console.log(Server running at http://127.0.0.1:${port}/); });Express 把路由、参数解析、JSON 响应都封装得更容易使用。学习和实际项目之间顺序是先会用http模块再切换到 Express最后再理解 Express 的中间件机制。7.2 环境变量与默认值第一个应用里端口写死为3000这没问题但生产环境通常不会固定端口。推荐方式const port process.env.PORT || 3000;这样本地不配置时用 3000部署平台注入PORT时读取平台端口。学习环境可以直接在命令行运行。生产环境还要考虑日志写到文件或集中日志平台。进程崩溃后自动重启。配置信息通过环境变量传入。监听地址根据部署平台调整。增加健康检查接口。7.3 目录规约和 .gitignore即使只有几个文件也可以从一开始建立规范node-first-app/ ├── app.js ├── package.json ├── package-lock.json └── .gitignore.gitignore至少要忽略node_modules/ .env *.lognode_modules是依赖安装后的目录不应该提交到 Git其他人拉取代码后通过npm install恢复。7.4 学习环境与生产环境的差异维度学习环境生产环境启动方式node server.js或 nodemon进程守护工具、容器、CI/CD 平台端口写死或process.env.PORT || 3000由平台注入环境变量日志终端输出独立日志文件、日志收集系统异常处理res.end直接返回统一错误中间件、告警依赖开发依赖不区分npm ci --production生成可复现依赖安全仅本机访问鉴权、限流、HTTPS、防火墙策略这里最核心的理解是能跑通不代表能上线。生产环境多出来的不是“更多代码”而是对异常、可观测性、回滚和安全的约束。7.5 可复用的检查清单分享一份适合自己的项目发布前检查清单node -v与项目要求的 Node.js 版本一致。package.json的scripts.start能正常启动。接口使用curl -i验证过状态码、响应头和响应体。node_modules已加入.gitignore。端口没有写死支持process.env.PORT。异常分支有日志不会静默失败。不使用裸catch吞掉错误。不需要在终端手工维持进程时提供进程守护方案。对于刚完成第一个 Web 应用的开发者下一步可以按这个顺序扩展先给接口增加表单提交和 JSON 请求体解析然后加上简单的文件读写接着学习 Express 中间件再接触数据库连接和 ORM。每一步都保持“先起一个能跑的最小例子再逐步加功能”比一次性啃完 Node.js 所有 API 有效得多。