修改
This commit is contained in:
379
.qoder/repowiki/zh/content/开发指南/代码规范与质量.md
Normal file
379
.qoder/repowiki/zh/content/开发指南/代码规范与质量.md
Normal file
@@ -0,0 +1,379 @@
|
||||
# 代码规范与质量
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [.eslintrc.cjs](file://.eslintrc.cjs)
|
||||
- [.eslintrc.json(客户端)](file://client/.eslintrc.json)
|
||||
- [.editorconfig](file://.editorconfig)
|
||||
- [package.json(服务端)](file://package.json)
|
||||
- [package.json(客户端)](file://client/package.json)
|
||||
- [tsconfig.json](file://tsconfig.json)
|
||||
- [tsconfig.lint.json](file://tsconfig.lint.json)
|
||||
- [jest.config.js](file://jest.config.js)
|
||||
- [src/index.ts](file://src/index.ts)
|
||||
- [src/server.ts](file://src/server.ts)
|
||||
- [client/src/peer.js](file://client/src/peer.js)
|
||||
- [client/src/sender.js](file://client/src/sender.js)
|
||||
- [test/websockethandler.test.ts](file://test/websockethandler.test.ts)
|
||||
- [client/test/inputremoting.test.js](file://client/test/inputremoting.test.js)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. 引言
|
||||
2. 项目结构
|
||||
3. 核心组件
|
||||
4. 架构总览
|
||||
5. 详细组件分析
|
||||
6. 依赖分析
|
||||
7. 性能考虑
|
||||
8. 故障排查指南
|
||||
9. 结论
|
||||
10. 附录
|
||||
|
||||
## 引言
|
||||
本指南面向视频服务器项目的开发者与维护者,系统性阐述代码规范与质量控制策略,覆盖以下方面:
|
||||
- ESLint 规则与 TypeScript/JavaScript 的差异化配置
|
||||
- 代码格式化工具与自动格式化设置(EditorConfig)
|
||||
- 命名约定与变量命名最佳实践
|
||||
- 注释规范与文档编写标准
|
||||
- 代码审查流程与质量检查要点
|
||||
- 常见问题识别与修复方法
|
||||
- 自动化质量检查工具的配置与使用
|
||||
|
||||
## 项目结构
|
||||
该项目采用前后端分离的多包结构:
|
||||
- 服务端(TypeScript):src、test、配置文件(tsconfig、eslint、jest)
|
||||
- 客户端(前端 JS/TS):client 目录下包含公共资源、源码与测试
|
||||
- 全局脚本与工具:根目录 package.json 提供 lint、test、build 等命令
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "服务端"
|
||||
TS["TypeScript 源码<br/>src/*.ts"]
|
||||
TSTest["测试<br/>test/*.test.ts"]
|
||||
ESLintCJS[".eslintrc.cjs<br/>TypeScript 规则"]
|
||||
JestCfg["jest.config.js<br/>测试配置"]
|
||||
TSConf["tsconfig.json<br/>编译配置"]
|
||||
LintTSConf["tsconfig.lint.json<br/>ESLint 专用"]
|
||||
end
|
||||
subgraph "客户端"
|
||||
JS["前端源码<br/>client/src/*.js"]
|
||||
JSTest["前端测试<br/>client/test/*.test.js"]
|
||||
ESLintJSON[".eslintrc.json<br/>浏览器环境规则"]
|
||||
end
|
||||
RootPkg["根 package.json<br/>脚本与依赖"]
|
||||
RootPkg --> ESLintCJS
|
||||
RootPkg --> JestCfg
|
||||
RootPkg --> TSConf
|
||||
RootPkg --> LintTSConf
|
||||
TS --> ESLintCJS
|
||||
TSTest --> JestCfg
|
||||
JS --> ESLintJSON
|
||||
JSTest --> JestCfg
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [.eslintrc.cjs](file://.eslintrc.cjs)
|
||||
- [.eslintrc.json(客户端)](file://client/.eslintrc.json)
|
||||
- [jest.config.js](file://jest.config.js)
|
||||
- [tsconfig.json](file://tsconfig.json)
|
||||
- [tsconfig.lint.json](file://tsconfig.lint.json)
|
||||
- [package.json(服务端)](file://package.json)
|
||||
- [package.json(客户端)](file://client/package.json)
|
||||
|
||||
章节来源
|
||||
- [package.json(服务端):1-60](file://package.json#L1-L60)
|
||||
- [package.json(客户端):1-19](file://client/package.json#L1-L19)
|
||||
|
||||
## 核心组件
|
||||
- 代码检查(ESLint)
|
||||
- 服务端:基于 TypeScript ESLint 插件,启用推荐规则集,解析器为 TypeScript,使用独立的 tsconfig.lint.json 以避免 sourceMap 影响性能。
|
||||
- 客户端:基于 eslint:recommended 与 jest 插件,针对浏览器与 ES6 环境,强制分号与禁止多余分号。
|
||||
- 测试框架(Jest)
|
||||
- 收集覆盖率、使用 ts-jest 转换 TS/TSX,测试环境为 node;客户端测试使用 jsdom 环境。
|
||||
- 编辑器配置(EditorConfig)
|
||||
- 统一缩进风格、换行符、结尾换行与尾随空白处理。
|
||||
|
||||
章节来源
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [.eslintrc.json(客户端):1-23](file://client/.eslintrc.json#L1-L23)
|
||||
- [tsconfig.lint.json:1-12](file://tsconfig.lint.json#L1-L12)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [.editorconfig:1-20](file://.editorconfig#L1-L20)
|
||||
|
||||
## 架构总览
|
||||
整体质量控制链路如下:
|
||||
- 开发阶段:编辑器读取 EditorConfig 进行基础格式化;保存时由 IDE 或插件执行 ESLint 校验。
|
||||
- CI/本地:通过 npm/yarn scripts 执行 lint 与 test;ESLint 针对 src 与 test;Jest 覆盖服务端与客户端测试。
|
||||
- 发布前:构建产物生成于 build 目录,确保 TypeScript 编译无误。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Dev as "开发者"
|
||||
participant IDE as "编辑器/IDE"
|
||||
participant ESL as "ESLint"
|
||||
participant Jest as "Jest"
|
||||
participant TS as "TypeScript 编译器"
|
||||
Dev->>IDE : 保存文件
|
||||
IDE->>ESL : 触发语法与风格检查
|
||||
ESL-->>Dev : 报告规则违规
|
||||
Dev->>Jest : 运行测试
|
||||
Jest-->>Dev : 输出测试结果与覆盖率
|
||||
Dev->>TS : 执行构建
|
||||
TS-->>Dev : 生成构建产物
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [package.json(服务端):5-12](file://package.json#L5-L12)
|
||||
- [jest.config.js:174-176](file://jest.config.js#L174-L176)
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### ESLint 配置与规则
|
||||
- 服务端(TypeScript)
|
||||
- 环境:node、jest
|
||||
- 继承:eslint:recommended、@typescript-eslint/eslint-recommended、@typescript-eslint/recommended、jest/recommended
|
||||
- 解析器:@typescript-eslint/parser
|
||||
- 解析选项:module、project 指向 tsconfig.lint.json
|
||||
- 关键规则:
|
||||
- 禁止 var 的 require 使用
|
||||
- any 类型放宽
|
||||
- 分号:强制;多余分号:报错
|
||||
- 客户端(JavaScript)
|
||||
- 环境:browser、es6、jest
|
||||
- 继承:eslint:recommended、jest/recommended
|
||||
- 规则:强制分号、禁止多余分号
|
||||
|
||||
章节来源
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [.eslintrc.json(客户端):1-23](file://client/.eslintrc.json#L1-L23)
|
||||
|
||||
### 代码格式化与 EditorConfig
|
||||
- 统一规则:
|
||||
- 缩进:空格
|
||||
- 行结束符:LF
|
||||
- 缩进大小:2
|
||||
- 文件末尾插入换行
|
||||
- 字符集:UTF-8
|
||||
- 去除行尾空白
|
||||
- 适用范围:ts、js、json、html
|
||||
|
||||
章节来源
|
||||
- [.editorconfig:10-20](file://.editorconfig#L10-L20)
|
||||
|
||||
### TypeScript 与 JavaScript 的差异化规则
|
||||
- TypeScript
|
||||
- 使用 @typescript-eslint 推荐规则,强调类型安全与结构一致性
|
||||
- 通过 tsconfig.lint.json 优化 ESLint 性能(关闭 sourceMap)
|
||||
- JavaScript(客户端)
|
||||
- 面向浏览器与 ES6,强调语义正确性与简洁性
|
||||
- 保留分号一致性,避免多余分号
|
||||
|
||||
章节来源
|
||||
- [.eslintrc.cjs:6-16](file://.eslintrc.cjs#L6-L16)
|
||||
- [.eslintrc.json(客户端):3-22](file://client/.eslintrc.json#L3-L22)
|
||||
- [tsconfig.lint.json:4-11](file://tsconfig.lint.json#L4-L11)
|
||||
|
||||
### 命名约定与变量命名最佳实践
|
||||
- 类型与模块
|
||||
- 类名:帕斯卡命名(如 RenderStreaming)
|
||||
- 接口/类型:帕斯卡命名(如 Options)
|
||||
- 模块导出:默认导出或具名导出保持一致,避免混用
|
||||
- 变量与函数
|
||||
- 变量:小驼峰命名(如 connectionId、options)
|
||||
- 函数:动词短语或小驼峰(如 getIPAddress、createServer)
|
||||
- 常量:全大写蛇形(如 MAX_RETRIES)
|
||||
- 文件与路径
|
||||
- 源文件:按功能分层组织(如 src/class、src/signaling)
|
||||
- 测试文件:与被测模块同名或以 .test 后缀
|
||||
- 前端输入设备类
|
||||
- 类名:帕斯卡命名(如 Sender、Observer)
|
||||
- 属性与方法:小驼峰(如 devices、onEvent)
|
||||
|
||||
章节来源
|
||||
- [src/index.ts:13-106](file://src/index.ts#L13-L106)
|
||||
- [src/server.ts:14-89](file://src/server.ts#L14-L89)
|
||||
- [client/src/peer.js:3-188](file://client/src/peer.js#L3-L188)
|
||||
- [client/src/sender.js:14-209](file://client/src/sender.js#L14-L209)
|
||||
|
||||
### 注释规范与文档编写标准
|
||||
- 文件级注释
|
||||
- 说明模块职责、入口点与关键行为
|
||||
- 函数/方法注释
|
||||
- 参数与返回值:使用 JSDoc 风格(如 @param、@returns)
|
||||
- 复杂逻辑:简述目的与边界条件
|
||||
- 类注释
|
||||
- 类的用途、构造参数、事件与生命周期
|
||||
- 前端类示例
|
||||
- 类定义处与关键方法处提供注释,描述事件派发与状态变化
|
||||
|
||||
章节来源
|
||||
- [client/src/sender.js:107-112](file://client/src/sender.js#L107-L112)
|
||||
- [client/src/sender.js:191-201](file://client/src/sender.js#L191-L201)
|
||||
|
||||
### 代码审查流程与质量检查要点
|
||||
- 代码检查
|
||||
- 本地:npm run lint(服务端)与 npm run lint(客户端)
|
||||
- CI:集成 lint 与 test 步骤,确保通过后再合并
|
||||
- 测试覆盖率
|
||||
- Jest 启用覆盖率收集,建议设定最小阈值
|
||||
- 审查清单
|
||||
- 类型安全:TS 是否启用严格模式相关规则
|
||||
- 命名一致性:是否遵循命名约定
|
||||
- 注释完整性:关键函数/类是否具备必要注释
|
||||
- 错误处理:异常分支与日志记录
|
||||
- 性能与资源:定时任务、事件监听与清理
|
||||
|
||||
章节来源
|
||||
- [package.json(服务端):5-12](file://package.json#L5-L12)
|
||||
- [package.json(客户端):5-8](file://client/package.json#L5-L8)
|
||||
- [jest.config.js:20-34](file://jest.config.js#L20-L34)
|
||||
|
||||
### 常见代码问题与修复方法
|
||||
- TypeScript
|
||||
- any 类型滥用:优先使用具体类型或泛型
|
||||
- 导入路径不一致:统一相对路径或别名
|
||||
- 未使用的变量/私有成员:删除或标记为私有
|
||||
- JavaScript(客户端)
|
||||
- 事件监听未移除:在组件销毁时解绑
|
||||
- 分号缺失:遵循 EditorConfig 与 ESLint 规则
|
||||
- 重复逻辑:抽取为函数或工具模块
|
||||
- 通用
|
||||
- 日志与错误:使用统一的日志模块,避免直接 console
|
||||
- 资源清理:WebSocket、HTTP 请求、文件句柄等及时释放
|
||||
|
||||
章节来源
|
||||
- [.eslintrc.cjs:18-23](file://.eslintrc.cjs#L18-L23)
|
||||
- [.eslintrc.json(客户端):19-22](file://client/.eslintrc.json#L19-L22)
|
||||
- [src/server.ts:44-57](file://src/server.ts#L44-L57)
|
||||
|
||||
### 自动化质量检查工具配置与使用
|
||||
- ESLint
|
||||
- 服务端:npm run lint 检查 src 与 test 下的 TypeScript 文件
|
||||
- 客户端:npm run lint 检查 public 与 src、test 下的 JS 文件
|
||||
- Jest
|
||||
- 服务端:npm test 运行所有测试
|
||||
- 客户端:npm test 运行前端测试(需 jsdom 环境)
|
||||
- TypeScript
|
||||
- 构建:npm run build 使用 tsconfig.build.json
|
||||
- ESLint 专用:tsconfig.lint.json 关闭 sourceMap,提升性能
|
||||
|
||||
章节来源
|
||||
- [package.json(服务端):5-12](file://package.json#L5-L12)
|
||||
- [package.json(客户端):5-8](file://client/package.json#L5-L8)
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
- [tsconfig.lint.json:1-12](file://tsconfig.lint.json#L1-L12)
|
||||
- [jest.config.js:174-176](file://jest.config.js#L174-L176)
|
||||
|
||||
## 依赖分析
|
||||
- 工具链耦合
|
||||
- ESLint 与 TypeScript 解析器耦合,解析选项指向 tsconfig.lint.json
|
||||
- Jest 与 ts-jest 耦合,支持 TS/TSX 测试文件
|
||||
- 环境差异
|
||||
- 服务端:Node 环境,Jest 测试环境为 node
|
||||
- 客户端:浏览器环境,Jest 使用 jsdom 与自定义环境配置
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
ESLintTS["@typescript-eslint/parser<br/>解析 TS/TSX"]
|
||||
ESLintCfg[".eslintrc.cjs<br/>规则与插件"]
|
||||
JestTS["ts-jest<br/>转换 TS/TSX"]
|
||||
JestCfg["jest.config.js<br/>测试环境与扩展"]
|
||||
TSConf["tsconfig.json<br/>编译配置"]
|
||||
LintTSConf["tsconfig.lint.json<br/>ESLint 专用"]
|
||||
ESLintCfg --> ESLintTS
|
||||
ESLintCfg --> LintTSConf
|
||||
JestCfg --> JestTS
|
||||
JestCfg --> TSConf
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [.eslintrc.cjs:12-16](file://.eslintrc.cjs#L12-L16)
|
||||
- [tsconfig.lint.json:4-11](file://tsconfig.lint.json#L4-L11)
|
||||
- [jest.config.js:174-176](file://jest.config.js#L174-L176)
|
||||
- [tsconfig.json:4-11](file://tsconfig.json#L4-L11)
|
||||
|
||||
章节来源
|
||||
- [.eslintrc.cjs:12-16](file://.eslintrc.cjs#L12-L16)
|
||||
- [tsconfig.lint.json:4-11](file://tsconfig.lint.json#L4-L11)
|
||||
- [jest.config.js:174-176](file://jest.config.js#L174-L176)
|
||||
- [tsconfig.json:4-11](file://tsconfig.json#L4-L11)
|
||||
|
||||
## 性能考虑
|
||||
- ESLint 性能
|
||||
- 使用 tsconfig.lint.json 关闭 sourceMap,减少解析开销
|
||||
- 仅对 src 与 test 目标进行检查,避免 node_modules
|
||||
- 构建与测试
|
||||
- 构建输出至 build 目录,便于缓存与增量编译
|
||||
- Jest 使用 v8 覆盖率提供器,平衡速度与准确性
|
||||
|
||||
章节来源
|
||||
- [tsconfig.lint.json:8](file://tsconfig.lint.json#L8)
|
||||
- [jest.config.js:34](file://jest.config.js#L34)
|
||||
- [package.json(服务端):6](file://package.json#L6)
|
||||
|
||||
## 故障排查指南
|
||||
- ESLint 报错
|
||||
- 规则冲突:调整 .eslintrc.cjs 或 .eslintrc.json 中的 rules
|
||||
- 解析失败:确认 tsconfig.lint.json 与 tsconfig.json 的 include/exclude 一致
|
||||
- Jest 测试失败
|
||||
- 环境问题:检查 jest.config.js 的 testEnvironment 与 jsdom 配置
|
||||
- 转换问题:确认 ts-jest 版本与 tsconfig.json 设置匹配
|
||||
- EditorConfig 不生效
|
||||
- 检查文件扩展名是否在 [*.{ts,js,json,html}] 范围内
|
||||
- 确认编辑器已加载 EditorConfig 插件
|
||||
|
||||
章节来源
|
||||
- [.eslintrc.cjs:18-23](file://.eslintrc.cjs#L18-L23)
|
||||
- [.eslintrc.json(客户端):19-22](file://client/.eslintrc.json#L19-L22)
|
||||
- [jest.config.js:140-145](file://jest.config.js#L140-L145)
|
||||
- [.editorconfig:15-18](file://.editorconfig#L15-L18)
|
||||
|
||||
## 结论
|
||||
本指南提供了从工具配置到编码实践的完整质量保障体系。建议团队在开发流程中坚持:
|
||||
- 保存即检查:利用 EditorConfig 与 ESLint 在本地即时反馈
|
||||
- 测试驱动:以 Jest 覆盖核心逻辑,持续改进覆盖率
|
||||
- 文档与注释:关键模块与复杂函数必须具备清晰注释
|
||||
- 审查与迭代:结合审查清单与自动化检查,逐步完善规则与流程
|
||||
|
||||
## 附录
|
||||
|
||||
### 示例:WebSocket 信令处理测试流程
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Test as "测试用例"
|
||||
participant WSHandler as "WebSocket 处理器"
|
||||
participant MockWS as "WebSocket 模拟"
|
||||
participant Signaling as "信令服务"
|
||||
Test->>MockWS : 建立连接
|
||||
Test->>WSHandler : add(客户端)
|
||||
WSHandler->>Signaling : 广播 connect 消息
|
||||
Test->>WSHandler : onOffer(发送 offer)
|
||||
WSHandler->>Signaling : 广播 offer 消息
|
||||
Test->>WSHandler : onAnswer(发送 answer)
|
||||
WSHandler->>Signaling : 广播 answer 消息
|
||||
Test->>WSHandler : remove(断开)
|
||||
WSHandler->>Signaling : 广播 disconnect 消息
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [test/websockethandler.test.ts:30-99](file://test/websockethandler.test.ts#L30-L99)
|
||||
|
||||
### 示例:输入远程控制测试流程
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Test as "测试用例"
|
||||
participant Sender as "Sender"
|
||||
participant Remoting as "InputRemoting"
|
||||
participant Observer as "Observer"
|
||||
Test->>Sender : 创建实例
|
||||
Test->>Remoting : 创建实例并绑定 Sender
|
||||
Test->>Observer : 创建观察者
|
||||
Test->>Remoting : subscribe(Observer)
|
||||
Test->>Remoting : startSending()
|
||||
Test->>Remoting : stopSending()
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [client/test/inputremoting.test.js:24-48](file://client/test/inputremoting.test.js#L24-L48)
|
||||
319
.qoder/repowiki/zh/content/开发指南/开发指南.md
Normal file
319
.qoder/repowiki/zh/content/开发指南/开发指南.md
Normal file
@@ -0,0 +1,319 @@
|
||||
# 开发指南
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [package.json](file://package.json)
|
||||
- [client/package.json](file://client/package.json)
|
||||
- [tsconfig.json](file://tsconfig.json)
|
||||
- [tsconfig.lint.json](file://tsconfig.lint.json)
|
||||
- [jest.config.js](file://jest.config.js)
|
||||
- [client/jest.config.js](file://client/jest.config.js)
|
||||
- [client/jest.setup.js](file://client/jest.setup.js)
|
||||
- [.eslintrc.cjs](file://.eslintrc.cjs)
|
||||
- [client/.eslintrc.json](file://client/.eslintrc.json)
|
||||
- [.editorconfig](file://.editorconfig)
|
||||
- [run.bat](file://run.bat)
|
||||
- [.gitignore](file://.gitignore)
|
||||
- [src/index.ts](file://src/index.ts)
|
||||
- [src/server.ts](file://src/server.ts)
|
||||
- [src/class/options.ts](file://src/class/options.ts)
|
||||
- [src/log.ts](file://src/log.ts)
|
||||
- [test/httphandler.test.ts](file://test/httphandler.test.ts)
|
||||
- [test/websockethandler.test.ts](file://test/websockethandler.test.ts)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本开发指南面向参与“视频流服务器”项目的开发者,目标是帮助你快速搭建本地开发环境、理解代码规范与编码标准、掌握调试与测试技巧、明确扩展开发流程、以及建立版本管理与发布流程的共识。项目采用 Node.js + TypeScript 构建,前端静态资源由服务端托管,支持 WebSocket 与 HTTP 两种信令模式,内置日志系统与 Swagger 文档。
|
||||
|
||||
## 项目结构
|
||||
项目分为服务端与客户端两部分:
|
||||
- 服务端(src):Express 应用、HTTP 路由、WebSocket 信令、日志与配置等。
|
||||
- 客户端(client):静态页面与前端脚本,通过 /module 与 /uploads 等路由访问。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "服务端(src)"
|
||||
IDX["入口: index.ts"]
|
||||
SRV["HTTP服务: server.ts"]
|
||||
LOG["日志: log.ts"]
|
||||
OPT["选项: class/options.ts"]
|
||||
end
|
||||
subgraph "客户端(client)"
|
||||
PUB["静态资源: public/*"]
|
||||
SRC["前端源码: src/*"]
|
||||
end
|
||||
IDX --> SRV
|
||||
SRV --> PUB
|
||||
SRV --> SRC
|
||||
SRV --> LOG
|
||||
IDX --> OPT
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
- [src/class/options.ts:1-10](file://src/class/options.ts#L1-L10)
|
||||
- [src/log.ts:1-51](file://src/log.ts#L1-L51)
|
||||
|
||||
章节来源
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
|
||||
## 核心组件
|
||||
- 入口与启动:命令行参数解析、HTTPS/HTTP 启动、信令类型选择、日志输出。
|
||||
- HTTP 服务:CORS、JSON/URL 编码中间件、静态资源、Swagger 文档、头像上传接口。
|
||||
- 日志系统:可配置的日志级别与格式化输出。
|
||||
- 测试框架:Jest(服务端)、Jest + jsdom(客户端),覆盖 HTTP 与 WebSocket 信令逻辑。
|
||||
|
||||
章节来源
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
- [src/log.ts:1-51](file://src/log.ts#L1-L51)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [client/jest.config.js:1-196](file://client/jest.config.js#L1-L196)
|
||||
|
||||
## 架构总览
|
||||
下图展示从浏览器到服务端的典型请求链路,包括静态资源、信令与上传接口。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Browser as "浏览器"
|
||||
participant Express as "Express 应用(server.ts)"
|
||||
participant Signaling as "信令(HTTP/WebSocket)"
|
||||
participant FS as "文件系统(头像上传)"
|
||||
Browser->>Express : GET /
|
||||
Express-->>Browser : 返回首页(静态资源)
|
||||
Browser->>Express : GET /config
|
||||
Express-->>Browser : 返回运行配置
|
||||
Browser->>Express : GET /signaling/*
|
||||
Express->>Signaling : 转发至 HTTP 信令处理器
|
||||
Browser->>Express : POST /api/upload/avatar
|
||||
Express->>FS : 写入头像并重命名
|
||||
FS-->>Express : 返回结果
|
||||
Express-->>Browser : JSON 响应
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/server.ts:25-87](file://src/server.ts#L25-L87)
|
||||
- [src/index.ts:75-90](file://src/index.ts#L75-L90)
|
||||
|
||||
章节来源
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 启动与配置(index.ts)
|
||||
- 支持命令行参数:端口、HTTPS 证书、信令类型、通信模式、日志级别。
|
||||
- 自动检测本机 IPv4 地址并输出访问地址。
|
||||
- 根据信令类型启动 HTTP 轮询或 WebSocket 信令服务。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进程启动"]) --> ParseArgs["解析命令行参数"]
|
||||
ParseArgs --> CreateApp["创建 Express 应用"]
|
||||
CreateApp --> Mode{"是否启用 HTTPS?"}
|
||||
Mode --> |是| HTTPS["读取密钥与证书并监听"]
|
||||
Mode --> |否| HTTP["以 HTTP 监听"]
|
||||
HTTPS --> DetectIP["检测本机 IPv4 地址"]
|
||||
HTTP --> DetectIP
|
||||
DetectIP --> SigType{"信令类型"}
|
||||
SigType --> |websocket| WS["初始化 WebSocket 信令"]
|
||||
SigType --> |http| HTTPSig["初始化 HTTP 轮询信令"]
|
||||
WS --> Done(["完成"])
|
||||
HTTPSig --> Done
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/index.ts:14-105](file://src/index.ts#L14-L105)
|
||||
|
||||
章节来源
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/class/options.ts:1-10](file://src/class/options.ts#L1-L10)
|
||||
|
||||
### HTTP 服务与静态资源(server.ts)
|
||||
- 中间件:CORS、JSON、URL 编码、日志(Morgan)。
|
||||
- 路由:
|
||||
- GET /config:返回运行配置(信令类型、模式、日志级别)。
|
||||
- /signaling:转发至信令模块。
|
||||
- 静态资源:/ 与 /module。
|
||||
- 上传接口:POST /api/upload/avatar,使用 Multer 存储并按用户 ID 重命名。
|
||||
- /uploads:公开头像目录。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Req["请求进入"] --> CORS["CORS 允许所有来源"]
|
||||
CORS --> Body["解析 JSON/URL 编码"]
|
||||
Body --> Log{"日志级别允许?"}
|
||||
Log --> |是| Morgan["Morgan 访问日志"]
|
||||
Log --> |否| Skip["跳过日志"]
|
||||
Morgan --> Routes["分发路由"]
|
||||
Skip --> Routes
|
||||
Routes --> Config["GET /config"]
|
||||
Routes --> Signaling["GET/POST /signaling/*"]
|
||||
Routes --> Static["静态资源: / 与 /module"]
|
||||
Routes --> Upload["POST /api/upload/avatar"]
|
||||
Routes --> PublicUploads["GET /uploads/*"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/server.ts:14-89](file://src/server.ts#L14-L89)
|
||||
|
||||
章节来源
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
|
||||
### 日志系统(log.ts)
|
||||
- 提供多级日志:none/error/warn/log/info。
|
||||
- 可通过字符串解析日志级别。
|
||||
- 输出包含时间戳与级别前缀。
|
||||
|
||||
章节来源
|
||||
- [src/log.ts:1-51](file://src/log.ts#L1-L51)
|
||||
|
||||
### 测试与断言(Jest)
|
||||
- 服务端测试:覆盖 HTTP 信令在 public/private 模式下的行为,含超时清理逻辑。
|
||||
- 客户端测试:Jest + jsdom 环境,通过 setup 注入 fetch、TextEncoder/Decoder、RTCPeerConnection 等缺失对象。
|
||||
|
||||
章节来源
|
||||
- [test/httphandler.test.ts:1-510](file://test/httphandler.test.ts#L1-L510)
|
||||
- [test/websockethandler.test.ts:1-191](file://test/websockethandler.test.ts#L1-L191)
|
||||
- [client/jest.setup.js:1-35](file://client/jest.setup.js#L1-L35)
|
||||
|
||||
## 依赖关系分析
|
||||
- 语言与构建:TypeScript、ts-node、Jest、ESLint。
|
||||
- Web 框架:Express、ws(WebSocket)、Multer(文件上传)。
|
||||
- 文档:Swagger JSdoc、Swagger UI Express。
|
||||
- 日志:Morgan。
|
||||
- 工具:Commander(命令行解析)。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Pkg["package.json 依赖"] --> TS["TypeScript 运行时"]
|
||||
Pkg --> Express["Express"]
|
||||
Pkg --> WS["ws"]
|
||||
Pkg --> Mul["Multer"]
|
||||
Pkg --> Swagger["Swagger UI Express"]
|
||||
Pkg --> Morgan["Morgan"]
|
||||
Pkg --> Cmdr["Commander"]
|
||||
Pkg --> Jest["Jest"]
|
||||
Pkg --> ESL["ESLint + TS 插件"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [package.json:14-46](file://package.json#L14-L46)
|
||||
|
||||
章节来源
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
|
||||
## 性能考虑
|
||||
- 上传路径:头像上传使用磁盘存储,建议在生产环境挂载独立持久卷并限制文件大小与类型。
|
||||
- 日志级别:默认 info,可在高并发场景调低日志级别以减少 I/O。
|
||||
- 静态资源:Express 静态托管适合开发,生产建议使用 CDN 或反向代理缓存。
|
||||
- 信令:WebSocket 在高并发下优于 HTTP 轮询,建议优先使用 websocket 模式。
|
||||
|
||||
## 故障排查指南
|
||||
- 启动失败(HTTPS 证书):确认 server.key 与 server.cert 存在且可读;或禁用 HTTPS 并使用 HTTP。
|
||||
- 无法访问 /uploads:确保 uploads 目录存在且可读写。
|
||||
- 上传失败:检查 Multer 配置与权限,查看服务端错误日志。
|
||||
- 测试失败(jsdom 缺失 API):确保使用客户端 jest.config 的 setup 文件已加载。
|
||||
- 超时会话未清理:检查 HTTP 信令测试中的超时轮询逻辑与清理触发点。
|
||||
|
||||
章节来源
|
||||
- [src/server.ts:44-87](file://src/server.ts#L44-L87)
|
||||
- [client/jest.setup.js:1-35](file://client/jest.setup.js#L1-L35)
|
||||
- [test/httphandler.test.ts:194-309](file://test/httphandler.test.ts#L194-L309)
|
||||
|
||||
## 结论
|
||||
本项目提供了清晰的服务端架构与完善的测试体系,支持 WebSocket 与 HTTP 两种信令模式,并内置日志与文档能力。遵循本文的开发与测试规范,可高效地进行功能扩展与维护。
|
||||
|
||||
## 附录
|
||||
|
||||
### 开发环境搭建步骤
|
||||
- 安装 Node.js 与 npm(建议使用版本管理器以避免版本冲突)。
|
||||
- 克隆仓库后,在根目录与 client 目录分别执行安装依赖命令。
|
||||
- 准备 HTTPS 证书(可选):若启用 HTTPS,需准备 server.key 与 server.cert。
|
||||
- 使用提供的脚本启动开发服务或打包产物。
|
||||
|
||||
章节来源
|
||||
- [package.json:5-12](file://package.json#L5-L12)
|
||||
- [client/package.json:5-8](file://client/package.json#L5-L8)
|
||||
- [run.bat:1-17](file://run.bat#L1-L17)
|
||||
|
||||
### 代码规范与编码标准
|
||||
- 统一缩进与换行:EditorConfig 规定空格缩进、LF 换行、UTF-8 字符集。
|
||||
- TypeScript 规范:ESLint 配置启用 @typescript-eslint 推荐规则,强制分号。
|
||||
- JavaScript 规范(客户端):ESLint 配置启用 jest 插件与推荐规则,强制分号。
|
||||
- 代码风格:遵循 EditorConfig 与 ESLint 规则,保持一致的排版与语法。
|
||||
|
||||
章节来源
|
||||
- [.editorconfig:10-20](file://.editorconfig#L10-L20)
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [client/.eslintrc.json:1-23](file://client/.eslintrc.json#L1-L23)
|
||||
|
||||
### 调试技巧与开发工具
|
||||
- 本地启动:使用开发脚本启动服务,自动监听 TypeScript 源码变化。
|
||||
- 单元测试:使用 Jest 运行服务端与客户端测试,关注覆盖率与断言。
|
||||
- 信令调试:根据运行日志确认信令类型与模式,必要时降低日志级别以便观察。
|
||||
- 上传调试:通过 /uploads 访问上传后的头像,验证重命名与路径。
|
||||
|
||||
章节来源
|
||||
- [package.json:5-12](file://package.json#L5-L12)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [client/jest.config.js:1-196](file://client/jest.config.js#L1-L196)
|
||||
- [src/server.ts:62-87](file://src/server.ts#L62-L87)
|
||||
|
||||
### 扩展开发机制
|
||||
- 新增 HTTP 路由:在 server.ts 中添加路由与处理逻辑,注意中间件顺序与错误处理。
|
||||
- 新增 WebSocket 事件:在 WebSocket 信令模块中新增事件处理函数,并在测试中补充断言。
|
||||
- 新增测试用例:在 test 目录下新增对应测试文件,复用现有的公共断言与模拟数据。
|
||||
- 修改现有功能:遵循最小变更原则,先写测试,再实现修复或增强。
|
||||
|
||||
章节来源
|
||||
- [src/server.ts:14-89](file://src/server.ts#L14-L89)
|
||||
- [test/httphandler.test.ts:1-510](file://test/httphandler.test.ts#L1-L510)
|
||||
- [test/websockethandler.test.ts:1-191](file://test/websockethandler.test.ts#L1-L191)
|
||||
|
||||
### 版本管理、分支策略与发布流程
|
||||
- 版本号:项目使用语义化版本(package.json 中 version 字段)。
|
||||
- 分支策略:建议采用 Git Flow,主分支用于稳定版本,开发分支用于迭代。
|
||||
- 发布流程:本地构建(build)、测试(test)、打包(pack),生成可执行包或容器镜像后发布。
|
||||
|
||||
章节来源
|
||||
- [package.json:2-4](file://package.json#L2-L4)
|
||||
- [package.json:5-12](file://package.json#L5-L12)
|
||||
|
||||
### 贡献指南与代码审查标准
|
||||
- 提交前:运行 lint 与 test,确保通过。
|
||||
- 提交流程:提交变更到功能分支,发起 Pull Request,至少一名维护者审查。
|
||||
- 代码审查要点:功能正确性、边界条件、错误处理、日志与安全、测试覆盖、性能影响。
|
||||
|
||||
章节来源
|
||||
- [package.json:11-12](file://package.json#L11-L12)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [client/jest.config.js:1-196](file://client/jest.config.js#L1-L196)
|
||||
|
||||
### 常见问题与最佳实践
|
||||
- 问题:浏览器跨域访问受限
|
||||
- 解决:服务端已启用 CORS,确保请求头与路径正确。
|
||||
- 问题:WebSocket 连接失败
|
||||
- 解决:确认信令类型为 websocket,检查服务端日志与防火墙设置。
|
||||
- 问题:头像上传失败
|
||||
- 解决:确认上传目录存在且可写,检查文件类型与大小限制。
|
||||
- 最佳实践:在生产环境使用 HTTPS、CDN 加速静态资源、合理设置日志级别与轮询间隔。
|
||||
|
||||
章节来源
|
||||
- [src/server.ts:22-24](file://src/server.ts#L22-L24)
|
||||
- [src/server.ts:44-87](file://src/server.ts#L44-L87)
|
||||
- [src/index.ts:55-74](file://src/index.ts#L55-L74)
|
||||
392
.qoder/repowiki/zh/content/开发指南/开发环境搭建.md
Normal file
392
.qoder/repowiki/zh/content/开发指南/开发环境搭建.md
Normal file
@@ -0,0 +1,392 @@
|
||||
# 开发环境搭建
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [package.json](file://package.json)
|
||||
- [client/package.json](file://client/package.json)
|
||||
- [tsconfig.json](file://tsconfig.json)
|
||||
- [tsconfig.build.json](file://tsconfig.build.json)
|
||||
- [tsconfig.lint.json](file://tsconfig.lint.json)
|
||||
- [jest.config.js](file://jest.config.js)
|
||||
- [client/jest.config.js](file://client/jest.config.js)
|
||||
- [.eslintrc.cjs](file://.eslintrc.cjs)
|
||||
- [client/.eslintrc.json](file://client/.eslintrc.json)
|
||||
- [run.bat](file://run.bat)
|
||||
- [src/index.ts](file://src/index.ts)
|
||||
- [src/server.ts](file://src/server.ts)
|
||||
- [client/jest.setup.js](file://client/jest.setup.js)
|
||||
- [.gitignore](file://.gitignore)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本指南面向首次参与“视频流服务器”项目的开发者,目标是帮助你在本地快速完成开发环境搭建与运行。内容涵盖:
|
||||
- Node.js 版本要求与安装步骤(含 LTS 建议)
|
||||
- TypeScript 编译与构建配置说明
|
||||
- 包管理器选择建议(npm 与 yarn)
|
||||
- 依赖安装流程(生产依赖与开发依赖)
|
||||
- 开发脚本详解(dev、build、test 等)
|
||||
- IDE 配置建议(VS Code 插件与调试)
|
||||
- 常见环境问题排查与解决方案
|
||||
|
||||
## 项目结构
|
||||
该项目采用前后端分离的多包结构:
|
||||
- 根包:服务端逻辑与构建、测试、打包配置
|
||||
- 客户端子包:前端示例页面与测试配置
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
Root["根项目<br/>package.json"] --> TS["TypeScript 配置<br/>tsconfig*.json"]
|
||||
Root --> JestRoot["Jest 根测试配置<br/>jest.config.js"]
|
||||
Root --> ESLintRoot[".eslintrc.cjs"]
|
||||
Root --> RunBat["启动批处理<br/>run.bat"]
|
||||
Client["客户端子包<br/>client/package.json"] --> JestClient["Jest 客户端测试配置<br/>client/jest.config.js"]
|
||||
Client --> ESLintClient["ESLint 客户端规则<br/>client/.eslintrc.json"]
|
||||
Client --> Public["静态资源<br/>client/public/*"]
|
||||
Root --> Src["服务端源码<br/>src/*"]
|
||||
Src --> IndexTS["入口与参数解析<br/>src/index.ts"]
|
||||
Src --> ServerTS["HTTP 服务与路由<br/>src/server.ts"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
- [client/package.json:1-19](file://client/package.json#L1-L19)
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [client/jest.config.js:1-196](file://client/jest.config.js#L1-L196)
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [client/.eslintrc.json:1-23](file://client/.eslintrc.json#L1-L23)
|
||||
- [run.bat:1-17](file://run.bat#L1-L17)
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
|
||||
章节来源
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
- [client/package.json:1-19](file://client/package.json#L1-L19)
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [client/jest.config.js:1-196](file://client/jest.config.js#L1-L196)
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [client/.eslintrc.json:1-23](file://client/.eslintrc.json#L1-L23)
|
||||
- [run.bat:1-17](file://run.bat#L1-L17)
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
|
||||
## 核心组件
|
||||
- Node.js 运行时与包管理器:用于安装依赖、执行脚本、启动服务
|
||||
- TypeScript 编译系统:将 ts/ts 文件编译为 js 并输出到 build 目录
|
||||
- 测试框架:Jest(服务端)与 Jest + jsdom(客户端)
|
||||
- 代码质量工具:ESLint(TS 规则与 Jest 插件)
|
||||
- 启动与打包:npm scripts 提供 dev/build/test/start/newman/pack 等命令;pkg 用于打包
|
||||
|
||||
章节来源
|
||||
- [package.json:5-13](file://package.json#L5-L13)
|
||||
- [client/package.json:5-8](file://client/package.json#L5-L8)
|
||||
- [tsconfig.json:4-11](file://tsconfig.json#L4-L11)
|
||||
- [tsconfig.build.json:1-5](file://tsconfig.build.json#L1-L5)
|
||||
- [tsconfig.lint.json:4-11](file://tsconfig.lint.json#L4-L11)
|
||||
- [jest.config.js:174-176](file://jest.config.js#L174-L176)
|
||||
- [client/jest.config.js:139-144](file://client/jest.config.js#L139-L144)
|
||||
- [.eslintrc.cjs:6-11](file://.eslintrc.cjs#L6-L11)
|
||||
- [client/.eslintrc.json:3-6](file://client/.eslintrc.json#L3-L6)
|
||||
|
||||
## 架构总览
|
||||
下图展示了从开发脚本到服务启动的关键路径,以及静态资源与 API 的组织方式。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Dev as "开发者"
|
||||
participant NPM as "npm 脚本"
|
||||
participant TS as "TypeScript 编译器"
|
||||
participant Node as "Node 进程"
|
||||
participant Express as "Express 应用"
|
||||
participant Static as "静态资源"
|
||||
participant Client as "浏览器客户端"
|
||||
Dev->>NPM : 执行 "npm run dev"
|
||||
NPM->>TS : 使用 ts-node 直接执行 src/index.ts
|
||||
TS-->>Node : 返回可执行的 Node 入口
|
||||
Node->>Express : 初始化应用与中间件
|
||||
Express->>Static : 挂载静态目录 client/public
|
||||
Express-->>Dev : 输出监听地址与模式信息
|
||||
Client->>Express : 访问 / 与 /config
|
||||
Express-->>Client : 返回示例页面与配置
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [package.json:10](file://package.json#L10)
|
||||
- [src/index.ts:13-109](file://src/index.ts#L13-L109)
|
||||
- [src/server.ts:14-89](file://src/server.ts#L14-L89)
|
||||
|
||||
章节来源
|
||||
- [package.json:5-13](file://package.json#L5-L13)
|
||||
- [src/index.ts:13-109](file://src/index.ts#L13-L109)
|
||||
- [src/server.ts:14-89](file://src/server.ts#L14-L89)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### Node.js 与包管理器
|
||||
- 版本要求与 LTS 建议
|
||||
- 项目使用 TypeScript 4.8.x 与 Jest 29.x 等较新生态,建议优先选择 Node.js LTS(长期支持版本),以获得更稳定的依赖兼容性与社区支持。
|
||||
- 若需使用实验特性(如客户端测试中的 ES Module),可考虑使用当前稳定版 Node.js,但请确保团队统一版本。
|
||||
- 包管理器选择
|
||||
- 推荐使用 npm(项目未指定 yarn.lock,且 package.json 中未声明 yarn 专属配置)。
|
||||
- 如团队已有 yarn 工作流,也可继续使用,但需注意切换时清理 node_modules 并重新安装,避免锁文件冲突。
|
||||
|
||||
章节来源
|
||||
- [package.json:28-46](file://package.json#L28-L46)
|
||||
- [client/package.json:9-16](file://client/package.json#L9-L16)
|
||||
|
||||
### TypeScript 配置与构建
|
||||
- 编译目标与输出
|
||||
- 目标:ES5(target),模块:CommonJS(module),输出目录:build(outDir),根目录:src(rootDir)。
|
||||
- 适用于 Node.js 运行时的通用兼容性与打包工具链。
|
||||
- 构建配置
|
||||
- 标准配置:tsconfig.json
|
||||
- 构建专用配置:tsconfig.build.json 继承标准配置,仅包含 src/**/*。
|
||||
- Lint 专用配置:tsconfig.lint.json,关闭 sourceMap,便于 ESLint 解析。
|
||||
- 关键编译脚本
|
||||
- build:通过 tsc -p tsconfig.build.json 执行构建。
|
||||
- dev:通过 ts-node 直接运行 src/index.ts,无需预先编译。
|
||||
- lint:通过 ESLint 对 src 与 test 下的 TS 文件进行检查。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["开始"]) --> LoadTS["加载 tsconfig.json"]
|
||||
LoadTS --> ExtendBuild["继承 tsconfig.build.json"]
|
||||
ExtendBuild --> Compile["执行 tsc 编译 src/**/*"]
|
||||
Compile --> OutDir["输出至 build 目录"]
|
||||
OutDir --> End(["结束"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
- [tsconfig.build.json:1-5](file://tsconfig.build.json#L1-L5)
|
||||
- [tsconfig.lint.json:1-12](file://tsconfig.lint.json#L1-L12)
|
||||
|
||||
章节来源
|
||||
- [tsconfig.json:4-11](file://tsconfig.json#L4-L11)
|
||||
- [tsconfig.build.json:1-5](file://tsconfig.build.json#L1-L5)
|
||||
- [tsconfig.lint.json:4-11](file://tsconfig.lint.json#L4-L11)
|
||||
- [package.json:6-7](file://package.json#L6-L7)
|
||||
- [package.json:11](file://package.json#L11)
|
||||
|
||||
### 依赖安装与分类
|
||||
- 生产依赖(dependencies)
|
||||
- 包括 express、ws、cors、morgan、multer、uuid、swagger-* 等,用于服务端运行期功能。
|
||||
- 开发依赖(devDependencies)
|
||||
- 包括 TypeScript、ts-node、jest、ts-jest、eslint 及其插件、pkg 等,用于开发、测试与打包。
|
||||
- 客户端子包
|
||||
- 客户端 package.json 为独立的开发环境,包含 eslint、jest、jsdom 等测试相关依赖。
|
||||
|
||||
章节来源
|
||||
- [package.json:14-27](file://package.json#L14-L27)
|
||||
- [package.json:28-46](file://package.json#L28-L46)
|
||||
- [client/package.json:9-16](file://client/package.json#L9-L16)
|
||||
|
||||
### 开发脚本详解
|
||||
- dev:使用 ts-node 直接运行 src/index.ts,支持热调试与快速迭代。
|
||||
- build:调用 tsc 按 tsconfig.build.json 编译生成 build。
|
||||
- test:运行 Jest 测试,收集覆盖率,服务端测试位于 test/*.ts。
|
||||
- start:启动已编译的服务端进程,支持 HTTPS 参数与日志级别。
|
||||
- lint:使用 ESLint 检查 TS 与测试代码。
|
||||
- pack:使用 pkg 将项目打包为可执行文件(targets 指向 node10)。
|
||||
- newman:执行 Postman 集合进行接口测试(需要 Newman)。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Dev as "开发者"
|
||||
participant NPM as "npm 脚本"
|
||||
participant Jest as "Jest"
|
||||
participant ESLint as "ESLint"
|
||||
participant TSC as "TypeScript 编译器"
|
||||
participant Pkg as "pkg 打包器"
|
||||
Dev->>NPM : npm run test
|
||||
NPM->>Jest : 执行测试与覆盖率收集
|
||||
Jest-->>Dev : 输出测试结果
|
||||
Dev->>NPM : npm run lint
|
||||
NPM->>ESLint : 检查 src 与 test 下 TS 文件
|
||||
ESLint-->>Dev : 输出规则警告/错误
|
||||
Dev->>NPM : npm run build
|
||||
NPM->>TSC : tsc -p tsconfig.build.json
|
||||
TSC-->>Dev : 生成 build 目录
|
||||
Dev->>NPM : npm run pack
|
||||
NPM->>Pkg : 打包为可执行文件
|
||||
Pkg-->>Dev : 输出二进制产物
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [package.json:5-13](file://package.json#L5-L13)
|
||||
- [jest.config.js:174-176](file://jest.config.js#L174-L176)
|
||||
- [.eslintrc.cjs:6-11](file://.eslintrc.cjs#L6-L11)
|
||||
- [tsconfig.build.json:1-5](file://tsconfig.build.json#L1-L5)
|
||||
|
||||
章节来源
|
||||
- [package.json:5-13](file://package.json#L5-L13)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
|
||||
### 客户端测试与环境配置
|
||||
- 客户端 Jest 配置
|
||||
- 测试环境:jest-environment-jsdom
|
||||
- 超时时间:5000ms
|
||||
- setupFilesAfterEnv:引入 client/jest.setup.js,注入 fetch、TextEncoder/Decoder、RTCPeerConnection 等浏览器 API 的 polyfill。
|
||||
- 客户端 ESLint
|
||||
- 推荐规则:eslint:recommended、plugin:jest/recommended
|
||||
- 环境:browser、es6、jest
|
||||
- 规则:分号强制与多余分号报错。
|
||||
|
||||
章节来源
|
||||
- [client/jest.config.js:139-144](file://client/jest.config.js#L139-L144)
|
||||
- [client/jest.config.js:130](file://client/jest.config.js#L130)
|
||||
- [client/jest.setup.js:1-35](file://client/jest.setup.js#L1-L35)
|
||||
- [client/.eslintrc.json:1-23](file://client/.eslintrc.json#L1-L23)
|
||||
|
||||
### 服务端启动与静态资源
|
||||
- 启动流程
|
||||
- 通过 src/index.ts 解析命令行参数(端口、HTTPS、密钥证书、信令类型、通信模式、日志级别等),创建 Express 应用并启动 HTTP/HTTPS 服务。
|
||||
- 根据模式输出监听地址与模式信息。
|
||||
- 静态资源与 API
|
||||
- 挂载 client/public 为静态目录,根路径返回示例页面。
|
||||
- 提供 /config 接口返回当前配置。
|
||||
- 提供 /signaling 路由(由 signaling 模块处理)。
|
||||
- 提供头像上传 API 与 /uploads 静态目录。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["启动 src/index.ts"] --> B["解析参数与选项"]
|
||||
B --> C{"是否启用 HTTPS"}
|
||||
C --> |是| D["读取 server.key 与 server.cert"]
|
||||
C --> |否| E["使用 HTTP 监听"]
|
||||
D --> F["创建 HTTPS 服务器"]
|
||||
E --> G["创建 HTTP 服务器"]
|
||||
F --> H["初始化 Express 应用"]
|
||||
G --> H
|
||||
H --> I["挂载静态资源 client/public"]
|
||||
H --> J["注册 /config 与 /signaling 路由"]
|
||||
H --> K["启动 Swagger 文档"]
|
||||
H --> L["启动头像上传与 /uploads"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/index.ts:14-109](file://src/index.ts#L14-L109)
|
||||
- [src/server.ts:14-89](file://src/server.ts#L14-L89)
|
||||
|
||||
章节来源
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
|
||||
### IDE 配置建议(VS Code)
|
||||
- 推荐扩展
|
||||
- ESLint:实时语法与风格检查
|
||||
- Jest Runner:一键运行/调试单个或全部测试
|
||||
- TypeScript Importer:自动导入 TS 模块
|
||||
- Prettier:格式化(配合 ESLint 规则)
|
||||
- Thunder Client 或 REST Client:HTTP 请求调试
|
||||
- 调试配置(launch.json)
|
||||
- 启动服务端:使用 Node 调试器附加到 ts-node 进程,或直接调试已编译的 build/index.js。
|
||||
- 启动客户端:在浏览器中打开 client/public 下的示例页面,结合断点与网络面板调试。
|
||||
- 设置同步
|
||||
- .vscode/settings.json 与 .vscode/tasks.json、.vscode/launch.json 由 .gitignore 排除,可在本地按需添加。
|
||||
|
||||
章节来源
|
||||
- [.gitignore:175-181](file://.gitignore#L175-L181)
|
||||
|
||||
## 依赖关系分析
|
||||
- 内部依赖
|
||||
- src/index.ts 依赖 src/server.ts 与 src/websocket(通过导入)。
|
||||
- src/server.ts 依赖 signaling、swagger、multer 等模块。
|
||||
- 外部依赖
|
||||
- 生产依赖:express、ws、cors、morgan、multer、uuid、swagger-*。
|
||||
- 开发依赖:TypeScript、ts-node、jest、ts-jest、eslint、pkg 等。
|
||||
- 客户端依赖
|
||||
- eslint、jest、jest-environment-jsdom、node-fetch 等。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Index["src/index.ts"] --> Server["src/server.ts"]
|
||||
Server --> Signaling["signaling 模块"]
|
||||
Server --> Swagger["swagger 初始化"]
|
||||
Server --> Multer["文件上传处理"]
|
||||
Index --> WS["WebSocket 信令"]
|
||||
RootPkg["根 package.json"] --> Deps["生产依赖"]
|
||||
RootPkg --> DevDeps["开发依赖"]
|
||||
ClientPkg["client/package.json"] --> ClientDeps["客户端测试依赖"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
- [package.json:14-46](file://package.json#L14-L46)
|
||||
- [client/package.json:9-16](file://client/package.json#L9-L16)
|
||||
|
||||
章节来源
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
- [package.json:14-46](file://package.json#L14-L46)
|
||||
- [client/package.json:9-16](file://client/package.json#L9-L16)
|
||||
|
||||
## 性能考虑
|
||||
- 构建与缓存
|
||||
- 使用 TypeScript 编译缓存(tsbuildinfo)减少增量编译时间。
|
||||
- 在 CI 环境中复用 node_modules,避免重复下载。
|
||||
- 测试性能
|
||||
- Jest 默认并发运行测试,可通过 maxWorkers 控制(已在配置中注释)。
|
||||
- 使用覆盖率收集时关注 I/O,必要时拆分测试集。
|
||||
- 服务端性能
|
||||
- 静态资源由 Express 直接提供,建议在生产环境前移至 CDN 或反向代理。
|
||||
- 日志级别可调整为 none 以降低开销(通过 start 脚本参数)。
|
||||
|
||||
[本节为通用指导,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 无法找到 node_modules 或依赖缺失
|
||||
- 清理缓存并重新安装:删除 node_modules 与 lockfile 后重新安装。
|
||||
- 确认包管理器一致性(npm/yarn),避免混用导致锁文件冲突。
|
||||
- 启动失败(端口占用)
|
||||
- 修改端口或释放占用端口(默认 8080)。
|
||||
- HTTPS 启动失败
|
||||
- 确认 server.key 与 server.cert 存在且可读。
|
||||
- 使用 start 脚本时传入正确的密钥与证书路径。
|
||||
- 浏览器控制台缺少 API
|
||||
- 客户端测试需注入 polyfill,确认 jest.setup.js 已被加载。
|
||||
- ESLint 报错
|
||||
- 使用 tsconfig.lint.json 作为 ESLint 的 parserOptions.project,确保规则解析正确。
|
||||
- 覆盖率未生成
|
||||
- 确认 Jest 配置中的 collectCoverage 与 coverageDirectory 设置。
|
||||
- Windows 批处理异常
|
||||
- run.bat 中包含注释与非执行语句,建议仅保留必要命令(如先 build 再 start)。
|
||||
|
||||
章节来源
|
||||
- [.gitignore:35-51](file://.gitignore#L35-L51)
|
||||
- [package.json:9](file://package.json#L9)
|
||||
- [src/index.ts:55-66](file://src/index.ts#L55-L66)
|
||||
- [client/jest.setup.js:1-35](file://client/jest.setup.js#L1-L35)
|
||||
- [.eslintrc.cjs:13-16](file://.eslintrc.cjs#L13-L16)
|
||||
- [jest.config.js:20](file://jest.config.js#L20)
|
||||
- [run.bat:1-7](file://run.bat#L1-L7)
|
||||
|
||||
## 结论
|
||||
按照本指南完成 Node.js、TypeScript、ESLint、Jest 与包管理器的配置后,你即可顺利运行与开发该视频流服务器项目。建议在团队内统一 Node.js 版本与包管理器,遵循 ESLint 规则与测试规范,以保证代码质量与协作效率。
|
||||
|
||||
[本节为总结,不直接分析具体文件]
|
||||
|
||||
## 附录
|
||||
- 快速验证清单
|
||||
- 安装 Node.js LTS(或稳定版)
|
||||
- 使用 npm 安装依赖
|
||||
- 运行 npm run build 与 npm run dev
|
||||
- 执行 npm run test 与 npm run lint
|
||||
- 如需打包,运行 npm run pack
|
||||
|
||||
[本节为补充说明,不直接分析具体文件]
|
||||
433
.qoder/repowiki/zh/content/开发指南/扩展开发.md
Normal file
433
.qoder/repowiki/zh/content/开发指南/扩展开发.md
Normal file
@@ -0,0 +1,433 @@
|
||||
# 扩展开发
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [src/index.ts](file://src/index.ts)
|
||||
- [src/server.ts](file://src/server.ts)
|
||||
- [src/websocket.ts](file://src/websocket.ts)
|
||||
- [src/class/websockethandler.ts](file://src/class/websockethandler.ts)
|
||||
- [src/class/httphandler.ts](file://src/class/httphandler.ts)
|
||||
- [src/signaling.ts](file://src/signaling.ts)
|
||||
- [src/class/offer.ts](file://src/class/offer.ts)
|
||||
- [src/class/answer.ts](file://src/class/answer.ts)
|
||||
- [src/class/candidate.ts](file://src/class/candidate.ts)
|
||||
- [client/src/signaling.js](file://client/src/signaling.js)
|
||||
- [client/src/peer.js](file://client/src/peer.js)
|
||||
- [test/websockethandler.test.ts](file://test/websockethandler.test.ts)
|
||||
- [package.json](file://package.json)
|
||||
- [client/package.json](file://client/package.json)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本指南面向希望扩展视频信令服务器的开发者,系统讲解如何:
|
||||
- 添加新的信令消息类型(如 Offer、Answer、Candidate 的扩展)
|
||||
- 扩展 WebSocketHandler 与 HttpHandler 的消息处理机制
|
||||
- 开发自定义信令处理器,实现消息路由与处理流程
|
||||
- 扩展客户端功能(新增 WebRTC 能力与 UI 组件)
|
||||
- 使用插件化扩展点设计原则与最佳实践
|
||||
- 考虑版本兼容性与向后兼容性
|
||||
|
||||
## 项目结构
|
||||
项目采用前后端分离的模块化组织:
|
||||
- 服务端(Node.js + Express + WebSocket):负责信令路由、消息持久化与广播
|
||||
- 客户端(浏览器端 JS):封装 HTTP 与 WebSocket 两类信令通道,驱动 WebRTC PeerConnection
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "服务端"
|
||||
IDX["入口: src/index.ts"]
|
||||
SRV["HTTP 服务器: src/server.ts"]
|
||||
WS["WebSocket 信令: src/websocket.ts"]
|
||||
WSH["WebSocket 处理器: src/class/websockethandler.ts"]
|
||||
HTH["HTTP 处理器: src/class/httphandler.ts"]
|
||||
SIG["HTTP 路由: src/signaling.ts"]
|
||||
end
|
||||
subgraph "客户端"
|
||||
CL_SIG["信令封装: client/src/signaling.js"]
|
||||
CL_PEER["WebRTC 对端: client/src/peer.js"]
|
||||
end
|
||||
IDX --> SRV
|
||||
SRV --> SIG
|
||||
SRV --> WS
|
||||
WS --> WSH
|
||||
SIG --> HTH
|
||||
CL_SIG --> WS
|
||||
CL_SIG --> SIG
|
||||
CL_PEER --> CL_SIG
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/index.ts:13-109](file://src/index.ts#L13-L109)
|
||||
- [src/server.ts:14-90](file://src/server.ts#L14-L90)
|
||||
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
|
||||
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
|
||||
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
|
||||
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
|
||||
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
|
||||
- [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188)
|
||||
|
||||
章节来源
|
||||
- [src/index.ts:13-109](file://src/index.ts#L13-L109)
|
||||
- [src/server.ts:14-90](file://src/server.ts#L14-L90)
|
||||
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
|
||||
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
|
||||
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
|
||||
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
|
||||
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
|
||||
- [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188)
|
||||
|
||||
## 核心组件
|
||||
- 信令模型类:Offer、Answer、Candidate,承载 SDP 与 ICE 候选等数据
|
||||
- WebSocket 信令:WSSignaling 负责连接生命周期与消息分发
|
||||
- WebSocket 处理器:websockethandler 提供连接组管理、广播、消息路由
|
||||
- HTTP 信令:httphandler 提供会话、连接、offer/answer/candidate 的持久化与轮询接口
|
||||
- HTTP 路由:signaling 路由器挂载在 /signaling 下,统一暴露 REST API
|
||||
- 客户端封装:signaling.js 提供 HTTP 与 WebSocket 两种信令通道;peer.js 驱动 WebRTC
|
||||
|
||||
章节来源
|
||||
- [src/class/offer.ts:1-11](file://src/class/offer.ts#L1-L11)
|
||||
- [src/class/answer.ts:1-8](file://src/class/answer.ts#L1-L8)
|
||||
- [src/class/candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
|
||||
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
|
||||
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
|
||||
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
|
||||
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
|
||||
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
|
||||
- [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188)
|
||||
|
||||
## 架构总览
|
||||
WebSocket 与 HTTP 两条信令通道并行工作:
|
||||
- WebSocket:低延迟、实时广播、支持 ping/pong 心跳
|
||||
- HTTP:轮询获取历史信令,适合弱网或受限环境
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as "客户端"
|
||||
participant WS as "WSSignaling"
|
||||
participant WH as "WebSocket 处理器"
|
||||
participant HS as "HTTP 服务器"
|
||||
participant HH as "HTTP 处理器"
|
||||
C->>WS : "connect/disconnect/offer/answer/candidate"
|
||||
WS->>WH : "分发消息类型"
|
||||
WH-->>C : "广播/单播回执"
|
||||
C->>HS : "PUT/GET/POST /signaling/*"
|
||||
HS->>HH : "路由到处理器"
|
||||
HH-->>C : "返回历史信令/状态"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/websocket.ts:44-115](file://src/websocket.ts#L44-L115)
|
||||
- [src/class/websockethandler.ts:76-338](file://src/class/websockethandler.ts#L76-L338)
|
||||
- [src/server.ts:25-42](file://src/server.ts#L25-L42)
|
||||
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
|
||||
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
|
||||
|
||||
章节来源
|
||||
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
|
||||
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
|
||||
- [src/server.ts:14-90](file://src/server.ts#L14-L90)
|
||||
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
|
||||
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 1) 新增信令消息类型(以 Offer/Answer/Candidate 为例)
|
||||
- 数据模型
|
||||
- Offer:包含 sdp、datetime、polite 字段
|
||||
- Answer:包含 sdp、datetime
|
||||
- Candidate:包含 candidate、sdpMLineIndex、sdpMid、datetime
|
||||
- 服务端处理
|
||||
- WebSocket:在 WSSignaling 中解析消息类型并调用 websockethandler 的 onOffer/onAnswer/onCandidate
|
||||
- HTTP:在 httphandler 中维护会话级的 offers/answers/candidates 映射,提供 GET/POST 接口
|
||||
- 客户端封装
|
||||
- HTTP 与 WebSocket 两端均提供发送与接收事件,便于上层业务订阅
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class Offer {
|
||||
+string sdp
|
||||
+number datetime
|
||||
+boolean polite
|
||||
}
|
||||
class Answer {
|
||||
+string sdp
|
||||
+number datetime
|
||||
}
|
||||
class Candidate {
|
||||
+string candidate
|
||||
+number sdpMLineIndex
|
||||
+string sdpMid
|
||||
+number datetime
|
||||
}
|
||||
class WebSocket_Handler {
|
||||
+onOffer(ws,msg)
|
||||
+onAnswer(ws,msg)
|
||||
+onCandidate(ws,msg)
|
||||
}
|
||||
class HTTP_Handler {
|
||||
+postOffer(req,res)
|
||||
+postAnswer(req,res)
|
||||
+postCandidate(req,res)
|
||||
+getOffer(req,res)
|
||||
+getAnswer(req,res)
|
||||
+getCandidate(req,res)
|
||||
}
|
||||
WebSocket_Handler --> Offer : "构造/转发"
|
||||
WebSocket_Handler --> Answer : "构造/转发"
|
||||
WebSocket_Handler --> Candidate : "构造/转发"
|
||||
HTTP_Handler --> Offer : "持久化/查询"
|
||||
HTTP_Handler --> Answer : "持久化/查询"
|
||||
HTTP_Handler --> Candidate : "持久化/查询"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/class/offer.ts:1-11](file://src/class/offer.ts#L1-L11)
|
||||
- [src/class/answer.ts:1-8](file://src/class/answer.ts#L1-L8)
|
||||
- [src/class/candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
|
||||
- [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338)
|
||||
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
|
||||
|
||||
章节来源
|
||||
- [src/class/offer.ts:1-11](file://src/class/offer.ts#L1-L11)
|
||||
- [src/class/answer.ts:1-8](file://src/class/answer.ts#L1-L8)
|
||||
- [src/class/candidate.ts:1-12](file://src/class/candidate.ts#L1-L12)
|
||||
- [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338)
|
||||
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
|
||||
|
||||
### 2) WebSocketHandler 扩展机制
|
||||
- 连接组管理:host 与 participants 的角色区分,支持私有模式下的多对一/一对一路由
|
||||
- 广播与单播:根据消息类型与角色进行目标选择
|
||||
- 心跳与断线:定时心跳检测,超时自动断开并广播离线事件
|
||||
- 新消息类型接入步骤
|
||||
1) 在 WSSignaling 的消息分发处增加 case 分支
|
||||
2) 在 websockethandler 中实现对应处理函数(如 onXxx),完成路由与广播
|
||||
3) 在客户端 signaling.js 中订阅并派发自定义事件
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant WS as "WebSocket"
|
||||
participant WSH as "websockethandler"
|
||||
participant P as "参与者"
|
||||
WS->>WSH : "type='xxx'"
|
||||
WSH->>WSH : "匹配处理函数"
|
||||
WSH->>P : "广播/单播消息"
|
||||
P-->>WSH : "回执/确认"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/websocket.ts:76-113](file://src/websocket.ts#L76-L113)
|
||||
- [src/class/websockethandler.ts:97-137](file://src/class/websockethandler.ts#L97-L137)
|
||||
- [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338)
|
||||
|
||||
章节来源
|
||||
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
|
||||
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
|
||||
|
||||
### 3) HttpHandler 扩展机制
|
||||
- 会话与连接:通过 session-id 维持会话上下文,支持连接对(connectionPair)在私有模式下建立双向关系
|
||||
- 消息持久化:offers/answers/candidates 以会话+连接维度缓存,支持 fromtime 过滤
|
||||
- 轮询接口:提供 /signaling、/signaling/offer、/signaling/answer、/signaling/candidate 的 GET/POST
|
||||
- 新消息类型接入步骤
|
||||
1) 在 httphandler 中新增 postXxx 与 getXxx 方法,维护内部映射
|
||||
2) 在 signaling 路由中注册对应路由
|
||||
3) 在客户端 signaling.js 中补充发送与接收逻辑
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["HTTP 请求进入"]) --> CheckSession["校验 session-id"]
|
||||
CheckSession --> Route{"路由到哪?"}
|
||||
Route --> |GET /signaling| GetAll["合并并排序历史消息"]
|
||||
Route --> |GET /signaling/offer| GetOffer["按会话/时间过滤 offer"]
|
||||
Route --> |GET /signaling/answer| GetAnswer["按会话/时间过滤 answer"]
|
||||
Route --> |GET /signaling/candidate| GetCandidate["按会话/时间过滤 candidate"]
|
||||
Route --> |POST /signaling/offer| PostOffer["写入 offer 映射"]
|
||||
Route --> |POST /signaling/answer| PostAnswer["写入 answer 映射"]
|
||||
Route --> |POST /signaling/candidate| PostCandidate["写入 candidate 映射"]
|
||||
GetAll --> End(["返回 JSON"])
|
||||
GetOffer --> End
|
||||
GetAnswer --> End
|
||||
GetCandidate --> End
|
||||
PostOffer --> End
|
||||
PostAnswer --> End
|
||||
PostCandidate --> End
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/class/httphandler.ts:128-145](file://src/class/httphandler.ts#L128-L145)
|
||||
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
|
||||
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
|
||||
|
||||
章节来源
|
||||
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
|
||||
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
|
||||
|
||||
### 4) 自定义信令处理器开发指南
|
||||
- 设计原则
|
||||
- 单一职责:每个处理器只负责一类消息或一类资源
|
||||
- 可组合:通过中间件/装饰器模式复用鉴权、日志、限流
|
||||
- 可替换:对外暴露一致的 API,内部可替换实现
|
||||
- 消息路由与处理流程
|
||||
- WebSocket:在 WSSignaling 的 switch 分支中新增 case,调用处理器对应方法
|
||||
- HTTP:在 signaling 路由中注册新路由,处理器中实现鉴权与数据持久化
|
||||
- 客户端集成
|
||||
- 在 signaling.js 中新增发送与接收事件,确保与服务端消息结构一致
|
||||
- 在 peer.js 或业务层订阅事件并驱动 WebRTC
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as "应用层"
|
||||
participant WS as "WSSignaling"
|
||||
participant WH as "自定义处理器"
|
||||
participant HH as "自定义 HTTP 处理器"
|
||||
participant CL as "客户端"
|
||||
App->>WS : "发送自定义消息"
|
||||
WS->>WH : "分发到自定义处理器"
|
||||
WH-->>CL : "广播/回执"
|
||||
App->>HH : "HTTP 请求"
|
||||
HH-->>CL : "返回处理结果"
|
||||
CL-->>App : "事件回调"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/websocket.ts:76-113](file://src/websocket.ts#L76-L113)
|
||||
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
|
||||
- [client/src/signaling.js:152-292](file://client/src/signaling.js#L152-L292)
|
||||
|
||||
章节来源
|
||||
- [src/websocket.ts:6-118](file://src/websocket.ts#L6-L118)
|
||||
- [src/signaling.ts:1-25](file://src/signaling.ts#L1-L25)
|
||||
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
|
||||
|
||||
### 5) 扩展客户端功能(WebRTC 与 UI 组件)
|
||||
- 新增 WebRTC 能力
|
||||
- 在 peer.js 中扩展事件(如 onCustomMessage),并在 signaling.js 中订阅
|
||||
- 如需数据通道,参考 createDataChannel 与 ondatachannel 的使用模式
|
||||
- UI 组件
|
||||
- 基于现有 signaling.js 的事件模型,新增 DOM 事件监听与渲染逻辑
|
||||
- 保持与现有连接/断开/offer/answer/candidate 事件的兼容
|
||||
|
||||
章节来源
|
||||
- [client/src/peer.js:1-188](file://client/src/peer.js#L1-L188)
|
||||
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
|
||||
|
||||
### 6) 插件系统与扩展点设计原则
|
||||
- 扩展点
|
||||
- WebSocket 消息分发:在 WSSignaling 的 switch 中新增 case
|
||||
- HTTP 路由:在 signaling 路由中新增子路由
|
||||
- 处理器内部:在 websockethandler/httphandler 中新增处理函数
|
||||
- 设计原则
|
||||
- 向后兼容:新增字段建议可选,避免破坏既有消息结构
|
||||
- 版本化:通过消息中的 version 字段或路由版本号区分
|
||||
- 强约束:严格校验必填字段,失败时返回明确错误码
|
||||
- 可观测:为新消息类型增加日志与指标埋点
|
||||
|
||||
章节来源
|
||||
- [src/websocket.ts:76-113](file://src/websocket.ts#L76-L113)
|
||||
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
|
||||
- [src/class/websockethandler.ts:76-338](file://src/class/websockethandler.ts#L76-L338)
|
||||
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
|
||||
|
||||
### 7) 实际扩展示例与最佳实践
|
||||
- 示例:新增“自定义消息”类型
|
||||
- 服务端
|
||||
- 在 WSSignaling 的 switch 中新增 case:"custom"
|
||||
- 在 websockethandler 中实现 onCustom,完成路由与广播
|
||||
- 在 httphandler 中新增 postCustom/getCustom,维护映射
|
||||
- 在 signaling 路由中注册 /signaling/custom
|
||||
- 客户端
|
||||
- 在 signaling.js 中新增 sendCustom 与订阅 "custom" 事件
|
||||
- 最佳实践
|
||||
- 消息结构最小化:仅包含必要字段
|
||||
- 错误处理:对缺失字段与非法值返回 4xx/5xx 并记录日志
|
||||
- 幂等性:对重复消息进行去重(基于时间戳或唯一 ID)
|
||||
- 性能:批量消息合并、异步处理、限流与背压
|
||||
|
||||
章节来源
|
||||
- [src/websocket.ts:76-113](file://src/websocket.ts#L76-L113)
|
||||
- [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338)
|
||||
- [src/class/httphandler.ts:398-641](file://src/class/httphandler.ts#L398-L641)
|
||||
- [src/signaling.ts:6-24](file://src/signaling.ts#L6-L24)
|
||||
- [client/src/signaling.js:1-292](file://client/src/signaling.js#L1-L292)
|
||||
|
||||
## 依赖分析
|
||||
- 服务端依赖
|
||||
- Express:HTTP 服务器与路由
|
||||
- ws:WebSocket 服务器
|
||||
- morgan:HTTP 日志
|
||||
- uuid:会话 ID 生成
|
||||
- 客户端依赖
|
||||
- 浏览器原生 fetch/WebSocket
|
||||
- Jest(测试)
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
PKG["服务端 package.json"] --> EXP["express"]
|
||||
PKG --> WS["ws"]
|
||||
PKG --> MORGAN["morgan"]
|
||||
PKG --> UUID["uuid"]
|
||||
CLPKG["客户端 package.json"] --> JEST["jest"]
|
||||
CLPKG --> ESLINT["eslint"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [package.json:14-27](file://package.json#L14-L27)
|
||||
- [client/package.json:9-18](file://client/package.json#L9-L18)
|
||||
|
||||
章节来源
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
- [client/package.json:1-19](file://client/package.json#L1-L19)
|
||||
|
||||
## 性能考量
|
||||
- WebSocket
|
||||
- 心跳间隔与超时阈值可调,避免频繁断线
|
||||
- 大消息拆分与压缩,减少带宽占用
|
||||
- HTTP
|
||||
- fromtime 参数配合增量拉取,降低响应体积
|
||||
- 合理设置轮询间隔,平衡实时性与资源消耗
|
||||
- 通用
|
||||
- 缓存热点数据(如最近 N 条 candidate)
|
||||
- 异步处理耗时操作(如持久化)
|
||||
|
||||
## 故障排查指南
|
||||
- WebSocket 无法连接
|
||||
- 检查 WSSignaling 的连接事件与日志
|
||||
- 确认客户端 URL 与协议(ws/wss)
|
||||
- 消息未到达
|
||||
- 核对 websockethandler 的广播逻辑与角色判断
|
||||
- 确认客户端事件监听是否正确
|
||||
- HTTP 会话异常
|
||||
- 检查 session-id 请求头与会话超时清理
|
||||
- 使用 getAll 接口核对历史消息
|
||||
- 单元测试参考
|
||||
- 使用 websockethandler.test.ts 验证消息路由与广播行为
|
||||
|
||||
章节来源
|
||||
- [src/websocket.ts:27-38](file://src/websocket.ts#L27-L38)
|
||||
- [src/class/websockethandler.ts:97-137](file://src/class/websockethandler.ts#L97-L137)
|
||||
- [src/class/httphandler.ts:218-232](file://src/class/httphandler.ts#L218-L232)
|
||||
- [test/websockethandler.test.ts:1-191](file://test/websockethandler.test.ts#L1-L191)
|
||||
|
||||
## 结论
|
||||
通过明确的扩展点与清晰的处理流程,项目允许以最小改动安全地引入新的信令消息类型与客户端能力。遵循向后兼容、可观测与可测试的原则,可确保扩展的稳定性与演进速度。
|
||||
|
||||
## 附录
|
||||
- 版本与兼容性
|
||||
- 服务端与客户端版本号:3.1.0
|
||||
- 建议在新增字段时保留默认值,避免破坏旧客户端解析
|
||||
- 对于重大变更,建议引入版本字段或路由版本号
|
||||
|
||||
章节来源
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
- [client/package.json:1-19](file://client/package.json#L1-L19)
|
||||
441
.qoder/repowiki/zh/content/开发指南/调试与测试.md
Normal file
441
.qoder/repowiki/zh/content/开发指南/调试与测试.md
Normal file
@@ -0,0 +1,441 @@
|
||||
# 调试与测试
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [package.json](file://package.json)
|
||||
- [jest.config.js](file://jest.config.js)
|
||||
- [src/index.ts](file://src/index.ts)
|
||||
- [test/websockethandler.test.ts](file://test/websockethandler.test.ts)
|
||||
- [test/httphandler.test.ts](file://test/httphandler.test.ts)
|
||||
- [client/package.json](file://client/package.json)
|
||||
- [client/jest.config.js](file://client/jest.config.js)
|
||||
- [client/jest.setup.js](file://client/jest.setup.js)
|
||||
- [client/test/signaling.test.js](file://client/test/signaling.test.js)
|
||||
- [client/test/mocksignaling.js](file://client/test/mocksignaling.js)
|
||||
- [client/test/testutils.js](file://client/test/testutils.js)
|
||||
- [client/test/peerconnection.test.js](file://client/test/peerconnection.test.js)
|
||||
- [src/log.ts](file://src/log.ts)
|
||||
- [run.bat](file://run.bat)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本指南面向开发者与测试工程师,系统化讲解本项目的测试体系与调试方法,覆盖以下主题:
|
||||
- JUnit(在本项目中为 Jest)测试框架的配置与使用,包括单元测试与集成测试的编写规范
|
||||
- 测试环境搭建、测试数据准备与断言策略
|
||||
- WebSocket 与 HTTP 服务的调试技巧(断点设置、日志分析)
|
||||
- 客户端测试:WebRTC 连接测试与信令测试
|
||||
- 模拟对象的使用:mock-socket 与 jest-websocket-mock
|
||||
- 性能测试与压力测试方法
|
||||
- 测试覆盖率报告的生成与分析
|
||||
|
||||
## 项目结构
|
||||
该项目采用前后端分离的测试布局:
|
||||
- 后端(Node/Express + WebSocket/HTTP 信令):位于根目录,测试文件位于 test/ 下
|
||||
- 前端(Web 客户端,含 WebRTC 与信令逻辑):位于 client/ 目录,测试文件位于 client/test/ 下
|
||||
- 根目录与 client/ 目录分别维护独立的 Jest 配置与脚本
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "后端服务"
|
||||
A["src/index.ts<br/>启动 HTTP/HTTPS 与 WebSocket 信令"]
|
||||
B["test/httphandler.test.ts<br/>HTTP 信令集成测试"]
|
||||
C["test/websockethandler.test.ts<br/>WebSocket 信令集成测试"]
|
||||
end
|
||||
subgraph "前端客户端"
|
||||
D["client/test/signaling.test.js<br/>信令端到端测试"]
|
||||
E["client/test/mocksignaling.js<br/>模拟信令管理器"]
|
||||
F["client/test/peerconnection.test.js<br/>WebRTC 连接单元测试"]
|
||||
G["client/jest.config.js<br/>Jest 配置JSDOM 环境"]
|
||||
H["client/jest.setup.js<br/>全局 polyfill 与 mock"]
|
||||
end
|
||||
A --> B
|
||||
A --> C
|
||||
D --> E
|
||||
D --> F
|
||||
G --> D
|
||||
H --> D
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [test/httphandler.test.ts:1-510](file://test/httphandler.test.ts#L1-L510)
|
||||
- [test/websockethandler.test.ts:1-191](file://test/websockethandler.test.ts#L1-L191)
|
||||
- [client/test/signaling.test.js:1-485](file://client/test/signaling.test.js#L1-L485)
|
||||
- [client/test/mocksignaling.js:1-225](file://client/test/mocksignaling.js#L1-L225)
|
||||
- [client/test/peerconnection.test.js:1-251](file://client/test/peerconnection.test.js#L1-L251)
|
||||
- [client/jest.config.js:1-196](file://client/jest.config.js#L1-L196)
|
||||
- [client/jest.setup.js:1-35](file://client/jest.setup.js#L1-L35)
|
||||
|
||||
章节来源
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
- [client/package.json:1-19](file://client/package.json#L1-L19)
|
||||
|
||||
## 核心组件
|
||||
- 后端入口与信令模式选择:根据命令行参数决定 HTTP 或 WebSocket 信令模式,并按模式启动对应信令服务
|
||||
- 前端信令抽象:支持 HTTP 与 WebSocket 两种信令;同时提供 MockSignaling 用于快速验证
|
||||
- WebRTC 连接层:封装 RTCPeerConnection、事件与候选处理
|
||||
- 日志系统:统一的日志级别控制,便于调试与生产输出
|
||||
|
||||
章节来源
|
||||
- [src/index.ts:13-109](file://src/index.ts#L13-L109)
|
||||
- [src/log.ts:1-51](file://src/log.ts#L1-L51)
|
||||
|
||||
## 架构总览
|
||||
下图展示从客户端发起信令到后端处理再到另一客户端接收的关键流程。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ClientA as "客户端A"
|
||||
participant SignalingA as "信令适配(HTTP/WebSocket/Mock)"
|
||||
participant Server as "后端服务(src/index.ts)"
|
||||
participant SignalingB as "信令适配(HTTP/WebSocket/Mock)"
|
||||
participant ClientB as "客户端B"
|
||||
ClientA->>SignalingA : "创建连接/发送Offer"
|
||||
SignalingA->>Server : "POST /offer 或 WebSocket 消息"
|
||||
Server-->>SignalingB : "广播/转发 Offer"
|
||||
SignalingB-->>ClientB : "触发 offer 事件"
|
||||
ClientB->>SignalingB : "发送 Answer/Candidate"
|
||||
SignalingB->>Server : "上报 Answer/Candidate"
|
||||
Server-->>SignalingA : "转发 Answer/Candidate"
|
||||
SignalingA-->>ClientA : "触发 answer/candidate 事件"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [client/test/signaling.test.js:67-208](file://client/test/signaling.test.js#L67-L208)
|
||||
- [test/httphandler.test.ts:71-120](file://test/httphandler.test.ts#L71-L120)
|
||||
- [test/websockethandler.test.ts:52-82](file://test/websockethandler.test.ts#L52-L82)
|
||||
- [src/index.ts:75-88](file://src/index.ts#L75-L88)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 后端 HTTP 信令测试(集成测试)
|
||||
- 使用 @jest-mock/express 提供的 getMockReq/getMockRes 构造 Express 请求/响应对象
|
||||
- 通过 createSession/checkSessionId/createConnection/post*/getAll/delete* 等接口组合,验证公共/私有模式下的消息流转
|
||||
- 关键断言点:
|
||||
- 连接创建时返回的 polite 标识
|
||||
- Offer/Answer/Candidate 的收发与过滤规则
|
||||
- 超时清理与会话删除行为
|
||||
- 超时场景通过循环调用 checkSessionId 并等待超时实现
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["开始"]) --> CreateSess1["创建会话A"]
|
||||
CreateSess1 --> CreateSess2["创建会话B"]
|
||||
CreateSess2 --> ConnA["会话A 创建连接"]
|
||||
ConnA --> ConnB["会话B 创建连接"]
|
||||
ConnB --> Offer["会话A 发送 Offer"]
|
||||
Offer --> ExpectOffer["会话B 收到 Offer"]
|
||||
ExpectOffer --> Answer["会话B 发送 Answer"]
|
||||
Answer --> ExpectAnswer["会话A 收到 Answer"]
|
||||
ExpectAnswer --> Candidate["双方发送 Candidate"]
|
||||
Candidate --> Cleanup["删除连接/会话"]
|
||||
Cleanup --> End(["结束"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [test/httphandler.test.ts:45-153](file://test/httphandler.test.ts#L45-L153)
|
||||
- [test/httphandler.test.ts:194-249](file://test/httphandler.test.ts#L194-L249)
|
||||
|
||||
章节来源
|
||||
- [test/httphandler.test.ts:1-510](file://test/httphandler.test.ts#L1-L510)
|
||||
|
||||
### 后端 WebSocket 信令测试(集成测试)
|
||||
- 使用 jest-websocket-mock 搭建本地 WebSocket 服务器,模拟真实信令通道
|
||||
- 验证公共/私有模式下 connect/polite、offer/answer、candidate、disconnect 的消息一致性
|
||||
- 使用 toReceiveMessage/toHaveReceivedMessages 断言消息内容与顺序
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant WS as "WS 服务器(jest-websocket-mock)"
|
||||
participant Handler as "wsHandler"
|
||||
participant C1 as "客户端1"
|
||||
participant C2 as "客户端2"
|
||||
C1->>WS : "连接"
|
||||
C2->>WS : "连接"
|
||||
C1->>Handler : "onConnect(connectionId1)"
|
||||
Handler-->>WS : "广播 connect(polite=true)"
|
||||
WS-->>C1 : "收到 connect"
|
||||
C2->>Handler : "onConnect(connectionId1)"
|
||||
Handler-->>WS : "广播 connect(polite=true)"
|
||||
WS-->>C2 : "收到 connect"
|
||||
C1->>Handler : "onOffer({connectionId1,sdp})"
|
||||
Handler-->>WS : "广播 offer"
|
||||
WS-->>C2 : "收到 offer"
|
||||
C2->>Handler : "onAnswer(...)"
|
||||
Handler-->>WS : "广播 answer"
|
||||
WS-->>C1 : "收到 answer"
|
||||
C1->>Handler : "onDisconnect(...)"
|
||||
Handler-->>WS : "广播 disconnect"
|
||||
WS-->>C1 : "收到 disconnect"
|
||||
WS-->>C2 : "收到 disconnect"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [test/websockethandler.test.ts:9-99](file://test/websockethandler.test.ts#L9-L99)
|
||||
- [test/websockethandler.test.ts:101-190](file://test/websockethandler.test.ts#L101-L190)
|
||||
|
||||
章节来源
|
||||
- [test/websockethandler.test.ts:1-191](file://test/websockethandler.test.ts#L1-L191)
|
||||
|
||||
### 前端信令测试(端到端测试)
|
||||
- 支持三种模式:mock、http、websocket
|
||||
- 使用 jest-dev-server 启动本地服务,或使用 MockSignaling 进行纯内存测试
|
||||
- 通过自定义事件 connect/offer/answer/candidate/disconnect 驱动断言
|
||||
- 使用 waitFor/sleep 辅助异步等待与稳定测试节奏
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Test as "Jest 测试"
|
||||
participant DevServer as "本地服务(可选)"
|
||||
participant Signaling as "Signaling/WS 签名器"
|
||||
participant PeerA as "Peer A"
|
||||
participant PeerB as "Peer B"
|
||||
Test->>DevServer : "启动(可选)"
|
||||
Test->>Signaling : "start()"
|
||||
Test->>PeerA : "createConnection()"
|
||||
Test->>PeerB : "createConnection()"
|
||||
Test->>PeerA : "sendOffer()"
|
||||
PeerA-->>PeerB : "触发 offer 事件"
|
||||
Test->>PeerB : "sendAnswer()"
|
||||
PeerB-->>PeerA : "触发 answer 事件"
|
||||
Test->>PeerB : "sendCandidate()"
|
||||
PeerB-->>PeerA : "触发 candidate 事件"
|
||||
Test->>PeerA : "deleteConnection()"
|
||||
PeerA-->>PeerB : "触发 disconnect 事件"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [client/test/signaling.test.js:23-65](file://client/test/signaling.test.js#L23-L65)
|
||||
- [client/test/signaling.test.js:67-208](file://client/test/signaling.test.js#L67-L208)
|
||||
- [client/test/signaling.test.js:221-264](file://client/test/signaling.test.js#L221-L264)
|
||||
|
||||
章节来源
|
||||
- [client/test/signaling.test.js:1-485](file://client/test/signaling.test.js#L1-L485)
|
||||
|
||||
### 前端模拟信令管理器(MockSignaling)
|
||||
- 公共模式:任意两个 Signaling 实例之间互相广播消息
|
||||
- 私有模式:基于 connectionId 维护对等集合,仅在双方均已打开连接时才互相广播
|
||||
- 提供延迟以模拟网络时延,便于验证事件顺序与时序
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class MockSignaling {
|
||||
+interval
|
||||
+start()
|
||||
+stop()
|
||||
+createConnection(connectionId)
|
||||
+deleteConnection(connectionId)
|
||||
+sendOffer(connectionId, sdp)
|
||||
+sendAnswer(connectionId, sdp)
|
||||
+sendCandidate(connectionId, candidate, sdpMLineIndex, sdpMid)
|
||||
}
|
||||
class MockPublicSignalingManager {
|
||||
+list : Set
|
||||
+add(signaling)
|
||||
+remove(signaling)
|
||||
+openConnection(signaling, connectionId)
|
||||
+closeConnection(signaling, connectionId)
|
||||
+offer(owner, data)
|
||||
+answer(owner, data)
|
||||
+candidate(owner, data)
|
||||
}
|
||||
class MockPrivateSignalingManager {
|
||||
+connectionIds : Map
|
||||
+openConnection(signaling, connectionId)
|
||||
+closeConnection(signaling, connectionId)
|
||||
+offer(owner, data)
|
||||
+answer(owner, data)
|
||||
+candidate(owner, data)
|
||||
-findList(owner, connectionId)
|
||||
}
|
||||
MockSignaling --> MockPublicSignalingManager : "公共模式"
|
||||
MockSignaling --> MockPrivateSignalingManager : "私有模式"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [client/test/mocksignaling.js:10-52](file://client/test/mocksignaling.js#L10-L52)
|
||||
- [client/test/mocksignaling.js:54-113](file://client/test/mocksignaling.js#L54-L113)
|
||||
- [client/test/mocksignaling.js:115-224](file://client/test/mocksignaling.js#L115-L224)
|
||||
|
||||
章节来源
|
||||
- [client/test/mocksignaling.js:1-225](file://client/test/mocksignaling.js#L1-L225)
|
||||
|
||||
### WebRTC 连接单元测试
|
||||
- 验证 Peer 对象在不同场景下的事件触发与状态变化
|
||||
- 包括添加轨道/Transceiver/DataChannel 自动触发 Offer
|
||||
- 在不同角色(polite/impolite)下正确触发 Answer
|
||||
- 候选收集与接受的条件判断
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Init["初始化 Peer(config)"] --> AddTrack["添加轨道/Transceiver/DataChannel"]
|
||||
AddTrack --> FireOffer["触发 sendoffer 事件"]
|
||||
FireOffer --> OnOffer["收到 Offer 描述"]
|
||||
OnOffer --> MaybeAnswer{"是否需要 Answer?"}
|
||||
MaybeAnswer --> |是| FireAnswer["触发 sendanswer 事件"]
|
||||
MaybeAnswer --> |否| Skip["不触发 Answer"]
|
||||
FireAnswer --> OnAnswer["收到 Answer 描述"]
|
||||
OnAnswer --> Negotiate["触发 negotiated 事件"]
|
||||
AddTrack --> Candidate["收集 ICE Candidate"]
|
||||
Candidate --> Accept{"已有远端描述?"}
|
||||
Accept --> |是| Store["保存候选"]
|
||||
Accept --> |否| Drop["丢弃候选"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [client/test/peerconnection.test.js:69-122](file://client/test/peerconnection.test.js#L69-L122)
|
||||
- [client/test/peerconnection.test.js:124-188](file://client/test/peerconnection.test.js#L124-L188)
|
||||
- [client/test/peerconnection.test.js:222-238](file://client/test/peerconnection.test.js#L222-L238)
|
||||
|
||||
章节来源
|
||||
- [client/test/peerconnection.test.js:1-251](file://client/test/peerconnection.test.js#L1-L251)
|
||||
|
||||
## 依赖分析
|
||||
- 根目录测试依赖
|
||||
- jest、jest-websocket-mock、@jest-mock/express、ts-jest、typescript
|
||||
- 客户端测试依赖
|
||||
- jest、jest-environment-jsdom、jest-dev-server、node-fetch、@jest/globals
|
||||
- 关键配置
|
||||
- 根目录 jest.config.js 开启覆盖率收集,使用 ts-jest 转换 TS
|
||||
- 客户端 jest.config.js 使用 JSDOM 环境,加载 jest.setup.js 注入 polyfill 与 WebRTC mock
|
||||
|
||||
章节来源
|
||||
- [package.json:28-46](file://package.json#L28-L46)
|
||||
- [client/package.json:9-18](file://client/package.json#L9-L18)
|
||||
- [jest.config.js:19-34](file://jest.config.js#L19-L34)
|
||||
- [client/jest.config.js:18-25](file://client/jest.config.js#L18-L25)
|
||||
- [client/jest.config.js:130-131](file://client/jest.config.js#L130-L131)
|
||||
|
||||
## 性能考虑
|
||||
- 单元测试应避免真实网络 I/O,优先使用 Mock 与内存态模拟
|
||||
- 集成测试中,WebSocket/HTTP 信令测试通过本地 mock 降低外部依赖
|
||||
- WebRTC 测试通过自定义事件与延迟函数控制执行节奏,避免非确定性
|
||||
- 大规模并发场景建议拆分测试套件,使用并行 worker 与独立端口运行多实例
|
||||
|
||||
## 故障排查指南
|
||||
- 启动与调试
|
||||
- 使用 run.bat 构建并启动服务,同时开启日志级别以便定位问题
|
||||
- 通过 src/log.ts 的日志级别控制,将日志提升至 info 或更高等级
|
||||
- WebSocket 调试
|
||||
- 在 jest-websocket-mock 中断言 toReceiveMessage/toHaveReceivedMessages,确保消息类型与字段匹配
|
||||
- 若出现“未收到消息”,检查信令管理器是否正确广播以及客户端监听是否生效
|
||||
- HTTP 信令调试
|
||||
- 使用 @jest-mock/express 的请求/响应对象构造,逐个接口断言状态码与 JSON 结果
|
||||
- 注意会话超时逻辑,必要时增加等待时间或调整超时阈值
|
||||
- 客户端测试
|
||||
- 若使用 jest-dev-server 启动本地服务,注意端口占用与进程回收
|
||||
- 使用 waitFor/sleep 稳定异步事件,避免竞态条件导致断言失败
|
||||
- 日志分析
|
||||
- 利用 setLogLevel 与 log 输出统一格式的时间戳与级别前缀,结合断点逐步缩小范围
|
||||
|
||||
章节来源
|
||||
- [run.bat:1-17](file://run.bat#L1-L17)
|
||||
- [src/log.ts:9-24](file://src/log.ts#L9-L24)
|
||||
- [client/test/signaling.test.js:23-65](file://client/test/signaling.test.js#L23-L65)
|
||||
- [client/test/testutils.js:3-15](file://client/test/testutils.js#L3-L15)
|
||||
|
||||
## 结论
|
||||
本项目提供了完善的测试与调试基础设施:
|
||||
- 后端通过 HTTP/WebSocket 两种信令模式的集成测试,覆盖公共/私有模式的消息流转与超时清理
|
||||
- 前端通过 MockSignaling 与 jest-dev-server 支持端到端测试,结合 WebRTC 单元测试保障连接稳定性
|
||||
- Jest 配置与覆盖率收集已就绪,便于持续改进质量与回归保障
|
||||
|
||||
## 附录
|
||||
|
||||
### 测试环境搭建与运行
|
||||
- 根目录测试
|
||||
- 安装依赖后,使用 npm 脚本运行测试与覆盖率收集
|
||||
- 客户端测试
|
||||
- 在 client/ 目录下安装依赖,使用 npm 脚本运行前端测试
|
||||
- 覆盖率报告
|
||||
- 根目录与客户端目录均启用覆盖率收集,生成 coverage 报告目录
|
||||
|
||||
章节来源
|
||||
- [package.json:5-12](file://package.json#L5-L12)
|
||||
- [client/package.json:5-8](file://client/package.json#L5-L8)
|
||||
- [jest.config.js:25-26](file://jest.config.js#L25-L26)
|
||||
- [client/jest.config.js:24-25](file://client/jest.config.js#L24-L25)
|
||||
|
||||
### 测试数据准备与断言规范
|
||||
- HTTP 信令
|
||||
- 使用 getMockReq/getMockRes 构造请求体与头部,断言 res.json/res.sendStatus 的返回值
|
||||
- 通过 getAll/getOffer/getAnswer/getCandidate 验证消息队列状态
|
||||
- WebSocket 信令
|
||||
- 使用 jest-websocket-mock 的 toReceiveMessage/toHaveReceivedMessages 断言消息
|
||||
- 前端信令
|
||||
- 使用自定义事件断言,结合 waitFor/sleep 控制异步时机
|
||||
- WebRTC
|
||||
- 通过事件监听与内部状态断言,验证 Offer/Answer/Candidate 的触发与接受条件
|
||||
|
||||
章节来源
|
||||
- [test/httphandler.test.ts:14-33](file://test/httphandler.test.ts#L14-L33)
|
||||
- [test/websockethandler.test.ts:17-28](file://test/websockethandler.test.ts#L17-L28)
|
||||
- [client/test/signaling.test.js:67-208](file://client/test/signaling.test.js#L67-L208)
|
||||
- [client/test/peerconnection.test.js:69-122](file://client/test/peerconnection.test.js#L69-L122)
|
||||
|
||||
### WebSocket 与 HTTP 服务调试技巧
|
||||
- 断点设置
|
||||
- 在 src/index.ts 的信令分支处设置断点,观察 mode/type 参数对行为的影响
|
||||
- 在 wsHandler/httphandler 的消息处理函数中设置断点,验证输入与输出
|
||||
- 日志分析
|
||||
- 使用 src/log.ts 的 log 函数输出关键路径,结合 setLogLevel 提升日志级别
|
||||
- 在客户端测试中,利用 waitFor/sleep 精确控制事件时序,便于定位异常
|
||||
|
||||
章节来源
|
||||
- [src/index.ts:75-88](file://src/index.ts#L75-L88)
|
||||
- [src/log.ts:30-50](file://src/log.ts#L30-L50)
|
||||
- [client/test/testutils.js:3-15](file://client/test/testutils.js#L3-L15)
|
||||
|
||||
### 客户端测试:WebRTC 连接与信令
|
||||
- 连接测试
|
||||
- 通过 Peer 对象的 addTrack/addTransceiver/createDataChannel 触发 Offer
|
||||
- 在不同角色下验证 Answer 的触发时机
|
||||
- 信令测试
|
||||
- 使用 MockSignaling 或 jest-dev-server 启动的服务进行端到端验证
|
||||
- 断言 connect/offer/answer/candidate/disconnect 事件的完整性
|
||||
|
||||
章节来源
|
||||
- [client/test/peerconnection.test.js:8-30](file://client/test/peerconnection.test.js#L8-L30)
|
||||
- [client/test/signaling.test.js:67-208](file://client/test/signaling.test.js#L67-L208)
|
||||
|
||||
### 模拟对象使用指南
|
||||
- jest-websocket-mock
|
||||
- 用于 WebSocket 信令的本地服务器模拟,断言消息收发
|
||||
- @jest-mock/express
|
||||
- 用于 HTTP 信令的请求/响应对象构造与断言
|
||||
- jest-dev-server
|
||||
- 用于启动本地服务参与端到端测试
|
||||
- WebRTC mock
|
||||
- 在 client/jest.setup.js 中注入 RTCPeerConnection/SessionDescription/IceCandidate/ResizeObserver 等 polyfill
|
||||
|
||||
章节来源
|
||||
- [test/websockethandler.test.ts:1](file://test/websockethandler.test.ts#L1)
|
||||
- [test/httphandler.test.ts:1](file://test/httphandler.test.ts#L1)
|
||||
- [client/test/signaling.test.js:3](file://client/test/signaling.test.js#L3)
|
||||
- [client/jest.setup.js:21-35](file://client/jest.setup.js#L21-L35)
|
||||
|
||||
### 性能测试与压力测试方法
|
||||
- 单元测试阶段保持无外部依赖,使用 Mock 与同步断言
|
||||
- 集成测试阶段,通过多个客户端并发创建连接、发送 Offer/Answer/Candidate,统计事件完成时间
|
||||
- 使用独立端口与进程并行运行多实例,评估吞吐与延迟
|
||||
- 建议在 CI 中开启覆盖率报告,持续监控代码覆盖度
|
||||
|
||||
### 测试覆盖率报告生成与分析
|
||||
- 根目录与客户端目录均启用覆盖率收集,输出目录为 coverage
|
||||
- 可在 CI 中配置覆盖率阈值,确保关键路径被覆盖
|
||||
|
||||
章节来源
|
||||
- [jest.config.js:19-26](file://jest.config.js#L19-L26)
|
||||
- [client/jest.config.js:18-25](file://client/jest.config.js#L18-L25)
|
||||
316
.qoder/repowiki/zh/content/开发指南/贡献指南.md
Normal file
316
.qoder/repowiki/zh/content/开发指南/贡献指南.md
Normal file
@@ -0,0 +1,316 @@
|
||||
# 贡献指南
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [package.json](file://package.json)
|
||||
- [tsconfig.json](file://tsconfig.json)
|
||||
- [.eslintrc.cjs](file://.eslintrc.cjs)
|
||||
- [jest.config.js](file://jest.config.js)
|
||||
- [src/index.ts](file://src/index.ts)
|
||||
- [src/server.ts](file://src/server.ts)
|
||||
- [src/class/websockethandler.ts](file://src/class/websockethandler.ts)
|
||||
- [src/class/httphandler.ts](file://src/class/httphandler.ts)
|
||||
- [.gitignore](file://.gitignore)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本贡献指南面向希望参与“视频流服务器”项目的开发者,提供从 Fork、Clone、分支与提交、Pull Request 到代码审查、Issue 提交、版本发布与变更日志维护、社区行为准则与协作规范的全流程说明。同时给出新贡献者的入门建议与资源链接,帮助快速上手。
|
||||
|
||||
## 项目结构
|
||||
该项目采用前后端一体化的 Node/Express + TypeScript 后端,内置静态前端资源与测试框架,支持 WebSocket 与 HTTP 两种信令模式,具备会话管理、WebRTC 信令转发、文件上传与 Swagger 文档能力。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "后端"
|
||||
IDX["入口: src/index.ts"]
|
||||
SRV["服务器: src/server.ts"]
|
||||
WS["WebSocket处理器: src/class/websockethandler.ts"]
|
||||
HTTP["HTTP处理器: src/class/httphandler.ts"]
|
||||
end
|
||||
subgraph "前端"
|
||||
PUB["静态资源: client/public/**/*"]
|
||||
SRC["前端模块: client/src/**/*"]
|
||||
end
|
||||
subgraph "工具与配置"
|
||||
PKG["包脚本: package.json"]
|
||||
TSC["编译配置: tsconfig.json"]
|
||||
ESL["代码规范: .eslintrc.cjs"]
|
||||
JST["测试配置: jest.config.js"]
|
||||
GIT["忽略规则: .gitignore"]
|
||||
end
|
||||
IDX --> SRV
|
||||
SRV --> WS
|
||||
SRV --> HTTP
|
||||
SRV --> PUB
|
||||
SRV --> SRC
|
||||
PKG --> TSC
|
||||
PKG --> ESL
|
||||
PKG --> JST
|
||||
PKG --> GIT
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
|
||||
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [.gitignore:1-187](file://.gitignore#L1-L187)
|
||||
|
||||
**章节来源**
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [.gitignore:1-187](file://.gitignore#L1-L187)
|
||||
|
||||
## 核心组件
|
||||
- 入口与启动
|
||||
- 通过命令行参数解析与 HTTPS/HTTP 服务启动,支持 WebSocket 或 HTTP 信令模式,以及公共/私有通信模式。
|
||||
- 服务器与路由
|
||||
- Express 应用挂载 CORS、日志中间件、静态资源、Swagger 文档、上传接口与信令路由。
|
||||
- WebSocket 信令
|
||||
- 实现 1 对多(主持人/参与者)模式下的 offer/answer/candidate 转发、广播、心跳检测与断线清理。
|
||||
- HTTP 信令
|
||||
- 基于轮询的信令 API,提供会话创建、连接管理、offer/answer/candidate 获取与断线记录。
|
||||
- 测试与规范
|
||||
- Jest 测试配置与覆盖率收集;ESLint TypeScript 规则;TypeScript 编译配置。
|
||||
|
||||
**章节来源**
|
||||
- [src/index.ts:1-109](file://src/index.ts#L1-L109)
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
|
||||
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
|
||||
## 架构总览
|
||||
后端以 Express 为核心,根据信令类型选择 WebSocket 或 HTTP 处理器;静态资源与前端模块通过 Express 提供;测试与规范工具贯穿开发流程。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
Client["浏览器/客户端"] --> Mode{"信令模式"}
|
||||
Mode --> |WebSocket| WS["WebSocket处理器<br/>websockethandler.ts"]
|
||||
Mode --> |HTTP| HTTP["HTTP处理器<br/>httphandler.ts"]
|
||||
WS --> Server["Express服务器<br/>server.ts"]
|
||||
HTTP --> Server
|
||||
Server --> Static["静态资源<br/>client/public/**/*"]
|
||||
Server --> Front["前端模块<br/>client/src/**/*"]
|
||||
Server --> Swagger["Swagger文档"]
|
||||
Server --> Upload["头像上传API"]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [src/server.ts:1-90](file://src/server.ts#L1-L90)
|
||||
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
|
||||
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### WebSocket 信令处理流程
|
||||
WebSocket 处理器支持公共/私有模式,实现连接、断开、offer/answer/candidate 转发与广播、心跳检测与断线清理。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as "客户端"
|
||||
participant S as "WebSocket处理器"
|
||||
participant G as "连接组"
|
||||
participant H as "主持人"
|
||||
participant P as "参与者"
|
||||
C->>S : "connect(connectionId)"
|
||||
S->>G : "创建/加入连接组"
|
||||
S-->>C : "connect(角色, participantId)"
|
||||
C->>S : "offer/answer/candidate"
|
||||
alt 私有模式
|
||||
S->>H : "主持人接收转发"
|
||||
S->>P : "参与者接收转发"
|
||||
else 公共模式
|
||||
S->>G : "广播到其他客户端"
|
||||
end
|
||||
C->>S : "disconnect"
|
||||
S->>G : "清理连接组并通知"
|
||||
S-->>C : "disconnect"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [src/class/websockethandler.ts:145-206](file://src/class/websockethandler.ts#L145-L206)
|
||||
- [src/class/websockethandler.ts:214-338](file://src/class/websockethandler.ts#L214-L338)
|
||||
- [src/class/websockethandler.ts:448-473](file://src/class/websockethandler.ts#L448-L473)
|
||||
|
||||
**章节来源**
|
||||
- [src/class/websockethandler.ts:1-479](file://src/class/websockethandler.ts#L1-L479)
|
||||
|
||||
### HTTP 信令处理流程
|
||||
HTTP 处理器提供会话与连接管理、offer/answer/candidate 获取、断线记录与全量信令拉取。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Handler as "HTTP处理器"
|
||||
participant Store as "内存存储"
|
||||
participant Other as "其他会话/连接"
|
||||
Client->>Handler : "PUT /signaling (创建会话)"
|
||||
Handler->>Store : "初始化会话映射"
|
||||
Handler-->>Client : "{ sessionId }"
|
||||
Client->>Handler : "PUT /signaling/connection (创建连接)"
|
||||
Handler->>Store : "登记连接ID与配对"
|
||||
Handler-->>Client : "{ connectionId, polite }"
|
||||
Client->>Handler : "GET /signaling/offer?fromtime"
|
||||
Handler->>Store : "按模式过滤并返回offer列表"
|
||||
Client->>Handler : "GET /signaling (全量信令)"
|
||||
Handler->>Store : "聚合连接/断线/offer/answer/candidate"
|
||||
Handler-->>Client : "{ messages, datetime }"
|
||||
Client->>Handler : "DELETE /signaling/connection"
|
||||
Handler->>Store : "清理连接与配对"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [src/class/httphandler.ts:664-783](file://src/class/httphandler.ts#L664-L783)
|
||||
- [src/class/httphandler.ts:492-641](file://src/class/httphandler.ts#L492-L641)
|
||||
|
||||
**章节来源**
|
||||
- [src/class/httphandler.ts:1-800](file://src/class/httphandler.ts#L1-L800)
|
||||
|
||||
### 代码规范与测试
|
||||
- ESLint 规则启用 TypeScript 推荐规则与 Jest 推荐规则,强制分号与多余分号检查。
|
||||
- Jest 配置启用覆盖率收集、TS 转换、Node 环境与测试匹配规则。
|
||||
- TypeScript 编译配置输出至 build 目录,源码位于 src,测试位于 test。
|
||||
|
||||
**章节来源**
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
|
||||
## 依赖关系分析
|
||||
- 后端运行时依赖:Express、WS、CORS、Morgan、Multer、Swagger。
|
||||
- 开发依赖:Jest、TS-Jest、ESLint、TypeScript、pkg 等。
|
||||
- 构建与打包:通过 TypeScript 编译与 pkg 配置,打包静态资源与前端模块。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
PKG["package.json"] --> DEPS["运行时依赖"]
|
||||
PKG --> DEVDEPS["开发依赖"]
|
||||
PKG --> BIN["构建与打包配置"]
|
||||
BIN --> TSC["tsconfig.json"]
|
||||
BIN --> ESL["eslint配置"]
|
||||
BIN --> JST["jest配置"]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
- [tsconfig.json:1-13](file://tsconfig.json#L1-L13)
|
||||
- [.eslintrc.cjs:1-25](file://.eslintrc.cjs#L1-L25)
|
||||
- [jest.config.js:1-196](file://jest.config.js#L1-L196)
|
||||
|
||||
**章节来源**
|
||||
- [package.json:1-60](file://package.json#L1-L60)
|
||||
|
||||
## 性能考量
|
||||
- WebSocket 心跳与超时:处理器内置心跳检测与超时断开逻辑,避免僵尸连接占用资源。
|
||||
- HTTP 轮询:提供 fromtime 参数过滤增量消息,降低带宽与计算压力。
|
||||
- 日志与中间件:morgan 日志级别可配置,建议在生产环境调整为合适级别。
|
||||
- 静态资源:静态目录与前端模块统一托管,确保缓存与压缩策略一致。
|
||||
|
||||
**章节来源**
|
||||
- [src/class/websockethandler.ts:404-430](file://src/class/websockethandler.ts#L404-L430)
|
||||
- [src/server.ts:17-20](file://src/server.ts#L17-L20)
|
||||
|
||||
## 故障排查指南
|
||||
- 启动失败
|
||||
- 检查证书文件路径与权限(HTTPS 模式),确认端口占用与网络接口。
|
||||
- 信令异常
|
||||
- 确认信令模式(WebSocket/HTTP)与通信模式(public/private)配置一致。
|
||||
- 查看日志输出定位连接组状态与消息转发问题。
|
||||
- 测试失败
|
||||
- 使用 Jest 覆盖率报告定位未覆盖路径,修正测试用例与模拟。
|
||||
- 规范检查
|
||||
- 运行 ESLint 并修复规则冲突,确保提交前通过静态检查。
|
||||
|
||||
**章节来源**
|
||||
- [src/index.ts:52-91](file://src/index.ts#L52-L91)
|
||||
- [src/server.ts:25-42](file://src/server.ts#L25-L42)
|
||||
- [jest.config.js:19-26](file://jest.config.js#L19-L26)
|
||||
- [.eslintrc.cjs:18-23](file://.eslintrc.cjs#L18-L23)
|
||||
|
||||
## 结论
|
||||
本指南提供了从开发环境准备到贡献流程、代码审查、Issue 规范、版本发布与变更日志维护、社区协作的完整实践路径。建议贡献者在提交前完成本地测试与规范检查,并遵循分支命名与提交信息格式,确保高质量交付。
|
||||
|
||||
## 附录
|
||||
|
||||
### 代码贡献流程
|
||||
- Fork 仓库
|
||||
- 在代码托管平台执行 Fork 操作,获得个人副本。
|
||||
- Clone 与安装
|
||||
- 克隆到本地,安装依赖并运行开发脚本。
|
||||
- 分支与提交
|
||||
- 基于主分支创建特性分支,遵循分支命名规范与提交信息格式。
|
||||
- Pull Request
|
||||
- 提交 PR,填写模板信息,等待审查与合并。
|
||||
|
||||
**章节来源**
|
||||
- [package.json:5-12](file://package.json#L5-L12)
|
||||
|
||||
### 分支命名规范与提交信息格式
|
||||
- 分支命名
|
||||
- feat/xxx:新增功能
|
||||
- fix/xxx:缺陷修复
|
||||
- docs/xxx:文档更新
|
||||
- refactor/xxx:重构
|
||||
- test/xxx:测试相关
|
||||
- 提交信息格式
|
||||
- 类型(scope): 描述
|
||||
- 例如:feat(server): 支持自定义日志级别
|
||||
|
||||
### 代码审查标准与流程
|
||||
- 审查清单
|
||||
- 功能正确性与边界条件
|
||||
- 性能影响与资源占用
|
||||
- 日志与错误处理
|
||||
- 单元测试覆盖率
|
||||
- 规范检查通过
|
||||
- 审查流程
|
||||
- 提交 PR → 指派审查者 → 评论与修改 → 合并
|
||||
|
||||
### Issue 提交规范
|
||||
- Bug 报告
|
||||
- 环境信息、复现步骤、期望/实际结果、日志片段
|
||||
- 功能请求
|
||||
- 背景、需求描述、影响范围、优先级建议
|
||||
|
||||
### 版本发布与变更日志维护
|
||||
- 版本号
|
||||
- 遵循语义化版本:主版本.次版本.修订
|
||||
- 变更日志
|
||||
- 按版本记录新增、修复、变更与废弃项,标注影响与迁移指引
|
||||
|
||||
### 社区行为准则与协作规范
|
||||
- 尊重与包容:保持友善与专业
|
||||
- 明确沟通:使用清晰、简洁的语言
|
||||
- 合规贡献:遵守开源许可证与安全政策
|
||||
|
||||
### 新贡献者入门指导与资源链接
|
||||
- 环境准备
|
||||
- Node.js、TypeScript、Git 基础
|
||||
- 本地运行
|
||||
- 使用开发脚本启动服务,访问静态页面与 Swagger 文档
|
||||
- 学习资源
|
||||
- Express、WebSocket、WebRTC 信令基础
|
||||
- Jest 与 ESLint 使用指南
|
||||
Reference in New Issue
Block a user