第一个 Node.js 程序
本教程共 76 篇 · 第 4 篇 · 更新于 2026-07-25 · 约 6 分钟阅读
4. 第一个 Node.js 程序
本节目标:写一个能跑的 HTTP 服务器,玩转 REPL 交互环境,读取命令行参数,还有开发时省事的
node --watch。
你好,HTTP 服务器
别的语言入门先打印 “Hello World”,Node.js 咱们直接点,搭一个 HTTP 服务器。
在项目目录下建一个 server.js:
import { createServer } from 'node:http';
const hostname = '127.0.0.1';
const port = 3000;
createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World');
}).listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Warning上面代码用的是 ESM(
import语法)。如果你直接node server.js报错,说不能用import,那是因为 Node.js 默认按 CommonJS 解析。解决办法:把文件重命名为server.mjs,或者在同级目录建一个package.json写上{ "type": "module" }。本教程全程 ESM 优先,后面默认你配好了模块类型。
运行:
node server.js
看到 Server running at http://127.0.0.1:3000/ 后,打开浏览器访问这个地址。一个活的服务器就起来了。
代码拆解:
import { createServer } from 'node:http'—— 加载内置 http 模块。node:前缀表示这是 Node.js 内置模块,自 v16 起推荐这么写,能避免和 npm 包重名。createServer(callback)—— 创建一个 HTTP 服务器,每次有请求进来就执行回调。req(请求对象)和res(响应对象)—— 分别携带了客户端发来的信息和你要回传的内容。res.end('Hello World')—— 结束响应,把文字发回浏览器。listen(port, hostname, callback)—— 让服务器开始监听端口,启动成功后执行最后的回调。
Tip写
127.0.0.1意味着只有本机能访问。如果你希望局域网里的手机或其他电脑也能访问,把 hostname 改成'0.0.0.0'。但注意,公网部署时别裸奔,前面要加 Nginx 或防火墙。
REPL:边想边试
REPL 全称 Read-Eval-Print Loop,就是交互式命令行。你不用建文件,直接敲 node 进 REPL:
$ node
> 1 + 1
2
> const arr = [1, 2, 3]
undefined
> arr.map(x => x * 2)
[ 2, 4, 6 ]
>
输入代码,立刻看到结果。适合验证表达式、试 API、算点数学题。
几个实用技巧:
- 按 上箭头 翻历史记录,不用重写。
- 输入
_获取上一个表达式的结果。 - 多行代码(比如函数定义)直接回车,REPL 会自动识别并进入续行模式,提示符变成
...。 .help查看所有点命令,.exit退出,.save session.js把本次输入保存到文件。
NoteREPL 里的变量是全局的,跟写在文件里不完全一样。有些异步行为在 REPL 里的表现也可能有细微差别。验证核心逻辑可以,但正式功能还是写到文件里跑。
命令行参数
你的程序可能需要从命令行接收输入,比如指定端口号、配置文件路径。Node.js 通过 process.argv 暴露所有参数。
建一个 args.js:
console.log('完整参数列表:', process.argv);
console.log('脚本路径:', process.argv[1]);
console.log('用户传入的参数:', process.argv.slice(2));
运行:
node args.js hello world --port=8080
输出:
完整参数列表: [
'/usr/local/bin/node',
'/home/you/args.js',
'hello',
'world',
'--port=8080'
]
用户传入的参数: [ 'hello', 'world', '--port=8080' ]
process.argv 是个数组:
- 第 0 项是
node可执行文件的路径 - 第 1 项是你运行的脚本路径
- 从第 2 项开始才是你真正传的参数
自己解析字符串太麻烦,生产环境一般用专门的 CLI 解析库,比如 minimist 或 commander。但底层原理就是 process.argv,你得先知道。
Tip环境变量用
process.env读取。比如NODE_ENV=production node app.js,代码里process.env.NODE_ENV就是'production'。这是区分开发/生产环境最常用的手段。
开发利器:node —watch
以前改一行代码就要手动 Ctrl+C 再重新 node server.js,很烦。从 Node.js v18 开始,内置了 --watch 模式,文件一改自动重启。
node --watch server.js
终端会显示:
Server running at http://127.0.0.1:3000/
Completed running 'server.js'
你修改 server.js 保存后,它会自动重启并打印 Restarting 'server.js'。
Note
node --watch自 v18 起可用,v24 LTS 已完全稳定。比第三方的nodemon省事的地方在于不用额外装包,开箱即用。但nodemon配置更灵活(比如忽略某些文件),复杂场景还是用得着。
你也可以同时 watch 多个文件或目录:
node --watch-path=./src --watch-path=./config server.js
如果只想检查语法不执行:
node --check server.js
这在提交代码前快速扫一遍语法错误很方便。
在终端输出点花样
console.log 你肯定熟悉,但 Node.js 的 console 模块比浏览器里丰富得多。
格式化输出:
const user = { name: 'Tom', age: 25 };
console.log('User: %o', user); // %o 格式化对象
console.log('Count: %d', 42); // %d 数字
console.log('Hello, %s', 'world'); // %s 字符串
计时:
console.time('query');
// ... 执行某些操作
console.timeEnd('query'); // 输出: query: 23.456ms
追踪调用栈:
function inner() {
console.trace('这里被调用了');
}
function outer() {
inner();
}
outer();
自 v22 起,还可以用 util.styleText 给终端文字上色:
import { styleText } from 'node:util';
console.log(styleText(['red', 'bold'], '错误!'));
console.log(styleText('green', '一切正常'));
Tip颜色输出在 CI 日志里有时会变成乱码。写库或者 CLI 工具时,建议检测
process.stdout.isTTY,非终端环境不输出颜色,或者给用户一个--no-color选项。
动手练一下
- 把上面的 HTTP 服务器跑起来,试着把
text/plain改成text/html,返回一段带标签的 HTML。 - 用 REPL 算一下
Array.from({ length: 5 }, (_, i) => i * i),看看结果是什么。 - 写一个
greet.js,接收命令行参数作为名字,输出Hello, 名字!。没传名字时默认输出Hello, stranger!。 - 用
node --watch启动服务器,改代码看会不会自动重启。
下一章我们拆开 Node.js 的引擎盖,看看里面是怎么转的。