一、核心能力解析
-
双模块化方案
- CommonJS (
require
):Node 早期标准,同步加载(示例中http
/fs
模块引入) - ES6 Modules (
import
):现代方案,异步加载(注释中强调其先进性) - 进化意义:
require
→import
是 Node 向浏览器规范靠拢的标志性升级
- CommonJS (
-
服务定位三要素
graph LR A[域名 localhost] --> B[IP 127.0.0.1] B --> C[端口 8080] C --> D[服务进程]
- 端口:服务入口(如 MySQL:3306,HTTP:80/443)
- 进程:资源分配单元(服务容器)
- 线程:执行单元(处理并发请求)
二、关键设计思想
-
轻量化定位
- 聚焦中小项目场景(对比 Java/PHP 重型框架)
- 单线程事件循环 → 高并发 I/O 处理能力
-
端口管理原则
端口类型 示例 使用建议 知名端口 80/443 避免占用 注册端口 3306 服务默认端口 动态端口 8080 开发首选 避坑指南: 1234
/8080
等常用端口需检测占用
三、代码映射网络架构
// 分层架构实现
const http = require("http"); // 网络层:TCP/IP协议封装
const fs = require("fs"); // 系统层:文件读写
const path = require("path"); // 工具层:路径处理
// 核心服务逻辑:将物理路径映射为网络资源
fs.readFile(path.join(__dirname, "public", "index.html"), (err, content) => {
res.end(content); // 文件内容 → HTTP响应体
});
关键洞察:
localhost:8080/style.css
→ 磁盘文件路径映射- 内容协商:
Content-Type
头决定资源解析方式(HTML/CSS/JS)
工程启示:Node.js 用 200 行代码揭示了 Web 服务的本质——通过端口映射,将文件系统转化为网络资源。理解端口-进程-线程的关系,是掌握后端开发的基石。
四、两种http模块化对比
这段代码是基于Node.js
实现的后端代码。Node.js
作为 JavaScript
的运行环境,让我们能够在命令行中运行 JavaScript
代码。在模块化方面,Node.js
早期采用的是CommonJS规范,使用 require
来实现模块导入;而 ES6 则带来了更为先进的 import
模块化方案。
const http = require('http');
const fs = require('fs'); // file system
const path = require('path'); // 路径模块 提供一些路径相关的方法
const server = http.createServer((req,res)=>{
// res.end('hello http server')
// http 基于请求响应的协议
if(req.method == 'GET' && req.url == '/'){
fs.readFile(path.join(__dirname,'public','index.html'),
(err,content)=>{
if(err){
res.writeHead(500); // 5XX 服务器错误
res.end('Server error');
return;
}
res.end('hello http server');
})
}
});
server.listen(8080);
可以看到页面实现的效果
现在让我们来看看
es6 module
更先进的mjs
import http from 'http';
const server = http.createServer((req,res)=>{
res.end('hello World')
})
server.listen(1314);
让我们看下这段代码实现的效果,发现效果跟使用require
关键字的作用相同,但是代码少了一大段❗
五、 创建静态的服务端口
// 引入 Node.js 的 http 模块,用于创建 HTTP 服务器
const http = require("http");
// 引入 Node.js 的 fs 模块,用于文件系统操作
const fs = require("fs"); // file system
// 引入 Node.js 的 path 模块,用于处理和转换文件路径
const path = require("path"); // 路径模块 提供一些路径相关的方法
// 创建一个 HTTP 服务器实例,传入请求处理函数
const server = http.createServer((req, res) => {
// 注释掉的代码,原本用于直接返回响应内容
// res.end('hello http server')
// 说明 HTTP 是基于请求 - 响应的协议
// http 基于请求响应的协议
// 解释路由的概念,Method 和 url 组合可以定位服务器端的资源
// 路由 Method + url 定位了服务器端的资源
// 强调路由的作用是为了获取资源
// 为了资源
// 判断请求方法是否为 GET,并且请求路径是根路径或 /index.html
if (req.method == "GET" && (req.url == "/" || req.url == "/index.html")) {
// 打印当前文件所在目录和要读取的 index.html 文件的完整路径
console.log(__dirname, path.join(__dirname, "public", "index.html"));
// 异步读取 public 目录下的 index.html 文件
fs.readFile(
path.join(__dirname, "public", "index.html"),
// 异步操作的回调函数,处理读取结果
// 异步 callback
(err, content) => {
// 前端开发通常更注重用户体验,后端开发更注重稳定性
// 前端体验为主
// 后端稳定为主
// 如果读取文件过程中出现错误
if (err) {
// 设置响应状态码为 500,表示服务器内部错误
res.writeHead(500); // 5XX 服务器错误
// 返回错误信息给客户端
res.end("Server error");
// 结束当前函数执行,避免后续代码继续执行
return;
}
// 说明响应内容不仅可以是 HTML,还可以是 CSS、JS、JPG 等格式
// 不只是html, css, js, jpg
// 设置响应状态码为 200,表示请求成功,并指定响应内容类型为 HTML
res.writeHead(200, {
"Content-Type": "text/html",
});
// 将读取到的文件内容作为响应返回给客户端
res.end(content);
}
);
}
// 说明这部分代码是后端路由,用于暴露服务器资源
// 后端路由, 暴露资源
// 举例说明 URL 的组成部分,包括协议、域名、端口、路径和查询字符串
//localhost:8080/style.css?a=1&b=2
// 协议 http:// localhost 域名 端口 /style.css path queryString
// 判断请求方法是否为 GET,并且请求路径是 /style.css
if (req.method == "GET" && req.url == "/style.css") {
// 异步读取 public 目录下的 style.css 文件
fs.readFile(path.join(__dirname, "public", "style.css"), (err, content) => {
// 如果读取文件过程中出现错误
if (err) {
// 设置响应状态码为 500,表示服务器内部错误
res.writeHead(500);
// 返回错误信息给客户端
res.end("Server error");
// 结束当前函数执行,避免后续代码继续执行
return;
}
// 设置响应状态码为 200,表示请求成功,并指定响应内容类型为 CSS
res.writeHead(200, { "Content-Type": "text/css" });
// 将读取到的文件内容作为响应返回给客户端
res.end(content);
});
// 结束当前请求处理,避免后续代码继续执行
return;
}
// 判断请求方法是否为 GET,并且请求路径是 /script.js
if (req.method == "GET" && req.url == "/script.js") {
// 异步读取 public 目录下的 script.js 文件
fs.readFile(path.join(__dirname, "public", "script.js"), (err, content) => {
// 如果读取文件过程中出现错误
if (err) {
// 设置响应状态码为 500,表示服务器内部错误
res.writeHead(500);
// 返回错误信息给客户端
res.end("Server error");
// 结束当前函数执行,避免后续代码继续执行
return;
}
// 设置响应状态码为 200,表示请求成功,并指定响应内容类型为 JavaScript
res.writeHead(200, { "Content-Type": "text/javascript" });
// 将读取到的文件内容作为响应返回给客户端
res.end(content);
});
// 结束当前请求处理,避免后续代码继续执行
return;
}
});
// 启动服务器,监听 8080 端口
server.listen(8080);
当我们在JS端使代码跑起来之后可以看到效果如下:
在一个静态网站项目中,服务器需要将
public
目录下的index.html
作为首页返回给用户。这段代码就可以部署在服务器上,当用户访问网站时,服务器就能正确返回首页内容。若index.html
文件缺失,服务器也会返回相应的错误信息,方便开发者排查问题。
六、 痛点切入:
面试中常问的 Cookie 和 LocalStorage 区别主要体现在以下几个方面:
- 存储容量:Cookie 每个大小通常受限制,一般为几 KB,浏览器对每个域名下的 Cookie 总大小也有限制;而 LocalStorage 容量通常较大,一般为 5MB 或更多 1 3 4 5。
- 生命周期:Cookie 可以设置过期时间,有会话 Cookie(浏览器关闭后自动删除)和持久性 Cookie(在指定过期时间前一直有效);LocalStorage 数据永久存储,除非用户手动清除或网站代码清除 1 4 5。
- 数据共享:Cookie 通过设置
domain
和path
可以实现不同页面之间的共享,但受同源策略限制;LocalStorage 存储在同源(相同协议、域名和端口)的所有窗口和标签页之间共享 1。 - 安全性:Cookie 在 HTTP 请求中自动发送到服务器,存在被窃取的风险,可以设置
HttpOnly
和Secure
属性增加安全性;LocalStorage 存储在客户端,相对较安全,不会在 HTTP 请求中自动发送到服务器,但仍然可能受到 XSS 攻击 1 4。 - 与服务器通信:Cookie 会在浏览器和服务器间来回传递,而 LocalStorage 仅在本地保存,不会自动把数据发给服务器 3 5。
- API 操作:LocalStorage 使用 Web Storage API,提供了
setItem
、getItem
、removeItem
等方法来操作数据;Cookie 通过document.cookie
属性进行操作,也可以使用辅助函数设置,操作相对复杂 1 4。 - 应用场景:Cookie 主要用于在客户端和服务器之间传递数据,或者存储少量的用户会话信息,如用户身份验证、登录状态等;LocalStorage 适用于大容量数据的存储和持久化需求,比如保存用户偏好设置、离线缓存数据等 1 2。
总体而言,Cookie 更适合处理需要与服务器交互的少量数据,而 LocalStorage 更适合本地大容量数据的持久化存储。
七、核心内容架构
Part 1:前端存储体系剖析
# 🌐 前端四大存储方案
1. **Cookie**
- 核心特性:4KB限制、自动携带在HTTP头
- 应用场景:登录态Token、购物车ID存储
- 安全风险:XSS攻击与`HttpOnly`解决方案
2. **Web Storage**
- `localStorage`:持久化存储(如用户主题配置)
- `sessionStorage`:会话级存储(表单草稿临时保存)
- 对比:5MB容量 vs Cookie的4KB
3. **IndexedDB**
- 前端NoSQL数据库:支持事务、索引查询
- 适用场景:离线应用(如PWA的本地数据缓存)
Part 2:Node.js服务端存储实战
### ⚙️ 手写静态资源服务器
```javascript
// 关键代码:路由映射+文件读取
if (req.method === "GET" && req.url === "/style.css") {
fs.readFile("public/style.css", (err, content) => {
res.writeHead(200, { "Content-Type": "text/css" });
res.end(content); // 返回CSS文件内容
});
}
- 三大核心模块
http
创建服务 +fs
读取文件 +path
解析路径 - 性能优化:
createReadStream()
流式传输大文件(对比readFile
内存占用)
**Part 3:前后端存储协作模式**
```markdown
### 🔗 数据流动实战案例
| 技术 | 前端角色 | 后端角色 |
|---------------|------------------|------------------|
| **Cookie** | 读取`document.cookie` | Set-Cookie响应头 |
| **LocalStorage| 长期存储用户配置 | 无需感知 |
| **MySQL** | 发起API请求 | 持久化核心数据 |
八、总结升华
- 核心观点:
“存储是数据生命周期的起点,前端需根据时效性/安全性选择方案,后端需保证资源稳定交付。”
“从Cookie到IndexedDB,是前端从简单到复杂的存储能力进化;
从readFile
到流处理,是后端对性能边界的不断突破。”