Node.js: 认识 Node.js

Alice 是一名后端开发者,她的公司需要在两周内为移动应用构建一套 REST API 后端。团队里全是前端开发者,只会 JavaScript,没人愿意再花时间学一门新语言。项目经理甚至考虑过招 Python 开发者,但时间根本来不及。就在团队陷入焦虑时,Alice 发现了 Node.js——一个让 JavaScript 跑在服务器上的运行时。前端开发者用熟悉的语法就能写后端 API,两周后项目顺利上线。这让 Alice 意识到:Node.js 不只是工具,更是打通前后端的桥梁。

你将学到:


1. Node.js 是什么

(1) 定义

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境。它让 JavaScript 脱离浏览器,可以直接在服务器端运行。Node.js 不是一门新语言,也不是一个框架,而是 JavaScript 的服务器端执行平台。

(2) 诞生背景

2009 年,Ryan Dahl 基于 V8 引擎创建了 Node.js。他的初衷是解决服务器端 I/O 操作的阻塞问题——传统的 Web 服务器在处理文件读取、网络请求等 I/O 操作时会阻塞线程,而 Node.js 采用事件驱动的方式,让单线程也能高效处理大量并发连接。

▶ 示例:第一个 Node.js 脚本

创建文件 hello.js

JAVASCRIPT
console.log('Hello, Node.js!');
console.log('Node.js version:', process.version);
console.log('Platform:', process.platform);
▶ 试一试

在终端运行:

BASH
node hello.js

预期输出:

TEXT 📖 仅展示
Hello, Node.js!
Node.js version: v20.11.0
Platform: win32


2. V8 引擎与 Node.js 架构

(1) V8 引擎的角色

V8 是 Google 开发的 JavaScript 引擎,负责将 JavaScript 代码编译为机器码执行。Node.js 直接嵌入了 V8 引擎,因此获得了极高的执行性能。V8 的即时编译(JIT)技术让 JavaScript 的运行速度接近原生代码。

(2) Node.js 架构分层

Node.js 的架构自下而上分为四层:

层级 组成 作用
JavaScript 代码层 用户编写的 .js 文件 业务逻辑
Node.js API 层 fs、http、path 等模块 提供服务器端能力
Node.js Bindings 层 C++ 桥接代码 连接 JavaScript 与底层 C 库
底层库层 V8、libuv、OpenSSL 等 引擎与系统调用

(3) libuv 的关键作用

libuv 是 Node.js 的异步 I/O 库,提供了事件循环、线程池和跨平台的异步 I/O 抽象。它让 Node.js 在不同操作系统上都能以统一的方式处理文件、网络、定时器等异步操作。

▶ 示例:查看 Node.js 依赖库信息

JAVASCRIPT
console.log('V8 version:', process.versions.v8);
console.log('libuv version:', process.versions.libuv);
console.log('OpenSSL version:', process.versions.openssl);
console.log('Node.js version:', process.version);
▶ 试一试

输出:

TEXT 📖 仅展示
V8 version: 11.3.244.8
libuv version: 1.46.0
OpenSSL version: 3.0.12
Node.js version: v20.11.0

▶ 示例:(4) 架构图

100%
graph TB
    A["JavaScript 代码<br/>(用户编写的 .js 文件)"] --> B["Node.js API<br/>(fs / http / path / ...)"]
    B --> C["Node.js Bindings<br/>(C++ 桥接层)"]
    C --> D1["V8 引擎<br/>(JavaScript 编译执行)"]
    C --> D2["libuv<br/>(事件循环 + 异步 I/O)"]
    C --> D3["其他 C 库<br/>(OpenSSL / zlib / c-ares)"]
    D2 --> E["操作系统<br/>(文件 / 网络 / 进程)"]


3. 事件驱动与非阻塞 I/O

(1) 事件驱动模型

Node.js 采用事件驱动架构:程序通过注册事件回调来响应各种操作,而不是主动轮询。当 I/O 操作完成时,事件循环会将对应的回调放入队列等待执行。

(2) 非阻塞 I/O 的含义

传统服务器在读取文件时会阻塞当前线程,直到文件读取完毕。Node.js 发起 I/O 请求后立即返回,继续执行后续代码,等 I/O 完成后再通过回调处理结果。这种模式让单线程也能同时处理数百个并发请求。

(3) 事件循环简介

事件循环是 Node.js 的核心调度机制,按以下阶段循环运行:

  1. timers:执行 setTimeout / setInterval 回调
  2. pending callbacks:执行系统操作的回调
  3. idle, prepare:内部使用
  4. poll:获取新 I/O 事件,执行 I/O 回调
  5. check:执行 setImmediate 回调
  6. close callbacks:执行关闭事件回调

