基础知识
什么是 Node.js(简称 Node)
Node.js 是一个开源、跨平台的 JavaScript 运行时环境,允许开发者在服务器端运行 JavaScript 代码。它是基于 Chrome V8 引擎构建的,可以执行 JavaScript 代码外部的浏览器环境。Node.js 使用事件驱动、非阻塞 I/O 模型,使其轻量且高效,非常适合构建数据密集型的实时应用程序。
什么是 TypeScript(简称 TS)
TypeScript 是 JavaScript 的一个超集,它添加了可选的静态类型检查功能。TypeScript 设计的目的是开发大型应用程序,并且随着时间的推移它被转译成 JavaScript。由于它提供了强大的类型系统和对 ES6+ 的支持,TypeScript 能够帮助开发者更有效地捕获错误,并提供更好的编辑器支持,包括代码自动完成、接口导航和重构。
什么是 Fastify
Fastify 是一个高性能和低开销的 Node.js web 框架,专注于提供最快的开发体验。它提供了一个简洁的开发模型,支持快速编写服务器端逻辑,并且内置了路由、插件系统等功能。Fastify 的设计哲学是尽可能地减少开销,同时提供丰富的功能和插件,使得开发高性能的 web 应用和 API 变得简单。
什么是 WebSocket
WebSocket 是一种网络通信协议,提供了全双工通信渠道,允许服务器和客户端之间进行实时、双向的数据传输。与 HTTP 不同,WebSocket 在建立连接后可以保持连接打开,使得数据可以快速地在两端之间传输,这对于需要实时功能的应用程序(如在线游戏、聊天应用、实时通知等)非常有用。
当前 Node.js Web 框架生态
Node.js 的 Web 框架生态丰富多样,包括但不限于:
- Express.js:最流行的 Node.js web 框架之一,以简单、灵活著称,适用于构建各种 web 应用和 API。
- Koa.js:由 Express 的原始创造者开发,旨在更现代化和模块化的方式构建 web 应用,使用 async/await 控制异步代码。
- NestJS:一个用于构建高效、可靠和可扩展的服务器端应用程序的框架。它完全支持 TypeScript,但也允许使用纯 JavaScript。
- Fastify:如前所述,以性能为中心的现代 web 框架。
当然,还有两个全栈框架nuxt和next这两个这几年特别火。但不在这个比对之列,后面业务系统会用nuxt3来写。
emmm,甚至websocket客户端也考虑nuxt3来试试
当前 Node.js WebSocket 框架生态
用于实现 WebSocket 功能的库和框架也很多,其中包括:
- Socket.IO:最广泛使用的 WebSocket 库之一,提供了易于使用的 API 和自动降级功能(在 WebSocket 不可用时退回到长轮询)。
- ws:一个简单且高性能的 WebSocket 库,专注于提供 WebSocket 服务的最小化实现。
- uWebSockets.js:一个高性能的 WebSocket 和 HTTP 库,宣称拥有最快的 WebSocket 性能。
什么是IM
IM(即时通讯,Instant Messaging)是一种实时通信技术,允许用户通过网络发送文本、文件、语音消息、视频通话等信息。IM服务可以在不同的设备上运行,如智能手机、平板电脑、个人电脑等,支持一对一的私聊或者群聊等多人交流形式。IM服务的关键特点是能够提供即时反馈,即用户可以几乎实时地接收和回复消息。
基础的即时通讯(IM)服务为业务提供了一系列的通讯解决方案,能够满足多种应用场景的需求。下面是一些典型的业务场景,展示了基础IM服务的潜在用途:
1. 即时通讯单聊/群聊
- 个人对个人(P2P)通讯:允许用户之间进行私密的文本、图片和视频交流,是社交应用的基础功能。
- 群组通讯:支持创建群组,实现多人之间的信息交流,适用于团队协作、社区讨论等场景。
2. 在线客服
- 客服系统:企业可以通过IM服务实现在线客服系统,让客户能够实时与客服人员沟通,提高服务效率和客户满意度。
- 客户支持:提供即时的客户支持和咨询服务,帮助解决用户问题,增强用户体验。
3. WebRTC 信令服务器
- 实时音视频通话:虽然基础IM服务主要关注文本和简单媒体消息,但它可以作为WebRTC技术的信令服务器,协助建立点对点的实时音视频通话。
- 数据通道:通过WebRTC,可以实现更为复杂的数据传输功能,如文件分享、屏幕共享等。
4. 弹幕聊天
- 直播互动:在视频直播场景中,观众可以通过弹幕实时发表评论和反馈,增加了观众之间以及观众与主播之间的互动性。
- 在线教育:教师和学生可以通过弹幕实时交流,提高在线教育的互动性和参与感。
其他应用场景
- 社交网络:构建社交网络中的即时通讯功能,促进用户之间的互动。
- 协同工作与项目管理:团队成员可以通过即时消息交流,协调工作,提高工作效率。
- 游戏内聊天:在网络游戏中添加聊天功能,增强玩家之间的社交互动。
- 紧急通讯系统:在需要快速响应的场合(如医疗紧急情况、灾害响应等)中,提供实时的通讯手段。
基础的IM服务通过提供实时、可靠的通讯手段,不仅可以增强用户体验,促进信息的即时交流,还可以作为构建更复杂应用和服务的基础。随着业务需求的不断发展,IM服务的功能也会不断扩展,以满足更广泛的应用场景。
我们的基础IM服务也是围绕着这些核心一点点升级迭代,至于能走到哪儿。随缘啦~
Fastify 快速开始
初始化项目
要初始化一个使用 TypeScript 的 Node.js 项目,你需要执行一系列步骤来设置项目的基础。以下是这些步骤的概述:
1. 创建项目目录
首先,创建一个新的目录来存放你的项目文件,并进入这个目录:
mkdir user-hub
cd user-hub
2. 初始化 npm 项目
运行 npm init
命令来创建一个新的 package.json
文件,这个文件将包含项目的元数据和依赖信息。你可以选择使用 -y
参数来快速生成一个默认的 package.json
文件:
npm init -y
3. 安装 TypeScript
作为一个 Node.js 项目,你需要全局或局部安装 TypeScript。局部安装是首选方法,因为它允许项目依赖于特定版本的 TypeScript,确保环境的一致性。使用 npm 安装 TypeScript:
npm install --save-dev typescript
4. 生成 TypeScript 配置文件
运行 tsc --init
命令来生成一个 tsconfig.json
文件,这个文件是 TypeScript 编译器的配置文件。你可能需要根据项目需求调整配置:
npx tsc --init
生成的 tsconfig.json
文件可能需要进行一些调整,例如:
{
"compilerOptions": {
"target": "es2018", // 根据 Node.js 版本选择合适的 ECMAScript 目标版本
"module": "commonjs", // Node.js 使用 CommonJS
"lib": ["es2018"], // 包含的库文件
"outDir": "./dist", // 输出目录
"rootDir": "./src", // 源文件目录
"strict": true, // 启用所有严格类型检查选项
"esModuleInterop": true, // 允许默认导入非 ESModule 模块
"skipLibCheck": true, // 跳过所有声明文件的类型检查
"forceConsistentCasingInFileNames": true // 强制文件名大小写一致
},
"include": ["src/**/*"], // 包含的源文件
"exclude": ["node_modules", "dist"] // 排除的文件
}
5. 安装 Fastify 和相关类型定义
安装 Fastify 以及为 TypeScript 提供的 DefinitelyTyped 类型定义:
npm install fastify
npm install --save-dev @types/node nodemon ts-node ts-node-dev tsconfig-paths
由于 Fastify 是用 TypeScript 编写的,它自带了类型定义,所以不需要安装额外的类型包。
nodemon
- 用途:nodemon是一个工具,用于在检测到文件变化时自动重启Node.js应用。它不是专门为TypeScript设计的,但非常适合用在任何Node.js开发环境中,以提高开发效率。
- 为什么需要:在开发过程中,每次修改代码后手动重启应用会非常繁琐。使用nodemon可以自动化这一过程,让开发者专注于编码。
ts-node
- 用途:ts-node是一个TypeScript执行环境和REPL,它允许你直接在Node.js环境中运行TypeScript代码,而不需要将TypeScript编译为JavaScript。
- 为什么需要:在开发阶段,直接运行TypeScript代码而不先编译为JavaScript可以简化开发流程,加快开发速度。
ts-node-dev
- 用途:ts-node-dev结合了ts-node和nodemon的功能,它在检测到TypeScript文件变化时,会自动重新编译并重启应用。它比单独使用ts-node和nodemon的组合更高效,因为它尽量只重新编译改变的部分,而不是整个应用。
- 为什么需要:它提供了一个快速的开发循环,自动处理编译和重启,特别适合TypeScript项目。
tsconfig-paths
- 用途:tsconfig-paths是一个工具,它允许Node.js应用根据tsconfig.json中的
paths
配置解析模块路径。这意味着你可以在TypeScript项目中设置自定义路径,简化模块导入。- 为什么需要:在大型项目中,可能需要配置较复杂的模块路径来避免使用相对路径导入模块,这样可以使得代码更加整洁。tsconfig-paths让这些自定义路径配置在运行时生效。
6. 设置项目结构
创建你的源代码目录和入口文件,通常是 src
和 src/index.ts
:
# 执行不了命令就键盘鼠标操作吧~
mkdir src
touch src/index.ts
在 src/index.ts
文件中,你可以开始写你的 Fastify 服务器代码。
7. 添加启动脚本
在 package.json
中添加一个脚本来编译 TypeScript 代码并启动你的应用:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node dist/index.js",
"dev": "NODE_ENV=dev nodemon --watch src -e ts --exec ts-node --esm src/index.ts",
"build": "tsc && tsc-alias"
},
这里,build
脚本会编译项目,start
脚本会运行编译后的 JavaScript,而 dev
脚本会使用 ts-node-dev
(你需要先安装它)来实现在开发时自动重启服务器。
基本使用和路由设置
在 TypeScript 中使用 Fastify 创建基本的路由和服务器的示例如下。这个示例包括了类型注解,以提供更好的类型安全性和自动补全功能。
然后,在你的 src/index.ts
文件中,编写以下 TypeScript 代码:
// 导入 Fastify 和类型定义
import fastify, { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
// 创建 Fastify 实例
const server: FastifyInstance = fastify({
logger: true
});
// 你好啊,世界
server.get('/', (request: FastifyRequest, reply: FastifyReply) => {
return 'hello world'
})
// 定义一个 GET 路由
server.get('/ping', async (request: FastifyRequest, reply: FastifyReply) => {
return 'pong\n';
});
// 带参数的路由
server.get('/greetings/:name', async (request: FastifyRequest, reply: FastifyReply) => {
// 使用类型断言获取参数
const name = (request.params as any).name as string;
return `Hello, ${name}!\n`;
});
// 带查询字符串的路由
server.get('/echo', async (request: FastifyRequest, reply: FastifyReply) => {
// 使用类型断言获取查询参数
const message = (request.query as any).message as string;
return `You said: ${message}\n`;
});
// 异步路由处理器
server.get('/async-operation', async (request: FastifyRequest, reply: FastifyReply) => {
const result = await someAsyncOperation();
return result;
});
// 监听端口
server.listen({ port: 3000 }, (err, address) => {
if (err) {
server.log.error(err);
process.exit(1);
}
server.log.info(`Server listening at ${address}`);
});
// 模拟的异步操作函数
async function someAsyncOperation(): Promise<string> {
return new Promise(resolve => setTimeout(() => resolve('Done!'), 1000));
}
在这个示例中,我们使用了 TypeScript 的类型注解来指定 FastifyInstance
, FastifyRequest
, 和 FastifyReply
的类型。当你访问请求对象的属性,如 params
和 query
,你通常需要使用类型断言来指定更具体的类型,因为 Fastify 默认不知道这些属性的确切结构。