📌 核心知识点:
服务器不仅要处理动态请求(如 /login ),还要能提供静态文件(HTML、CSS、JS、图片等)。我们将学会如何用 Node.js 原生方式服务这些“静态资源”。
🧱 什么是静态资源?
| 文件类型 | 示例路径 |
|---|---|
| HTML 页面 | /index.html |
| CSS 样式表 | /style.css |
| JavaScript 文件 | /app.js |
| 图片 | /logo.png, /bg.jpg |
| 字体、图标等 | /icon.svg |
👉 这些文件内容是“固定的”,不需要每次计算,直接读取并返回即可。
📁 先准备项目结构
修改你的项目目录如下:
my-web-app/
├── server.js ← 主服务器
├── public/ ← 所有静态文件放这里
│ ├── index.html
│ ├── style.css
│ ├── script.js
│ └── logo.png ← (可以随便放一张图片命名为此)
💡 public/ 是前端资源的标准存放文件夹名称。
✅ 步骤一:创建 public/index.html
<!-- public/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>我的 Node.js 网站</title>
<link rel="stylesheet" href="/style.css">
</head>
<body>
<h1>🎉 欢迎来到我的网站</h1>
<p class="intro">这是由纯 Node.js 提供的页面,连样式都是它给的!</p>
<img src="/logo.png" alt="Logo" width="200">
<button onclick="sayHello()">点我试试</button>
<script src="/script.js"></script>
</body>
</html>
✅ 步骤二:创建 public/style.css
/* public/style.css */
body {
font-family: Arial, sans-serif;
text-align: center;
margin-top: 50px;
background-color: #f0f8ff;
}
h1 {
color: #2e8b57;
}
.intro {
color: #4682b4;
font-size: 1.2em;
}
button {
padding: 10px 20px;
font-size: 1em;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
✅ 步骤三:创建 public/script.js
// public/script.js
function sayHello() {
alert('Hello from Node.js server!');
}
✅ 步骤四:更新 server.js 支持静态文件
我们现在要实现:
- 如果请求的是
/style.css→ 返回 CSS 文件 - 如果是
/script.js→ 返回 JS 文件 - 是
/logo.png→ 返回图片(二进制)
🔧 关键点:根据文件扩展名设置正确的 Content-Type
const http = require('http');
const fs = require('fs');
const path = require('path');
const url = require('url');
// MIME 类型映射(告诉浏览器文件是什么格式)
const mimeTypes = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'application/javascript',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.gif': 'image/gif',
'.json': 'application/json'
};
const server = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url);
let pathname = parsedUrl.pathname;
// 默认首页
if (pathname === '/') {
pathname = '/index.html';
}
// 构造本地文件路径
const filePath = path.join(__dirname, 'public', pathname);
// 获取文件扩展名
const extname = path.extname(filePath).toLowerCase();
const contentType = mimeTypes[extname] || 'application/octet-stream'; // 默认为二进制流
// 尝试读取文件
fs.readFile(filePath, (err, content) => {
if (err) {
if (err.code === 'ENOENT') {
// 文件不存在
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 - 页面未找到');
} else {
// 其他错误(如权限问题)
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('500 - 服务器内部错误');
}
} else {
// 成功读取文件
res.writeHead(200, { 'Content-Type': contentType + '; charset=utf-8' });
res.end(content);
}
});
});
const PORT = 3000;
server.listen(PORT, () => {
console.log(`✅ 静态服务器已启动:http://localhost:${PORT}`);
});
🏃♂️ 测试步骤
- 确保所有文件已创建
- 启动服务器:
node server.js
- 打开浏览器访问:
👉 http://localhost:3000
你应该看到:
- 美观的标题和文字
- 背景颜色
- 显示图片
- 可点击按钮弹出提示
🎉 恭喜!你已经用原生 Node.js 实现了一个能提供完整网页体验的服务器!
✅ 本课小结一句话:
使用 fs.readFile + path.join + MIME type 映射,可以让 Node.js 服务器正确返回 HTML、CSS、JS、图片等静态资源,打造真正可用的网站。
🚨 注意事项
- 生产环境不会用这种方式服务静态文件(性能不够好),而是用 Nginx 或 Express 的
express.static()。 - 但我们通过手动实现,彻底理解了“静态资源服务”的原理,这非常重要!
📬 下一课预告:
第 15 课:实战项目② —— 构建一个“天气查询”API 接口!
我们将结合前面所学,做一个真实的 API:
- 接收城市名
- 返回模拟天气数据
- 支持 JSON 格式