▶ 示例:阻塞 vs 非阻塞读取文件

阻塞方式(不推荐):

JAVASCRIPT
const fs = require('fs');
const data = fs.readFileSync('/etc/hosts', 'utf8');
console.log('File read (blocking):', data.length, 'bytes');
console.log('This line runs after file is read');
▶ 试一试

非阻塞方式(推荐):

JAVASCRIPT
const fs = require('fs');
fs.readFile('/etc/hosts', 'utf8', (err, data) => {
  if (err) throw err;
  console.log('File read (non-blocking):', data.length, 'bytes');
});
console.log('This line runs immediately');

输出(非阻塞方式):

TEXT 📖 仅展示
This line runs immediately
File read (non-blocking): 250 bytes

注意非阻塞方式中,"This line runs immediately" 先输出,说明 readFile 没有阻塞后续代码。



4. Node.js vs 浏览器 JavaScript

(1) 核心差异

Node.js 和浏览器中的 JavaScript 使用相同的语言规范(ECMAScript),但运行环境和可用 API 完全不同。

对比维度 Node.js 浏览器 JavaScript
运行环境 服务器 浏览器
模块系统 CommonJS / ESM ESM
全局对象 global / process window / document
文件系统 fs 模块直接访问 无法直接访问
网络 I/O http / net 模块 fetch / XMLHttpRequest
DOM 操作 无 DOM 有 DOM API
安装包管理 npm 无(或通过 CDN)
主要用途 服务器应用、CLI 工具 网页交互、UI 渲染

(2) 共同点

▶ 示例:相同的语法,不同的 API

浏览器代码:

JAVASCRIPT
document.getElementById('output').textContent = 'Hello from browser';
▶ 试一试

Node.js 代码:

JAVASCRIPT
const fs = require('fs');
fs.writeFileSync('output.txt', 'Hello from Node.js');

同样的 JavaScript 语法,但操作对象完全不同:浏览器操作 DOM,Node.js 操作文件系统。



5. Node.js 的典型应用场景

(1) REST API 服务

Node.js 非常适合构建 RESTful API。其非阻塞 I/O 模型可以高效处理大量并发请求,JSON 是 JavaScript 的原生数据格式,省去了序列化转换的步骤。

(2) CLI 工具

Webpack、Babel、ESLint、npm 本身都是用 Node.js 构建的 CLI 工具。Node.js 提供了丰富的文件系统、子进程和命令行参数处理 API。

(3) 实时应用

聊天系统、在线协作、实时通知等场景需要持久的双向连接。Node.js 的 WebSocket 支持和事件驱动架构天然契合这类需求。

(4) 微服务

Node.js 启动快、内存占用小,适合作为轻量级微服务。每个微服务可以独立部署和扩展。

(5) 爬虫与数据采集

结合 Cheerio 等库,Node.js 可以高效抓取和解析网页数据,异步 I/O 让并发请求效率极高。

▶ 示例:应用场景对比

场景 优势 代表项目
REST API 非阻塞 I/O + 原生 JSON Express / Fastify / Koa
CLI 工具 文件操作 + 子进程 Webpack / Babel / ESLint
实时应用 WebSocket + 事件驱动 Socket.IO / ws
微服务 轻量 + 快速启动 NestJS / seneca
爬虫 异步并发 + DOM 解析 Puppeteer / Cheerio

▶ 示例:5 行代码创建 HTTP 服务器

JAVASCRIPT
const http = require('http');
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ message: 'Hello from Node.js API' }));
});
server.listen(3000, () => console.log('Server running on port 3000'));
▶ 试一试
BASH
node server.js
TEXT 📖 仅展示
Server running on port 3000

访问 http://localhost:3000 即可看到 JSON 响应。



6. Node.js 版本策略

(1) LTS 与 Current

Node.js 采用双轨发布策略:

对比项 LTS(长期支持版) Current(当前版)
发布周期 每两年一个大版本 每 6 个月一个大版本
维护期 30 个月 约 6 个月
稳定性 高,仅接收 bug 修复和安全补丁 低,包含最新特性
适用场景 生产环境 体验新特性、测试
版本号规则 偶数号(18、20、22...) 奇数号(19、21、23...)

(2) 版本选择建议

(3) 版本管理工具

推荐使用 nvm(Node Version Manager)来管理和切换 Node.js 版本。

▶ 示例:使用 nvm 管理版本

BASH
nvm install 20
nvm use 20
nvm ls
TEXT 📖 仅展示
       v18.17.0
->     v20.11.0
         system
default -> 20 (-> v20.11.0)

▶ 示例:查看当前 Node.js 版本与状态

