基于 React、TS的聊天室monorepo实战

本文详细介绍了使用React和TypeScript构建客户端APP组件库的方法,包括使用create-react-app初始化、多包管理、覆盖Webpack配置,以及服务端用Node.js和Express实现。重点讨论了状态管理、消息组件设计、数据流设计,特别是如何利用ReactHooks共享状态和Socket.IO实现通信。
摘要由CSDN通过智能技术生成

最终以这种模式去规范组件库的开发(PS:没有文档的组件库,不叫组件库):

客户端

APP 的开发采用我们最熟悉的模式,直接用 create-react-app 初始化环境。

npx create-react-app app --typescript

整个聊天室项目采用的是多包管理模式,所以在开发时我们会直接通过 lerna link命令来创建软连接,因此可以不必通过发布包来完成依赖的使用。

但这里要注意的是,由于 create react app 命令生成的项目中 babel 配置是忽略编译 node_modules 的。所以,不得不覆盖其 webpack 配置

这里简单通过 react-app-rewired 到方式来达成目的,但并不是最佳实践。

服务端

这里,服务端的代码,仅作为辅助演示的作用,因此暂不考虑健壮性。标配 ts-nodenodemonexpress 即可满足需求。

启动命令如下:

nodemon --watch ‘src//*.ts’ --ignore 'src//*.spec.ts’ --exec ‘ts-node’ src/index.ts

核心实现


至此,基本的环境以及搭建完毕。接下来讲下聊天室核心实现逻辑

大家可以用个 TODO 的方式进行开发,比如:

把需求拆分成若干个任务,每个任务关联到一个 TODO,并以此规范 git commit。

消息组件设计

虽然项目是基于 Material-UI 开发的,但考虑到业务带来的差异性,组件库可能需要高度定制,故直接采用全量导出的方式来使用基础 UI 组件。

聊天室用到比较多是消息流组件,比如:纯文本消息组件,纯图片消息组件,系统消息组件,推荐组件等。

├── MessageBase.tsx # 包含头像、反向显示的基础消息组件

├── MessageMedia.tsx # 图片、音频等

├── MessageSystem.tsx # 系统消息

├── MessageText.tsx # 文本组件

├── stories # 文档相关

│ ├── Demo.tsx

│ ├── Message.stories.tsx

│ ├── README.md

│ └── img.jpg

└── index.tsx

主要的设计思路:

  1. 以组合的方式开发组件

  2. 保持组件 API 一致性

  3. 尽可能简单,不过度设计

目前需要实现的消息组件比较简单,具体实现,可以看源码。这里主要传达的是文件组织方式和基本设计思路。

数据流设计

先来看下,React hook 出现后,前端可以如何更优雅地共享状态

export const ChatContext = React.createContext<{

state: typeof initialState;

dispatch: (action: Action) => void;

}>({

state: initialState,

dispatch: () => {},

});

export const useChatStore = () => React.useContext(ChatContext);

export function ChatProvider(props: any) {

const [state, dispatch] = React.useReducer(reducer, initialState);

const value = { state, dispatch };

return <ChatContext.Provider value={value}>{props.children}</ChatContext.Provider>;

}

  1. 通过 React.createContext 创建 context

  2. 通过 React.useReducer 管理 reducer,生成 state 与 dispatch

  3. 通过 React.useContext 获取状态源

这样,我们就可以很方便的维护局部或全局状态。至于是否要将所有的状态都放到根状态树里以及 domain 数据是否需要状态化,就是另外一个故事了,这里就留给读者自己去深究。

接着我们来设计一个聊天室所需的数据结构:

interface State {

messages: Message[]; // 数组的方式存储所有消息,保持有序

members: { [id: string]: Member }; // map 的形式存储当前聊天室所有用户,便于查询

}

数据尽可能地保持简单,比如一个 message 的结构可以是这样:

interface Message {

id: string;

type: MESSAGE_TYPE; // 消息类型,用于渲染不用的消息组件

userId: string; // 发送消息的用户标识

content: object; // 根据消息组件类型收敛的数据结构

}

MESSAGE_TYPE 消息类型枚举,用于与消息流组件隐射一一对应,以及 socket 消息发送时的 type 数据。建议可以在 @im/helper 里统一维护这类的常量。

interface Member {

id: string;

avatar: string;

name: string;

}

通过消息中的 userId 去 members 获取对应用户数据来渲染头像和用户昵称等。

按以上的约定基本可以满足一个简单的聊天室了。另外,如果组件层级比较多,组件粒度拆得比较细的话,在不考虑业务组件复用的情况下,可以引入一些共享状态,如:currentUserId、socket、activeTool 等,可有效避免父子组件状态传达,但这里需要开发者自行权衡复用性。

客户端 Socket

  1. 组件挂载完成后,建立 socket 链接,并保存当前 socket 实例,卸载后记得断开连接。

React.useEffect(() => {

const socket: SocketIOClient.Socket = io(‘http://localhost:3002’);

dispatch({ type: Type.INSERT_SOCKET, payload: socket });

return () => {

socket.close();

};

}, [dispatch]);

  1. 通过以下方式通知服务端,比如用户加入聊天室

state.socket.emit(‘add user’, username);

  1. 监听服务端事件,比如用户发送消息

React.useEffect(() => {

if (!state.socket) {

return;

}

state.socket.removeAllListeners();

state.socket.on(‘login’, handleLogin);

state.socket.on(‘user joined’, handleUserJoin);

state.socket.on(‘user left’, handleUserLeft);

state.socket.on(‘new message’, handelNewMessage);

}, [state.socket, handleLogin, handleUserJoin, handelNewMessage, handleUserLeft]);

服务端 Socket

这是一个 socket 官方的 demo,比较简单。不考虑其他的场景,这样就可以了!

import express from ‘express’;

import socket from ‘socket.io’;

const server = require(‘http’).createServer(app);

const io = socket(server);

server.listen(port);

io.on(‘connection’, socket => {

// 处理接收的新消息

socket.on(‘new message’, data => {

// 通知其他客户端

socket.broadcast.emit(‘new message’, {

id: v4(),

username: socket.username,

userId: socket.userId,

message: data.message,

type: data.type,

});

});

});

客户端和服务端的 socket 已经完成通信,贴代码总是很累的,具体细节参看源码。


QA


这一节我通过问答的方式来快速过一下开发聊天室中可能遇到的问题:

  1. 如何实现表情发送

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

资料过多,篇幅有限,需要文中全部资料可以点击这里获取前端面试资料PDF完整版!

自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。

适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**

[外链图片转存中…(img-3EcpcTZC-1712670303173)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

[外链图片转存中…(img-pSGwL8Cu-1712670303175)]

[外链图片转存中…(img-CHeucfs6-1712670303178)]

资料过多,篇幅有限,需要文中全部资料可以点击这里获取前端面试资料PDF完整版!

自古成功在尝试。不尝试永远都不会成功。勇敢的尝试是成功的一半。

  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值