TNF 学习笔记 (tnf dev)
1. 执行流程
cli.ts -> dev.ts -> server.ts -> bundler.ts -> bundler_mako.ts
1.1 命令执行路径
// 1. 执行 tnf dev
cli.ts -> buildContext() -> dev() -> createServer() -> createBundler() -> configDevServer() -> build()
1.2 核心流程
- 创建 Express 服务器 (8000端口)
- 创建 Mako 开发服务器 (8001端口)
- 配置代理和中间件
- 启动构建监听
2. 服务器架构
2.1 分层设计
Client Request
↓
Express Server (8000) // 代理层
↓
Mako Dev Server (8001) // 构建层
2.2 职责分工
Express 服务器 (代理层)
- 请求代理
- 通用中间件 (cors, compression, history)
- 插件系统支持
- 统一入口
Mako 服务器 (构建层)
- 资源构建
- 热更新
- 开发时优化
2.3 中间件功能
- CORS 中间件
app.use(cors({
origin: true,
methods: ['GET', 'HEAD', 'PUT', 'POST', 'PATCH', 'DELETE', 'OPTIONS'],
credentials: true,
}));
- 允许跨域请求
- 支持所有 HTTP 方法
- 允许携带认证信息
- 压缩中间件
app.use(compression());
- 压缩响应内容
- 减少传输大小
- 提高加载速度
- History 中间件
app.use(history({
index: '/',
}));
- 处理 SPA 路由
- 防止刷新 404
- 支持 HTML5 History API
3. 代理机制
3.1 HTTP 代理
opts.app.use(
proxy(`http://127.0.0.1:${hmrPort}`, {
proxyReqOptDecorator: function (proxyReqOpts: any) {
proxyReqOpts.agent = false;
return proxyReqOpts;
},
filter: function (req: any, res: any) {
return req.method == 'GET' || req.method == 'HEAD';
},
skipToNextHandlerFilter: function (proxyRes: any) {
return proxyRes.statusCode !== 200;
},
}),
);
特点:
- 只代理 GET 和 HEAD 请求
- 非 200 响应跳过代理
- 禁用 HTTP 代理代理
3.2 WebSocket 代理
const wsProxy = createProxyMiddleware({
target: `http://127.0.0.1:${hmrPort}`,
ws: true,
});
opts.app.use('/__/hmr-ws', wsProxy);
opts.server.on('upgrade', wsProxy!.upgrade);
功能:
- 支持 WebSocket 连接
- 处理热更新通信
- 自动升级协议
4. 请求流程示例
4.1 静态资源请求
Browser: GET http://localhost:8000/main.js
↓
Express: 代理到 http://localhost:8001/main.js
↓
Mako: 返回构建后的 main.js
4.2 WebSocket 热更新
Browser: WS ws://localhost:8000/__/hmr-ws
↓
Express: 升级连接并代理到 ws://localhost:8001/__/hmr-ws
↓
Mako: 建立 WebSocket 连接,发送热更新信息
5. 设计优势
-
关注点分离
- Express 处理通用 Web 服务器功能
- Mako 专注于构建和开发时优化
-
灵活性
- 可以添加任何中间件
- 可以通过插件系统扩展功能
- 可以控制请求的转发规则
-
统一管理
- 所有请求通过同一个入口
- 便于做统一的请求处理
- 便于添加通用功能
-
可扩展性
- 支持插件系统
- 易于添加新功能
- 便于维护和升级