在前端开发越来越追求全栈能力的今天,Node.js 凭借其轻量高效的特点,成为众多开发者的心头好。它让 JavaScript 不仅能运行在浏览器中,还能在服务器端大展拳脚。今天,我们就一起从零开始,走进 Node.js 的世界,亲手搭建一个简易的 HTTP 服务器!
基础知识
1. Node.js 基础
-
核心模块:
http:创建 HTTP 服务器(处理请求和响应)。fs:文件系统操作(读取文件、写入文件等)。path:处理文件路径(避免不同系统路径分隔符差异)。
-
模块化方案:
- CommonJS(老方案):使用
require('模块名')引入模块(如const http = require('http'))。 - ES6 Modules(新方案):使用
import 模块 from '模块名'(需在package.json中添加"type": "module"或使用.mjs后缀)。
- CommonJS(老方案):使用
2. HTTP 服务器
-
创建服务器:
const server = http.createServer((req, res) => { // 处理请求和响应 }); server.listen(1234); // 监听 1234 端口 -
请求与响应:
-
req(请求对象):包含method(请求方法)、url(请求路径)等信息。 -
res(响应对象):res.writeHead(statusCode, headers):设置响应状态码和头部。res.end(content):结束响应并返回内容。
-
3. 路由基础
-
路径匹配:根据
req.url处理不同请求(如首页、CSS、JS 文件)。if (req.method === 'GET' && req.url === '/') { // 处理首页请求 } else if (req.url === '/index.html') { // 处理 HTML 请求 }else if (req.url === '/style.css') { // 处理 CSS 请求 }else if (req.url === '/script.js') { // 处理 javaScript 请求
4. 文件系统操作
- 异步读取文件:
准备几个文件:
fs.readFile(path.join(__dirname, 'public', 'index.html'), (err, content) => {
if (err) {
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content);
});
path.join():拼接路径(如__dirname表示项目根路径/public/index.html)。Content-Type:根据文件类型设置响应头(如text/html、text/css)。
5. 端口与网络基础
- 端口作用:区分同一设备上的不同服务(如
3306对应 MySQL,80对应 HTTP)。 - URL 结构:
协议://域名:端口/路径(如http://localhost:1234/style.css)。 - 本地开发:使用
localhost(域名)或127.0.0.1(IP 地址)访问本地服务。
6. 错误处理
- 服务器错误:
- 500 状态码:服务器内部错误(如文件读取失败)。
- 404 状态码:资源未找到(代码中未处理,需自行添加)。
7. 现代模块化实践
- ES6 Modules 启用方式:
- 使用
.mjs后缀文件。
- 使用
注意:node 最新版本22 支持
实战
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./style.css">
<!-- 记得引入css文件 -->
</head>
<body>
<h1>Cookie</h1>
<!-- 记得引入js文件 -->
<script src="./script.js"></script>
</body>
</html>
*{
margin: 0;
padding: 0;
}
body{
background-color: green;
width: 100vw;
height: 100vh;
}
console.log("hhhhh")
const http = require('http'); // 引入核心模块
const fs = require('fs'); // 文件系统模块 file system
const path = require('path'); // 路径模块 path
const server = http.createServer((req, res) => {
if(req.method=='GET' && (req.url=='/' || req.url=='/index.html')){ // 首页
fs.readFile(path.join(__dirname,'public','index.html'),(err,content)=>{
if(err){
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'}); // 响应头
res.end(content); // 响应体
})
}
// http://localhost:1234/style.css
if(req.method=='GET'&& req.url=='/style.css'){
fs.readFile(path.join(__dirname,'public','style.css'),(err,content)=>{
if(err){
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200,{'Content-Type':'text/css;charset=utf-8'});
res.end(content);
})
}
if(req.method=='GET'&& req.url=='/script.js'){
fs.readFile(path.join(__dirname,'public','script.js'),(err,content)=>{
if(err){
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200,{'Content-Type':'text/javascript;charset=utf-8'});
res.end(content);
})
}
});
server.listen(1234); // 监听端口
如果我把路径的文件名故意写错,看看会发生什么
//改成style1.css
fs.readFile(path.join(__dirname,'public','style1.css'),(err,content)=>{
if(err){
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200,{'Content-Type':'text/css;charset=utf-8'});
res.end(content);
})
报错500
常见问题与避坑指南
- 端口占用:如果 1234 端口被占用,可以换一个端口(如 8080 )。
- 响应头设置错误:例如返回 HTML 却设置 Content-Type: 'text/plain' ,会导致浏览器无法正确解析内容。
- 文件路径错误:使用 path.join() 拼接路径,确保兼容性,同时检查文件是否存在。