# DDDMicroFrontend **Repository Path**: bmycode/dddmicro-frontend ## Basic Information - **Project Name**: DDDMicroFrontend - **Description**: 搭建的一套基于DDD领域驱动设计的微服务前端,适用于大型企业,开发大型复杂且拓展灵活的前端应用的架构方案。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2025-09-17 - **Last Updated**: 2025-09-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## DDD领域驱动设计的微服务前端案例 > 持续开发中,及时拉取代码,文档还不够完善,先凑合看!!目前只是demo,代码还会进行大规模封装细化和改造! 搭建的一套 **基于DDD领域驱动设计的微服务前端** 项目脚手架,适用于大型企业,开发大型复杂且拓展灵活的前端应用的架构方案。 代码编写建议使用 **OOP面向对象 + TypeScript + JSX** 进行开发,让项目更适合开发和维护,获得更好更极致的编码体验。 本案例中 **[主应用]** 采取的就是OOP风格,当然如果你不熟悉上面的写法,那么可以在 【其他模块】中使用Vue2,Vue3都行,但仍然需要遵守DDD的规范进行开发! ## 开发日记 - [x] 基于DDD理念改造 - [x] 拆分领域模块为联邦模块,实现微前端 - [x] 基于 Vue3+OOP+JSX 改造项目代码 - [x] 基于 Nacos 开发 nacos-federation 插件,实现各模块的服务注册&发现,统一管理远程地址 - [x] 修改 nacos-federation 插件实现其成为vite的插件,进一步简化代码! - [x] 修改 nacos-federation 插件,实现 接口请求基地址从 配置中心获取,并注入到环境变量中 - [x] 配置 Traefik,实现微前端网关,限流与熔断,重试,IP 白名单,压缩 - [x] 封装自动生成 Traefik 代理配置的 nodejs 插件代码 - [x] 修改base,增加资源来源地址,修复资源错误加载的问题 - [x] 将vite.config.ts中的base 改到插件 nacos-federation中实现,简化代码 - [x] 增加控制台日志,方便访问各种服务 - [x] pnpm 统一管理集中项目依赖,运行&构建等 - [ ] 领域模块实现 docker 自动化构建部署上线 - [ ] Deno集成GraphQL - [ ] .... - [ ] 爬快手api,实现一个完整项目,测试脚手架不足 ## 技术栈: - [DDD领域驱动设计](https://zh.wikipedia.org/zh-cn/%E9%A0%98%E5%9F%9F%E9%A9%85%E5%8B%95%E8%A8%AD%E8%A8%88) - [@originjs/vite-plugin-federation](https://www.npmjs.com/package/@originjs/vite-plugin-federation) - [Deno](https://deno.com/) - [TypeScript](https://www.typescriptlang.org/) - [GraphQL](https://graphql.org/) - [docker](https://www.docker.com/) - [drone](https://drone.cool/) - [nacos](https://nacos.io/?spm=5238cd80.47ee59c.0.0.189fcd36fF0ca9) - [nginx](https://nginx.org/) - [Vue3](https://cn.vuejs.org/) - [Jsx](https://legacy.reactjs.org/docs/introducing-jsx.html) - [Vite](https://cn.vite.dev/) - [axios](https://axios-http.com/) - 等等等.... ## 文件夹结构 **根目录:** ```txt . ├── back-end # 【后端】基于Deno写的后端 测试接口,仅供测试 ├── doc # 一些markdown笔记 ├── docker # 微服务系统下的一些工具 │ ├── nacos # 动态服务发现配置管理平台 │ └── traefik # 微服务网关 ├── front-end # 前端 微服务 项目 │ ├── app-product # 独立的【商品】领域模块 │ ├── app-shared # 独立的 共享资源 模块 │ ├── nacos-federation # 开发的Nacos服务注册与发现的插件,简化优雅代码 │ ├── .... # 实际项目还会有更多其他的领域模块 │ └── main-app # 主应用(入口应用) ├── package.json # pnpm的顶级配置文件,可以控制模块运行相同命令 ├── pnpm-workspace.yaml # 管理多个包的依赖关系 └── README.md # 帮助文档 ``` ** DDD前端分层目录:** ```txt src/ ├── domains/ # 【核心】领域层 - 所有业务领域模块 │ └── product/ # 【app-product模块】订单领域模块 │ ├── domain/ # 领域模型(充血模型) │ │ ├── entities/ # 实体(如:Product, ProductLineItem) │ │ ├── value-objects/ # 值对象(如:Money, Address) │ │ ├── types/ # 领域内通用类型 │ │ ├── enums/ # 领域枚举 │ │ └── events/ # 领域事件(如果需要) │ ├── application/ # 应用服务层 - 协调领域对象完成用例 │ │ └── services/ # 应用服务(如:ProductApplicationService) │ ├── infrastructure/ # 基础设施层 - 领域层的具体实现 │ │ └── api/ # 数据获取实现(如:HttpProductRepository) │ ├── ports/ # 端口(接口/抽象类)- 定义契约 │ │ └── repositories/ # 仓储接口(如:ProductRepository) │ └── use-cases/ # (可选)或将用例放在这里 ├── app/ # 【交付层】应用组装和配置:路由、状态管理、主布局、UI库设置、错误处理、依赖注入容器 │ ├── components/ # 通用UI组件(与业务无关,如Button,Modal) │ ├── layouts/ # 布局组件 │ ├── di/ # 依赖注入配置 │ ├── router/ # Vue Router 配置 │ ├── stores/ # Pinia Store(用于UI状态管理,非核心业务状态) │ └── main.ts # 应用入口,依赖注入的组装之地 │ └── App.vue # 根组件 ├── features/ # 【交付层】基于领域的功能模块:关注具体的业务功能实现,它是舞台上的“演员”和“节目”。 │ └── product/ # 订单功能模块(app-product) │ ├── components/ # 订单领域专用的UI组件 │ ├── views/ # 订单相关的页面级Vue组件 │ ├── router/ # 订单相关的页面级Vue组件 │ ├── composables/ # 订单相关的Vue组合式函数 │ └── index.ts # 订单功能模块的出口 ├── shared/ # 【app-shared模块】共享资源 │ ├── infra(infrastructure) # 基础设施层 │ │ ├── http/ │ ├── lib/ # 第三方库的封装/工具函数 │ ├── utils/ # 纯工具函数 │ └── types/ # 全局通用的TypeScript类型定义 │ └── constants/ # 全局常量(如错误码、正则) │ └── exceptions/ # 通用异常(如NotFoundError) └── public/ # 静态资源目录 └── index.html # 主HTML文件 ``` ## 代码风格 ```tsx // 首页 页面 import { Component, Ref, Setup, Vue } from 'vue-facing-decorator' import Header from '../components/Header' import { RouteLocationNormalizedLoaded, Router, useRoute, useRouter } from "vue-router"; interface ListItemType { id: number title: string } @Component() export default class Home extends Vue { counter: number = 1; @Ref readonly refH1!: HTMLDivElement @Setup((props, ctx) => useRouter()) router!: Router @Setup((props, ctx) => useRoute()) route!: RouteLocationNormalizedLoaded newList: ListItemType[] = [ { id: 1, title: '新闻1' }, { id: 2, title: '新闻2' }, { id: 3, title: '新闻3' }, ] addCount() { // console.log("ref dom: ", this.refH1) // this.router.push({ name: 'about' }) // this.route.query this.counter++ } testHtml() { return

