Event-Driven/Domain-Driven Architecture in Client-Side (草稿)

19 阅读4分钟

Domain-Driven Architecture in Client-Side

总体概览

拆分策略

传统的拆分策略

  • 应用拆分
  • 页面拆分
  • 组件拆分

服务拆分

拆分策略
Module Name模块描述
Product
Promotion
User
Search
Checkout
Cart
Auth
Personalization
Retail
Category
Review

架构中的通信

基于同步的 API 调用模式的通信

使用REST
使用 gRPC

暂时省略

错误处理
容错策略
  • 快速失败
    • 超时处理
容错设计模式
  • 断路起模式
    • 服务降级
      • SSR-->CSR
  • 重构模式
    • 3次

基于异步消息模式的通信

什么消息传递

  • 消息类型
    • Document
    • Command
    • Event
使用消息机制实现交互方式
实现请求/响应 和 异步请求/响应
  • async/await
实现单向通知
  • 普通请求
实现发布 / 订阅
  • listening

这里到时要定下 编排 和 编曲 的两种写法分别在哪中场景下使用比较好

无代理(消息中间件)的消息架构
消息顺序和竞态问题
sequenceDiagram
    participant Component
    participant Domain
    participant API

    Component->>Domain: 发起Event A
    Component->>Domain: 发起Event B
    Component->>Domain: 发起Event C

    Domain->>API: 基于Event A发起请求A
    Domain->>API: 基于Event B发起请求B
    Domain->>API: 基于Event C发起请求C

    API-->>Domain: 返回请求A
    API-->>Domain: 返回请求B
    API-->>Domain: 返回请求C
    Domain-->>Domain: 最终的数据:C
    Component->>Domain: 获取数据
    Domain -->> Component  : 返回

提供一个通用的解决方案

处理重复消息
  • 读缓存策略
sequenceDiagram
    participant UI
    participant Store
    participant API

    UI->>Store: Mutation
    Store->>API: POST/PUT/Delete API
    UI->>Store: Querie
    Store->>API: GET API
    Store->>Store: Generate View Model
    Store-->>UI: Data
    UI->>Store: Querie
    Store-->>UI: Cache Data

redux-toolkit.js.org/rtk-query/u…

提供一个标准方案

redux-toolkit.js.org/rtk-query/u…

架构中业务逻辑设计

业务逻辑组织方式

使用 Transaction script pattern 设计业务逻辑

简单页面不需要走DDD流程

使用 Domain model pattern 设计业务逻辑

www.figma.com/board/qHShT…

使用聚合模式设计领域模型

聚合的规则和颗粒度

到时要把图更新成我们的项目的,具体的模块划分,这一块可以和产品还有后端同学对齐

使用聚合设计业务逻辑

redux-toolkit.js.org/api/createS…

发布领域事件

生成和发布领域事件
  • 聚合变化发布事件
  • Command发布事件
消费领域事件

redux-toolkit.js.org/api/createL…

CQRS and Event sourcing

Overview of CQRS

经过 Middleware 就可以访问有副作用的数据,比如 API数据,浏览器存储等

乐观更新

redux-toolkit.js.org/rtk-query/u…

Event sourcing(事件溯源)

event sourcing 的好处
time-travel debugging
event sourcing 的弊端
  • 架构复杂
  • 性能问题
挑战与限制

生成快照,序列化在HTML里面返回

redux-toolkit.js.org/usage/nextj…

现在初始化问题解决的不是很好

RSC的限制问题

SSR下的序列化处理方式

序列化后的性能影响

  • No global stores - Because the Redux store is shared across requests, it should not be defined as a global variable. Instead, the store should be created per request.
  • RSCs should not read or write the Redux store - RSCs cannot use hooks or context. They aren't meant to be stateful. Having an RSC read or write values from a global store violates the architecture of the Next.js App Router.
  • The store should only contain mutable data - We recommend that you use your Redux sparingly for data intended to be global and mutable.

