Node.js 简介

用 http 模块搭建 Web 服务器

掌握 Node.js http 模块创建服务器、处理请求与响应的方法,理解请求、响应、状态码与简单路由。

🎯 引言

学完这篇文章,你能用 Node.js 内置的 http 模块启动一个 Web 服务器,根据访问地址返回不同内容,还能写出一个返回 JSON 数据的接口,迈出后端开发的关键一步。


🧱 先懂客户端与服务器

Web 的世界里有两种角色:客户端(比如浏览器)负责发请求,服务器负责接收请求并返回响应。

就像去餐厅点餐:你告诉服务员要吃什么,这是“请求”;厨房做好后端上来,这是“响应”。浏览器访问一个网址,背后就是这一套流程。Node.js 可以让我们的电脑扮演服务器的角色。


🛠 第一个服务器

创建 server.js,写入下面的代码:

server.js
import http from 'node:http';

// 创建服务器:每次有请求进来,这个回调函数就会执行
const server = http.createServer((req, res) => {
    res.end('Hello Node.js Server');
});

// 监听 3000 端口,启动服务
server.listen(3000, () => {
    console.log('服务器已启动:http://localhost:3000');
});

逐行理解:

  • createServer 创建一个服务器实例,回调里的 req 是请求对象(客户端发来的信息),res 是响应对象(我们回给客户端的内容)。
  • res.end() 结束响应并把内容发给客户端,每个请求都必须调用它,否则浏览器会一直转圈等待。
  • listen(3000) 让服务器监听 3000 端口,端口可以理解为这台电脑上的“服务窗口编号”。

运行 node server.js,浏览器打开 http://localhost:3000,就能看到返回的文字了。


🪤 中文乱码问题

把上面的返回内容改成中文试试:res.end('你好,世界')。浏览器很可能显示一堆乱码。

原因是浏览器不知道我们发的是什么编码。用 setHeader 明确告诉它:

server.js
const server = http.createServer((req, res) => {
    res.setHeader('Content-Type', 'text/plain; charset=utf-8');
    res.end('你好,世界');
});
返回中文却不设置 charset=utf-8 是初学者的高频踩坑点。记住:Content-Type 告诉浏览器“内容的类型和编码”,设置要在 res.end() 之前。

🛠 简单路由

真实的服务器要根据访问地址返回不同内容,这就是路由。用 req.urlreq.method 判断即可:

server.js
import http from 'node:http';

const server = http.createServer((req, res) => {
    res.setHeader('Content-Type', 'text/plain; charset=utf-8');

    if (req.url === '/' && req.method === 'GET') {
        res.end('欢迎来到首页');
    } else if (req.url === '/about' && req.method === 'GET') {
        res.end('这是关于页面');
    } else {
        // 没匹配到的地址,返回 404
        res.statusCode = 404;
        res.end('页面不存在');
    }
});

server.listen(3000);

现在访问 //about 会看到不同内容,访问其他地址会收到 404。这就是路由的朴素实现:Express 等框架本质上就是把这套判断做得更优雅,后面的课程会专门学习。


🛠 返回 JSON 接口

前后端分离项目里,服务器经常返回 JSON 数据。把 Content-Type 换成 application/json,内容用 JSON.stringify 转换:

api.js
import http from 'node:http';

const server = http.createServer((req, res) => {
    if (req.url === '/api/user') {
        const user = { name: '小明', age: 18 };

        res.setHeader('Content-Type', 'application/json; charset=utf-8');
        res.end(JSON.stringify(user));
    }
});

server.listen(3000);

浏览器访问 http://localhost:3000/api/user,就能看到 {"name":"小明","age":18}。这就是后端接口的雏形,前端用 Axios 请求它就能拿到数据。


🧾 常见状态码速查

状态码含义常见场景
200成功正常返回内容
404未找到地址不存在
500服务器内部错误代码抛异常了

设置方式是 res.statusCode = 404,记得要在 res.end() 之前设置。


🧾 小节总结

  • 客户端发请求,服务器返回响应;Node.js 用 http 模块扮演服务器角色。
  • http.createServer 的回调处理每个请求,res.end() 必须调用,listen 指定端口。
  • 返回中文要设置 Content-Type: text/plain; charset=utf-8,否则浏览器会乱码。
  • 通过 req.urlreq.method 可以实现简单路由,未匹配的地址返回 404。
  • 返回 JSON 接口:application/jsonJSON.stringify

❓ 知识问答

Q1:res.write 和 res.end 有什么区别?

res.write 可以分多次发送内容,res.end 发送最后的内容并结束响应。简单场景只用 res.end 就够了,每个请求必须有一个 end 收尾。

Q2:改了代码为什么浏览器里不生效?

服务器代码运行在 Node 进程里,改完需要在终端按 Ctrl+C 停止,再重新执行 node server.js。开发时也可以用 node --watch server.js,文件保存后自动重启。

Q3:启动时报端口被占用怎么办?

说明 3000 端口已经被其他程序用了。要么关掉占用它的程序,要么把 listen 的端口换成 3001 等其他值。

Q4:http 模块和 Express 是什么关系?

Express 是基于 http 模块封装的框架,把路由、中间件等常用功能做得更方便。先懂 http 模块的原理,再学 Express 会觉得水到渠成。


🧪 小练习

在服务器上加一个 /api/time 接口,返回当前时间的 JSON,格式为 { "time": "2024-01-01 12:00:00" }

server.js
import http from 'node:http';

const server = http.createServer((req, res) => {
    // 请在这里编写代码
});

server.listen(3000);

🎉 恭喜你已经能独立搭建 Web 服务器了!下一篇我们深入 Node.js 的心脏:事件循环与异步机制。