测试html jsx 函数

} render() { return (

首页

counter 响应式变量(点我):{ this.counter }

{ { default: () =>
父到子 default 插槽
, haveName: () =>
父到子 具名 插槽
, item: (val: ListItemType) =>
  • { val.title }
  • } }
    { this.testHtml }
    ) } } ``` ```tsx // 头部组件 import { Component, Prop, TSX, Vue } from 'vue-facing-decorator' interface Props { text?: string list?: ListItemType[] } interface ListItemType { id: number title: string } @Component() export default class Header extends TSX()(Vue) implements Props { @Prop({ default: '默认数值' }) text!: string; @Prop() list!: ListItemType[]; created() { console.log("created: ", this) } render() { return (
    头部组件

    { this.text }

    { this.$slots.default?.() } { this.$slots.haveName?.() }
    ) } } ``` ## ~~【失效】运行 & 打包~~ ```bash # 1 下载代码 git clone https://gitee.com/bmycode/dddmicro-frontend.git # 2 运行后端 cd back-end # 进入 后端 文件夹 deno install # 安装依赖 deno run dev # 运行后端 # 3 运行前端 cd front-end # 进入 前端 文件夹 pnpm install # 会同时为 所有模块 安装依赖 pnpm add -g concurrently # 全局安装 并发命令执行 插件,局部安装也行,随你。 pnpm run all # 构建 app-product 和 app-shared 并启动预览,并开发阶段启动 main-app 模块 # 注意:命令跑完后 ctrl + c 停止,重跑一次!!因为子模块内命令并发执行预览跑在构建之前,解决办法很简单,后面再搞。 pnpm run all # 打开 main-app 主模块访问地址即可:[http://localhost:1300/](http://localhost:1300/) # 4 部署上线 pnpm run build:main # 构建并预览主应用,预览打包后的主应用,没问题,ctrl + c 停止。 # 子模块在 第三步 已经打包好了,不需要重新打包了。 # 上传部署 各模块内的 dist/ 文件夹到服务器上,注意修改 vite.config.ts 内 plugins.federation.remotes.xxx 的地址! # 后期会实现集中管理 地址配置,并根据环境变量动态加载!! ``` ## 问 & 答 **问: 为什么vue项目要抛弃SFC写法而尝试jsx/tsx方式来编码?** > 答:https://juejin.cn/post/6911175470255964174 **问:不会 vue3 jsx 语法,怎么办?** > 答:https://juejin.cn/post/7141674726434439176