渲染模式

在本架构中,我们会使用nextjs.org/ 来实现具体的渲染模式。

Client-side Rendering(CSR,客户端渲染)

www.patterns.dev/react/clien…

后续要把整个 新POS系统 迁移成这种方案

sequenceDiagram
    participant Browser
    participant S as File Server
    participant CDN as CDN

    Browser->>S: Request HTML
    S-->>Browser: Return basic HTML 
    Browser->>CDN: Request JS/CSS/...
    CDN-->>Browser: 
    Browser->>Browser: Load JavaScript
    Browser->>API: Request data
    API-->>Browser: Return data
    Browser->>Browser: Render page using data

Incremental Static Generation (ISG)

www.patterns.dev/react/incre…

Server-side Rendering(SSR,服务端渲染)

www.patterns.dev/react/serve…

  • 现Web方案
sequenceDiagram
    participant Client
    participant Gateway
    participant Server(NodeJs)
    participant API

    Client->>Gateway: Web page requests
    Gateway->>Server(NodeJs): 
    Server(NodeJs)->>API: API requests
    API-->>Server(NodeJs): Return Response
    Server(NodeJs)->>Client: Return Response
    Client->>API: API requests
    API-->>Client: Return Response

React Server Components(RSC,React服务组件)

www.patterns.dev/react/react…

  • 可以用来处理 CMS 的页面

  • 投放页面

sequenceDiagram
    participant Client
    participant Gateway
    participant Node as Server(NodeJs)
    participant API

    Client->>Gateway: Web page requests
    Gateway->>Node: 
    Node->>API: API requests
    API-->>Node: Return Response
    Node->>Client: Return Response
    Client->>API: API requests
    API-->>Client: Return Response

外部API模式

BFF

使用 GraphQL 实现 API Gateway

暂时先不考虑

测试策略

testing.googleblog.com/2015/04/jus…

单元测试

jestjs.io/

组件测试

Visual tests

storybook.js.org/docs/writin…

Accessibility tests

storybook.js.org/docs/writin…

Snapshot testing

storybook.js.org/docs/writin…

集成测试

storybook.js.org/docs/writin…

端到端测试(E2E)

  • playwright
  • Gherkin
  • 需要 产品同学 去输出 Gherkin 的需求文档
  • 需要 测试同学 完成UI自动化验收

迈向生产环境

安全与合规

可访问

可发现

页面被搜索引擎或者第三方媒体更好的发现和使用

Metadata and SEO
  • Metadata API: Use the Metadata API to improve your application's Search Engine Optimization (SEO) by adding page titles, descriptions, and more.
  • Open Graph (OG) images: Create OG images to prepare your application for social sharing.
  • Sitemaps and Robots: Help Search Engines crawl and index your pages by generating sitemaps and robots files.

可配置化

  • env
  • CMS
  • feature flag

可观测(Observability)

健康检查 API
日志上报

www.datadoghq.com/

性能指标

sentry

SEO指标
异常追踪

castlery.sentry.io/issues

行为监控

脚手架与能力复用

  • 快速添加应用
  • CI/CD复用
  • CLI生成应用/页面/组件等

部署策略

部署模式:包部署

  • npm仓库,使用GitHub的

  • package的打包配置,版本管理等

部署模式:容器部署

Docker
K8s

部署模式:CDN部署

部署模式:Edge and Node.js runtime / Serverless部署

业务模式

CMS

  • playlaod

设计系统

Design Token

JSON → 切换 → 新的主题

CMS组件库

类Low-Code

物料搭建

设计稿 → 组件化 → 组件(代码+设计稿)

文档系统

storybook.js.org/

协作系统

www.chromatic.com/

迁移

迁移策略

全量迁移

渐进式迁移

  • CDN
  • K8S

渐进式迁移的协作方式

弊端

  • 体验没有那么好
    • 可以通过预加载来避免
    • 通过交互来避免
  • 实现起来复杂