基于React18+Mobx+Typescript的web端(PC+Mobile)架构

架构图

image.png

技术栈

image.png

基于 React 18, React Route 6.x, Mobx 6.x
源码地址

1. Key design

1.1 Business decoupling

image.png

当研发人员同时工作,业务复杂时,需要将业务划分为模块,解耦
比如有A、B、C等模块,会在Store、Api、Page等关键层进行隔离。

1.2 Views compatible for Mobile and PC

有如下 3 种方式可以让View层与Mobile和 PC端兼容。

  • 不同项目:当用户在浏览器中输入URL时,通过nginx解析useAgent响应对应的mobie或pc页面
  • 不同页面组件:当用户在浏览器中输入URL时,由userAgent判断,在路由上挂载mobile或pc页面组件。
  • 页面组件内:通过在页面组件内部的userAgent来判断,渲染mobile或pc组件

当然也可以根据浏览器分辨率来判定,或浏览器分辨率+userAgent。
在本项目中我采用的是'不同页面组件'的方法,具体可以查看10 Compatible for Mobile and PC的详细信息

1.3 Authentication

image.png

每个routes.ts里给每个路由设置isAuth.默认isAuth为true,代表需要鉴权
如果需要鉴权,则会判定是否已登录。没登录渲染login组件。已登录则正常渲染。
具体参考require-auth组件

1.4 I18n

有如下2种处理项目I18n的方式

  • 支持在任何地方,包括任何js文件写国际化代码,然后通过window.location.reload() 来进行语言的切换
  • 仅支持在react组件里写国际化代码,通过hook来进行语言的切换

由于第二种不需要切换页面,体验更加友好,所以在本项目采用了它
具体参考demo 页面组件

1.5 Directory Structure

image.png

下面是架构图各层的解释
架构图底端的 Postman/Swagger 是指后端提供 API 文档后,用它们来调试

2.Network request and service processing

2.1 flow

image.png

2.2 code of View Layer

Store.onLoad(action) 通过页面根组件Page自动调用
或页面通过store.action调用api
详见 pages/home/index.tsx

2.3 code example of page store

如果页面被components/page组件包裹,则页面初始化时会自动执行Store中的onLoad,卸载页面时会自动执行Store中的onUnload。


image.png

定义调用api的action


image.png

在 store 中调用 api


image.png

所有接口类型都定义在@types 里
详情请参阅store/home

2.4 http.ts code

image.png
image.png

更多详情请参考http/base/http
MobX构建store,相当于model层,model层负责调用Api
相比于 Redux(dispatch(action) -> reducer -> new state)流程,MobX 的 store 类看起来自然简洁; 另外,Redux 需要依赖中间件,比如插件 Redux-thunk 调用 Api,而 MobX 不需要。 最后,需通过 store.subscribe 异步获取 Redux 更新组件,而 MobX 是同步响应式更新。 以上就是用 MobX 代替 Redux 的原因。

3. Utils

helper包下有很多辅助JS类

3.1 Content

image.png

3.2 Internationalization

image.png

3.3 Contants

[图片上传失败...(image-6fd5db-1658808848167)]

3.4 Config

基于不同环境下的env生成配置项


image.png

image.png

更多详情请查看 helper 下的代码

4. Page Container

所有页面组件都放在pages下,公共组件放在components下

4.1 components

image.png

如果不是公共组件,只用于某个页面,请放在对应页面的 components 文件夹中。 例如 home/components

4.1.1 Page root component

image.png

提取根组件是为了重用页面的一些通用逻辑。 例如,它会自动处理所有页面store的初始化action: onLoad, onUnload。
其他请查看components的代码

4.2 Router

使用 React Router 6.x

4.2.1 Register Routes
image.png
4.2.3 Define Route for certain page module
image.png

加载时显示Chunk 名称


image.png

4.3 MobX state management

4.3.1 Define store

image.png

初始化每个store
[图片上传失败...(image-64749d-1658808848167)]

所有store包裹在Context里


image.png

响应式变量,初始化action: onLoad,卸载action:onUnload,其他action,computed变量

4.3.2 Store used in page

image.png

通过store.xxx调用action/变量
示例代码在 pages/home

5. UI component library

对于一些常用的ui库如Bootstrap、Material UI、Andt 等,很容易集成到项目中。
下面是一个集成Antd的例子。

5.1 integrate Antd

image.png
image.png

6. Compile and package

6.1 Configuration items

image.png

可以覆盖webpack配置信息
Refer to configuration item description

6.2 Debugger by mock environment

6.2.1 Add mock data
image.png

在 mocks 目录中为一些 api 添加mock数据

6.2.2 Exec yarn mock
image.png
6.3.3 Principle analysis

通过koa启一个mock服务器


image.png

将 BASEURL 设置为 .env.mock 中的模拟服务器host,于是所有请求都会访问它


image.png

7. Log

7.1 Catching React Exceptions

image.png
image.png

7.2 Log upload

image.png

目前在helper/log中收集异常日志后,只打印到控制台,一般应该上传到日志平台,如Sentry。
注意:Promise 等异步异常需要通过 try...catch 来捕获

8. Unit Test

8.1 add unit test

image.png

__tests__/unit 目录中添加单元测试文件
jest 的 assert 可用于普通函数,在 js-dom-test-spec.js有示例代码
用 enzyme 或 testing-library 来测试react 组件,在 app-spec.js 有示例代码
执行命令yarn test
参考 Jest 27.x create-react-app unit test
enzyme

8.2 Check out coverage

image.png

执行命令 yarn test:coverage

9. Pre Commit

image.png

9.1 Code format

image.png

9.2 Validate commit message

通过 commitlint 验证 commit msg,参考 commitlint
msg格式如'feat: XXX...'

10 Compatible for Mobile and PC

10.1 Load the corresponding global style

image.png
image.png

10.2 Load the corresponding hooks/components inside the page

image.png

10.3 Load the corresponding page component inside the router

image.png

如果是mobile环境,挂载mobile端页面组件,否则,挂载pc端页面组件

10.4 Example

mobile


image.png

pc


image.png

11. Other

  • 文章涉及的源码地址
  • 我的技术博客
  • helper/hooks 文件夹显示了 1 个hook示例
  • 组件推荐使用memo+useMemo+useCallback,避免重复渲染

你可能感兴趣的:(基于React18+Mobx+Typescript的web端(PC+Mobile)架构)