15分钟深度面谈逐字稿:轻流低代码平台

是这样的,我当时做轻流低代码平台时,遇到的不是一个“搭页面工具”的问题,而是公司 SaaS 业务扩张以后,交付模式已经跟不上商业节奏了。

当时企业移动办公、CRM、审批流这些业务线都在增长,但大量需求本质上都是相似的 CRUD、表单、流程和仪表盘。前端团队很容易变成“画表单机器”:客户要加一个字段、改一个审批条件、调整一个列表展示,都要重新开发、联调、测试、发版。单个需求不大,但数量一多,研发排期会拖慢销售交付和客户定制。(2 分钟)

这个问题当时不是凭感觉判断的。我们复盘需求池时发现,很多排期并不是卡在复杂业务设计,而是卡在重复页面搭建、字段调整、表单联动和客户定制配置上。也就是说,研发在大量消耗时间处理“结构类似、规则不同”的需求。这个发现很关键,因为它说明问题不在某个页面写得慢,而在交付方式本身不适合继续线性扩张。

所以这个项目的业务目标,不是让前端少写几个组件,而是把常规 SaaS 页面从“研发交付”变成“配置交付”。实施、产品和业务团队能自己完成大部分通用页面搭建,研发只负责沉淀底层引擎和复杂插件。

这里面有三个核心技术矛盾。

第一是标准化和扩展性的矛盾。低代码平台必须有统一协议,否则每条业务线都自己写表单联动、权限、校验和生命周期,最后只是把重复代码换了个地方。但协议又不能太死,否则复杂业务接不进来。

第二是动态渲染和性能的矛盾。低代码页面不是几个输入框,真实业务里经常是几百个字段的表单、复杂联动、动态校验,或者多图表联动的仪表盘。如果每次字段变化都让整棵 React 树重新渲染,页面很快就会卡住。

第三是平台复用和工程治理的矛盾。底层引擎、组件库、业务插件、业务应用会快速膨胀,如果没有清晰依赖边界,Monorepo 里很容易出现循环依赖、版本冲突和发版互相拖累。(4 分钟)

当时也有几种可选方案。最简单的是做一套组件库,让业务线自己组合使用。这个能提升 UI 一致性,但解决不了表单联动、权限、数据源和生命周期这些平台问题。第二种是买现成低代码产品,短期快,但我们的业务组件、私有化部署、权限模型和客户现场定制都很重,二次开发成本不可控。第三种是让每个业务线自己封装页面模板,这能解决局部重复,但长期一定会形成多套 DSL 和多套运行时。

所以我最后选择的是做一个基于 Schema 的插件化渲染引擎,核心引擎尽量克制,只负责解析 Schema、调度生命周期、管理状态和渲染插件;业务能力通过插件注册进来。这样底层协议稳定,业务扩展又不会直接污染核心引擎。(6 分钟)

第一层设计是 Schema 协议和插件体系。页面、表单、字段、数据源、校验、联动、权限都用 Schema 描述。核心渲染器只认识统一结构,不关心具体业务组件。文本框、人员选择器、审批流组件、图表组件都通过 registerPlugin 注册自己的渲染逻辑、配置面板、校验规则和生命周期。这样业务线新增组件时,不需要改核心引擎;核心升级时,也不会牵动所有业务代码。

第二层设计是大表单的精确渲染。低代码表单里最容易出问题的是字段联动,比如 A 字段变化影响 B、C 的可见性,C 又影响 D 的校验。单纯依赖 React 自顶向下渲染,字段一多就会出现明显卡顿。所以我在 React 上层维护了一张依赖收集图,记录字段和字段之间、字段和表达式之间、字段和组件之间的依赖关系。某个源字段变化时,只触发受影响的节点重新计算和渲染,而不是全局刷新。

第三层设计是仪表盘和海量数据处理。对于多图表看板,数据聚合和格式转换不能都压在主线程里。我把重计算放到 Web Worker,主线程只负责交互和最终渲染。Worker 回传大量数据时,也不能一次性 setState,所以前端用 requestAnimationFrame 和批处理队列做分片更新,把密集刷新拆到多帧里,避免拖拽、缩放和筛选时卡住。(9 分钟)

第四层是工程治理。随着插件和业务应用变多,我主导把工程拆成 Core Engine、UI Components、Business Plugins、Business Apps 几层,并用 Nx Monorepo 管住依赖方向。底层不能反向依赖业务,上层通过公开 API 使用引擎能力。再配合 lint、tsconfig path、affected build 和缓存机制,把循环依赖和无效构建压下去。

这套方案也有几个必须提前面对的代价。Schema 足够灵活以后,后端怎么存、怎么查、怎么做全文检索会变复杂;大表单依赖图如果处理不好,会出现循环依赖和雪崩更新;拖拽嵌套组件时,光标定位、占位符和滚动容器会带来很多交互边界;多个业务线共用底层引擎时,也会遇到版本兼容和灰度发布问题。这些问题不能靠“低代码”三个字跳过去,必须在架构里预留治理手段。(12 分钟)

