配好了环境,我们终于可以开始编写第一个 Node.js 程序了。这一节会从头开始创建一个最简单的应用,并演示三种常用的运行和调试方式。即便你之前对其他语言已有丰富经验,了解 Node.js 的原生输出和调试机制,也能在后面的开发中少走弯路。
1. 编写第一个脚本
新建一个项目目录,并在其中创建一个 index.js 文件:
// index.js
const now = new Date().toISOString();
const message = `Hello, Node.js! 现在的时间是 ${now}`;
console.log(message);
// 尝试读取系统信息
const os = require('os');
console.log(`运行平台: ${os.platform()}, CPU 核心数: ${os.cpus().length}`);
// 模拟异步操作
setTimeout(() => {
console.log('3 秒后的异步问候');
}, 3000);
这个脚本做了四件典型的事情:使用 ES6 模板字符串、调用 os 模块获取系统信息、通过 console.log 输出到终端、并用 setTimeout 演示异步执行。
2. 终端运行
在项目目录下打开终端,执行:
node index.js
你会立即看到类似的输出:
Hello, Node.js! 现在的时间是 2025-06-15T08:22:10.345Z
运行平台: darwin, CPU 核心数: 10
三秒之后,才会追加输出:
3 秒后的异步问候
然后程序自动退出。如果需要在脚本运行过程中持续观察,可以添加服务器监听或使用 --watch 模式。
3. 自动重启与文件监听
在开发阶段,频繁手动执行 node index.js 会降低效率。Node.js(v18 起)内置了 --watch 选项,可以监听文件变化并自动重启进程:
node --watch index.js
修改并保存文件后,进程会被终止并重新启动,无需手动干预。对于早期版本,可以使用社区工具 nodemon 或 tsx 的 watch 功能。
4. 使用 Chrome DevTools 调试
Node.js 内嵌了 Chrome 浏览器的调试协议,这意味着可以直接用 DevTools 对服务端代码进行可视化调试。
启动脚本时加上 --inspect 选项:
node --inspect index.js
终端会输出类似信息:
Debugger listening on ws://127.0.0.1:9229/a7f8c...
此时打开 Chrome 浏览器,在地址栏输入 chrome://inspect,进入「Devices」页面。点击「Open dedicated DevTools for Node」链接,就会弹出调试窗口。你可以在源码面板中设置的断点处暂停,查看变量、调用栈,与调试前端代码完全一致。
如果希望脚本启动时立即暂停(以便从第一行开始调试),可以使用 --inspect-brk:
node --inspect-brk index.js
5. 使用 VS Code 内置调试器
日常开发中,更常见的调试方式是在编辑器里直接设置断点。以 VS Code 为例:
- 打开项目目录,在
index.js的行号左侧单击设置断点。 - 按
F5或点击侧边栏「运行和调试」图标,选择「Node.js」环境。 - VS Code 会自动生成
.vscode/launch.json配置文件。最简单的配置如下:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "启动程序",
"program": "${workspaceFolder}/index.js"
}
]
}
- 点击绿色三角箭头启动调试。程序运行到断点时会自动暂停,鼠标悬停可以查看变量值,控制台也可以随时输入表达式。
如果你使用的是 TypeScript,可以添加 "runtimeArgs": ["-r", "ts-node/register"] 或配置 tsx 来直接调试 TS 文件,无需预先编译。
6. 理解输出:不仅仅是 console.log
console.log 是最常用的输出方式,但 Node.js 的 console 模块还提供了更丰富的调试工具:
console.error():输出到 stderr,通常用于错误信息。console.warn():警告信息,同样输出到 stderr。console.table():以表格形式打印数组或对象,方便观察结构化数据。console.time()/console.timeEnd():测量代码片段的执行时间,对性能优化很有帮助。console.trace():打印当前的调用堆栈,方便跟踪代码执行路径。
const users = [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 }
];
console.table(users);
console.time('loop');
// 模拟慢操作
for (let i = 0; i < 1e6; i++) {}
console.timeEnd('loop');
这些方法在前端开发中本就常用,在服务端同样适用,无需额外学习成本。
7. 环境变量与进程退出码
第一个程序还有一个重要常识:Node.js 使用环境变量来传递配置,并且会向系统返回退出码。
console.log('当前环境:', process.env.NODE_ENV || 'development');
// 正常退出
process.exit(0);
退出码 0 表示成功,非 0 表示失败。在 CI/CD 脚本中,常通过退出码判断构建或测试是否通过。
小结
虽然只是第一个程序,但它覆盖了 Node.js 开发最基本的闭环:编写代码、运行脚本、观察输出、使用调试器定位问题。这些看似简单的操作,是所有复杂 Node.js 应用的起手式。随着项目逐渐复杂,这里介绍的终端运行、文件监听和两种调试方式会成为日常开发中最常用的技能,务必在真实项目中熟练运用。