掘金 后端 ( ) • 2024-04-12 16:29

基础知识

什么是 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. 设置项目结构

创建你的源代码目录和入口文件,通常是 srcsrc/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 的类型。当你访问请求对象的属性,如 paramsquery,你通常需要使用类型断言来指定更具体的类型,因为 Fastify 默认不知道这些属性的确切结构。