BASH
node -v
node -e "console.log(process.release.lts ? 'LTS: ' + process.release.lts : 'Current (non-LTS)')"
TEXT 📖 仅展示
v20.11.0
LTS: Iron

❓ 常见问题

Q Node.js 是一门新语言吗?
A 不是。Node.js 是 JavaScript 的运行时环境,它让 JavaScript 可以在服务器端运行,语言本身还是 JavaScript。
Q 为什么 Node.js 适合 I/O 密集型应用?
A Node.js 采用事件驱动和非阻塞 I/O 模型,单线程即可同时处理大量并发 I/O 请求,不会因为一个慢操作阻塞整个进程。
Q Node.js 不适合做什么?
A CPU 密集型任务,如视频编码、大量数学运算、图像处理等。长时间占用 CPU 会阻塞事件循环,导致所有请求排队等待。这类任务应交给 Worker Threads 或外部服务处理。
Q 必须先学 JavaScript 才能学 Node.js 吗?
A 是的。Node.js 本身不是新语言,它运行的就是 JavaScript。你需要掌握 JavaScript 基础语法、函数、对象、异步编程(Promise / async-await)后才能有效使用 Node.js。
Q Node.js 和 Deno 有什么区别?
A Deno 也是 JavaScript/TypeScript 运行时,由 Node.js 原作者 Ryan Dahl 创建。主要区别:Deno 原生支持 TypeScript、使用 ES Modules 而非 CommonJS、有安全沙箱(默认禁止文件/网络访问)、无 package.json 和 node_modules、标准库内置格式化和测试工具。Deno 生态尚在成长中,Node.js 生态更成熟。
Q Node.js 是单线程的吗?
A JavaScript 代码在单线程中执行,但 Node.js 底层使用 libuv 线程池(默认 4 线程)处理文件 I/O、DNS 查询等操作,还支持 Worker Threads 处理 CPU 密集任务。
Q 学习 Node.js 需要安装什么?
A 只需安装 Node.js(自带 npm 包管理器)和一个代码编辑器(推荐 VS Code)。安装后在终端运行 node -v 验证即可。

📖 小节


📝 作业

  1. 安装 Node.js(推荐 LTS 版本),运行 node -v 确认安装成功,记录你的版本号和是否为 LTS
  2. 创建 hello.js 文件,使用 console.log 输出你的名字和 Node.js 版本号,运行并截图
  3. 编写脚本使用 process 对象输出以下信息:Node.js 版本、操作系统平台、当前工作目录、CPU 架构
  4. 使用 fs.readFile 非阻塞方式读取一个文本文件并输出内容,观察回调函数的执行顺序
  5. 对比 fs.readFileSync(阻塞)和 fs.readFile(非阻塞),在读取同一文件时分别在回调前后打印时间戳,说明两者的执行差异


7. 综合示例:系统信息读取脚本

以下脚本使用 Node.js 内置模块读取并输出系统信息,展示 Node.js 作为服务器端运行时的基本能力:

JAVASCRIPT
const os = require('os');
const fs = require('fs');
const path = require('path');

const sysInfo = {
  nodeVersion: process.version,
  platform: process.platform,
  arch: process.arch,
  hostname: os.hostname(),
  totalMemoryMB: Math.round(os.totalmem() / 1024 / 1024),
  freeMemoryMB: Math.round(os.freemem() / 1024 / 1024),
  cpuCores: os.cpus().length,
  cpuModel: os.cpus()[0].model,
  uptimeHours: (os.uptime() / 3600).toFixed(2),
  cwd: process.cwd(),
  homedir: os.homedir()
};

const output = JSON.stringify(sysInfo, null, 2);
console.log(output);

const filePath = path.join(os.homedir(), 'nodejs-sysinfo.txt');
fs.writeFile(filePath, output, 'utf8', (err) => {
  if (err) {
    console.error('Write failed:', err.message);
    return;
  }
  console.log('System info saved to:', filePath);
});

预期输出:

TEXT 📖 仅展示
{
  "nodeVersion": "v20.11.0",
  "platform": "win32",
  "arch": "x64",
  "hostname": "DESKTOP-ABC123",
  "totalMemoryMB": 16384,
  "freeMemoryMB": 8192,
  "cpuCores": 8,
  "cpuModel": "Intel(R) Core(TM) i7-12700K",
  "uptimeHours": "48.32",
  "cwd": "C:\\projects\\node-demo",
  "homedir": "C:\\Users\\Alice"
}
System info saved to: C:\Users\Alice\nodejs-sysinfo.txt

脚本展示了 Node.js 的三个核心能力:操作系统信息获取(os)、文件写入(fs)、路径处理(path),同时使用了非阻塞 I/O 写入文件——fs.writeFile 的回调在 console.log 之后执行,体现了事件驱动的特性。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