如果面试官进一步追问“自定义流程”或者后续 AI 工作流编排,我会把它承接到低代码里的流程引擎难点上:流程不能只是把画布连线存成配置,而要抽象成一张有向无环图,也就是 DAG。节点代表 Start、表单、审批、条件、Webhook、LLM、知识库检索这类业务单元,每个节点有自己的配置 Schema;边代表控制流和数据流,前后端统一用 nodesedges 的 JSON 协议交互。运行时引擎解析这份 JSON,构建邻接表和入度表,再用 Kahn 拓扑排序调度:入度为 0 的节点先进入队列,节点执行完成后把下游入度减 1,下游所有依赖满足后再触发对应的 NodeExecutor。这样画布、流程协议和执行器之间是解耦的,后续要接 AI 节点、向量检索节点或者代码节点,本质上都是新增插件,而不是改核心调度器。

这里真正容易翻车的点有三个。第一是环检测,因为用户在画布上很容易连出 A 到 B、B 到 C、C 再回到 A 的死循环,所以保存时和运行前都要做双重校验,可以用 Kahn 算法看最终处理节点数是否等于总节点数,也可以用 DFS 三色标记法在编译期拦截;如果要显式支持 Loop,也应该把 Loop 做成有明确退出条件的局部子图容器,主图仍然保持 DAG。第二是条件分支和动态剪枝,Condition 节点只会激活某一条分支,未命中的分支不能继续等入度归零,也不能被错误执行,所以要对未选分支做 DFS 标记,写成 SKIPPED 或失效入度,确保主路径下游可以继续推进。第三是全局上下文和变量映射,每次执行都生成一个 ExecutionContext,按 nodeId 隔离存储节点输出,并约定 ${nodeId.variableName} 这样的变量引用格式;节点真正执行前由变量解析器把配置里的占位符解析成上游真实输出,再配合类型校验和作用域隔离,避免异步执行时串数据。这样讲,自定义流程就不是“我会画流程图”,而是能落到 DAG 调度、分支治理和上下文数据流治理这三个底层问题上。

最终这套平台带来的业务价值,是把通用 SaaS 交付从周级缩短到天级。超过 80% 的常规页面不需要前端重新手写,实施团队可以在客户现场完成一部分配置交付;研发团队则把精力放到复杂插件、性能优化和底层引擎上。更重要的是,公司沉淀了一批可复用的业务组件和 Schema 资产,后续新业务不是从零开始,而是在统一底座上扩展。

这里的数字如果被追问,我会先按 目标、边界、证据、价值 限定统计口径。所谓“超过 80%”,不是指所有复杂业务都能低代码化,而是指后台管理、表单、列表、详情、基础仪表盘这类常规页面,能通过已有 Schema 和插件完成主要搭建;涉及复杂算法、强交互编辑器或特殊业务流程的部分,仍然由研发沉淀成插件。所谓“周级到天级”,也不是说所有需求一天上线,而是把原来需要前端排期、开发、联调的常规配置类需求,压缩到配置、验收和少量插件补充。这个口径讲清楚,面试官就不会把它理解成夸张的全场景承诺。

在 AI 协作上,这个平台也有一个自然落点:AI 可以辅助生成 Schema 初稿、插件样板和测试用例,但不能直接把生成结果上线。我们会用 Schema 校验、插件类型约束、预览渲染、快照测试和人工验收去兜住输出质量。这样讲 AI,不是说“用了 AI 所以快”,而是说平台协议稳定以后,AI 才有了可以生成和校验的结构化目标。

从全流工程师角度看,这个项目的核心不是把前端页面做成可拖拽,而是把销售、实施、产品、研发之间反复传递的客户定制知识,沉淀成可以被配置、验证和复用的交付资产。

我一开始不是直接抽组件,而是先从需求池和实施反馈里识别模式:很多需求在页面结构上相似,但字段、权限、联动和流程规则不同。基于这个判断,才把页面、表单、字段、数据源、权限、校验和生命周期统一抽象成 Schema,再通过插件体系把业务差异隔离出去。这样产品能用 Schema 描述能力边界,实施能在客户现场完成配置,研发能围绕 Core、Plugin、App 做任务分解,测试也能围绕 Schema 预览、快照和插件兼容性定义验收。

这里体现的全流能力,是我没有只站在前端实现角度看低代码,而是沿着“需求从哪里来、如何拆成平台能力、如何验证配置正确、上线后如何持续兼容”这条链路来设计平台。

如果用一句话总结,我做的不是一个拖拽搭页面工具,而是把 SaaS 交付里的页面、表单、规则和数据源抽象成可配置、可扩展、可治理的平台能力。这个方案也自然会引出几个深挖点,比如 Schema 如何触发精确渲染,Worker 回传大数据后主线程怎么分片更新,Monorepo 里如何治理版本冲突和循环依赖,复杂嵌套组件怎么做流畅拖拽,以及海量动态 Schema 在后端如何存储和检索。(15 分钟)