返回简历
低代码平台迁移套件

Fero Migration Kit

Fero DSL → React 自动化转换 · Claude Code 驱动 · AST 解析 · 零运行时依赖

2025.01 - 2025.03 设计者 / 开发者 Claude Code · AST
Claude Code React + TypeScript AST 解析 Monorepo JSON DSL

迁移动因:低代码平台的依赖困境

迁移前:Fero 平台依赖

Fero Runtime(平台运行时)
page.fero.json(DSL 配置)
动态渲染引擎(黑盒)
  • 页面逻辑锁在平台内,无法 Code Review
  • 无法纳入 Git 版本管理与 CI 流程
  • 平台升级导致页面行为不可预期
  • 无法与 Monorepo 共享组件库

迁移后:标准 React 工程

React 组件(标准 TSX)
Monorepo 共享组件库
Webpack / Vite 构建
  • 完整源码,可 Review、可测试
  • 纳入 Monorepo,统一依赖管理
  • 零运行时依赖,构建产物可独立部署
  • 复用团队 React 组件库与工具链

DSL → React 转换流程

flowchart TD IN["📄 输入
page.fero.json
(Fero 平台导出的 DSL)"] subgraph "第一阶段:解析" P1["fero-parser
读取 DSL JSON
识别节点类型"] P2["component-map
Fero 组件 → React 组件
映射查表"] P3["prop-transformer
Fero prop 语法
→ React prop 规则转换"] P4["输出 IR
标准化中间表示
(框架无关)"] P1 --> P2 --> P3 --> P4 end subgraph "第二阶段:调用skill生成" G1["skill-tsx-generator
IR → React TSX
组件树生成"] G2["skill-style-generator
Fero 样式配置
→ CSS Module"] G3["skill-api-generator
Fero 数据源配置
→ API 函数"] P4 --> G1 & G2 & G3 end subgraph "第三阶段:Claude 兜底" C1{"存在无法
规则化的节点?"} C2["Claude Code Agent
理解语义
手工生成对应 React 代码"] G1 --> C1 C1 -->|"是"| C2 C1 -->|"否"| OUT C2 --> OUT end OUT["✅ 输出
标准 React TSX 组件
+ CSS Module
+ API 函数"] style IN fill:#f0f9ff,stroke:#0ea5e9 style P4 fill:#fef3c7,stroke:#f59e0b style C2 fill:#ede9fe,stroke:#8b5cf6 style OUT fill:#dcfce7,stroke:#16a34a

DSL → IR → TSX 三阶段转换示例

Fero DSL(输入)

page.fero.json
{
  "type": "FeroTable",
  "props": {
    "dataSource": "@api:fetchOrderList",
    "columns": [
      { "key": "orderId",  "title": "订单号" },
      { "key": "status",   "title": "状态",
        "render": "@component:StatusTag" }
    ],
    "pagination": true,
    "rowKey": "orderId"
  }
}

标准化 IR(中间)

ir.json
{
  "component": "Table",
  "library": "@team/ui",
  "props": {
    "dataSource": {
      "type": "api-call",
      "fn": "fetchOrderList"
    },
    "columns": [
      { "dataIndex": "orderId",
        "title": "订单号" },
      { "dataIndex": "status",
        "title": "状态",
        "render": {
          "type": "component",
          "name": "StatusTag"
        }}
    ],
    "rowKey": "orderId"
  }
}

React TSX(输出)

OrderList.tsx
import { Table } from '@team/ui'
import { StatusTag } from '../ui'
import { useOrderList } from '../model'

const columns = [
  { dataIndex: 'orderId',
    title: '订单号' },
  { dataIndex: 'status',
    title: '状态',
    render: (v) => <StatusTag value={v} /> },
]

export const OrderList = () => {
  const { list, loading } = useOrderList()
  return (
    <Table
      dataSource={list}
      columns={columns}
      loading={loading}
      rowKey="orderId"
    />
  )
}

规则化转换 vs Claude 兜底

规则化转换(覆盖 ~80%)

通过skill调用component-map.tsprop-transformer.ts 静态映射处理,速度快、结果稳定、可单测覆盖。

  • 标准布局组件:FeroForm → Form,FeroTable → Table
  • 基础 prop 映射:dataSourcecolumnsrowKey
  • 样式配置:Fero 内联样式 → CSS Module class
  • 数据源绑定:@api:xxx → 对应 API 函数调用

Claude 兜底(处理 ~20%)

规则无法覆盖的复杂节点交由 Claude Code Agent 处理,Agent 读取 CLAUDE.md 中的目标工程规范,生成符合团队标准的代码。

  • 自定义渲染函数:@component:xxx 引用的内联逻辑
  • 条件渲染:复杂的 Fero 条件表达式
  • 事件处理:Fero 平台特有的事件语法
  • 跨组件通信:Fero 的全局状态绑定语法

批量迁移与 Monorepo 集成

graph LR subgraph "迁移前" F1["Fero 平台
page-a.fero.json"] F2["Fero 平台
page-b.fero.json"] F3["Fero 平台
page-c.fero.json"] end subgraph "fero-migration-kit" BATCH["migrate-batch.sh
读取 pages.list
顺序执行迁移"] end subgraph "Monorepo(迁移后)" direction TB PKG["packages/fenghuo-admin/
├── src/pages/page-a/
│ ├── ui/
│ ├── model/
│ └── api/
├── src/pages/page-b/
└── src/pages/page-c/"] SHARED["packages/shared-ui/
共享组件库
(迁移页面直接复用)"] PKG -->|"import"| SHARED end F1 & F2 & F3 --> BATCH --> PKG style BATCH fill:#fef3c7,stroke:#f59e0b style PKG fill:#d1fae5,stroke:#10b981 style SHARED fill:#ede9fe,stroke:#8b5cf6

迁移产物直接输出到 Monorepo 对应 package 的 src/pages/ 目录下,遵循 FSD 结构,可立即被 Webpack 构建、被 CI 流程检测,无需额外的手工整理步骤。diff-check.sh 在迁移完成后对比新旧页面的 API 调用记录,确保接口行为一致。