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 设计业务逻辑
使用聚合模式设计领域模型
聚合的规则和颗粒度
到时要把图更新成我们的项目的,具体的模块划分,这一块可以和产品还有后端同学对齐
使用聚合设计业务逻辑
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
- 本地定位问题
- Sentry查看用户的操作流水
event sourcing 的弊端
- 架构复杂
- 性能问题
挑战与限制
生成快照,序列化在HTML里面返回
现在初始化问题解决的不是很好
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,客户端渲染)
后续要把整个 新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)
headless CMS
Server-side Rendering(SSR,服务端渲染)
- 现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服务组件)
可以用来处理 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
暂时先不考虑
测试策略
单元测试
组件测试
Visual tests
Accessibility tests
Snapshot testing
集成测试
端到端测试(E2E)
- playwright
- Gherkin
- 需要 产品同学 去输出 Gherkin 的需求文档
- 需要 测试同学 完成UI自动化验收
迈向生产环境
安全与合规
- Tainting: Prevent sensitive data from being exposed to the client by tainting data objects and/or specific values.
- Server Actions: Ensure users are authorized to call Server Actions. Review the the recommended security practices.
- Environment Variables: Ensure your .env.* files are added to .gitignore and only public variables are prefixed with NEXT_PUBLIC_.
- Content Security Policy: Consider adding a Content Security Policy to protect your application against various security threats such as cross-site scripting, clickjacking, and other code injection attacks.
- Understanding XSS Attacks
- Understanding CSRF Attacks
- Authentication
- next-auth.js.org/
- WEB还需要考虑支持第三方登录
- 合规
- CookieYes
- 隐私策略
- 可访问性
可访问
- 浏览器兼容版本
- 无JS Runtime
可发现
页面被搜索引擎或者第三方媒体更好的发现和使用
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
日志上报
性能指标
sentry
SEO指标
异常追踪
行为监控
脚手架与能力复用
- 快速添加应用
- CI/CD复用
- CLI生成应用/页面/组件等
部署策略
部署模式:包部署
npm仓库,使用GitHub的
package的打包配置,版本管理等
部署模式:容器部署
Docker
K8s
部署模式:CDN部署
部署模式:Edge and Node.js runtime / Serverless部署
业务模式
CMS
- playlaod
设计系统
Design Token
JSON → 切换 → 新的主题
CMS组件库
类Low-Code
物料搭建
设计稿 → 组件化 → 组件(代码+设计稿)
文档系统
协作系统
迁移
迁移策略
全量迁移
渐进式迁移
- CDN
- K8S
渐进式迁移的协作方式
弊端
- 体验没有那么好
- 可以通过预加载来避免
- 通过交互来避免
- 实现起来复杂