低代码平台架构设计方案 - 从浅入深完整指南(2)
前言: 本文系统阐述了一套完整的低代码平台架构设计方案,涵盖从基础架构到企业级应用的全链路技术实现。
核心内容:
🏗️ 四层架构体系:可视化设计器、Schema协议、运行时引擎、物料体系的完整设计
🔄 全局状态管理:基于Zustand的页面级Store架构,支持跨组件数据流动
⚡ 性能优化方案:三种发布模式(纯运行时、Schema编译、混合模式)对比与实践
🎯 动作系统:枚举化业务操作设计,实现配置化与安全性的平衡
🔧 Schema编译器:深度解析编译优化策略,在保持Runtime架构一致性的同时实现70%体积优化
🚀 SSR支持:Next.js集成方案,满足SEO与首屏性能需求
📦 发布流程:从Schema保存到产物部署的完整工程化实践
适合人群:前端架构师、低代码平台开发者、对前端工程化感兴趣的技术人员
全文15万+字,涵盖架构设计、核心实现、性能优化、工程实践等多个维度,提供可直接落地的技术方案。
阶段二:物料独立 - 插件化架构
核心改进: 物料抽离为独立NPM包,支持按需加载 解决问题: 物料复用、按需加载、第三方扩展
3.1 架构演进
阶段一(单体):
┌─────────────────────────────────┐
│ lowcode-platform │
│ ├── designer/ │
│ ├── renderer/ │
│ └── materials/ (内置) │
└─────────────────────────────────┘
↓ 演进
阶段二(物料独立):
┌────────────────────┐ ┌──────────────────┐
│ lowcode-platform │ │ Material Packages│
│ ├── designer/ │ │ @lc/button │
│ ├── renderer/ │ <-- │ @lc/table │
│ └── material- │ │ @lc/form │
│ registry/ │ │ ... │
└────────────────────┘ └──────────────────┘
3.2 物料包结构
@lowcode-materials/button/
├── src/
│ ├── Button.jsx # 组件实现
│ └── index.js # 导出
│
├── lowcode-meta.json # 物料元信息
├── package.json
└── README.md
# lowcode-meta.json
{
"name": "Button",
"title": "按钮",
"category": "basic",
"version": "1.0.0",
"main": "dist/index.js",
"props": [
{
"name": "type",
"title": "类型",
"setter": "SelectSetter",
"options": ["primary", "default", "danger"]
}
],
"snippets": {
"componentName": "Button",
"props": { "type": "primary", "children": "按钮" }
}
}
3.3 物料注册表
// material-registry/MaterialRegistry.js
class MaterialRegistry {
constructor() {
this.materials = new Map(); // 已加载的物料
this.metadata = new Map(); // 物料元信息
}
// 注册物料
register(packageName, config) {
const { component, meta } = config;
this.materials.set(meta.name, component);
this.metadata.set(meta.name, {
packageName,
...meta
});
console.log(`✅ Material registered: ${meta.name}`);
}
// 获取组件
getComponent(componentName) {
return this.materials.get(componentName);
}
// 获取元信息
getMeta(componentName) {
return this.metadata.get(componentName);
}
// 获取所有物料列表(用于设计器展示)
getAllMaterials() {
return Array.from(this.metadata.values());
}
// 动态加载物料包
async loadMaterialPackage(packageName) {
try {
// 方式1: 从CDN加载
const module = await this.loadFromCDN(packageName);
// 方式2: 通过import动态导入
// const module = await import(packageName);
this.register(packageName, module.default);
return true;
} catch (error) {
console.error(`Failed to load material: ${packageName}`, error);
return false;
}
}
// 从CDN加载物料
async loadFromCDN(packageName, version = 'latest') {
const url = `https://cdn.example.com/materials/${packageName}@${version}/index.js`;
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.onload = () => {
// 假设物料包挂载到 window.LowCodeMaterials
const module = window.LowCodeMaterials[packageName];
resolve(module);
};
script.onerror = reject;
document.head.appendChild(script);
});
}
}
export default new MaterialRegistry();
3.4 渲染引擎升级(支持动态物料)
// renderer/Renderer.jsx (升级版)
import React from 'react';
import MaterialRegistry from '../material-registry/MaterialRegistry';
class Renderer extends React.Component {
constructor(props) {
super(props);
this.schema = props.schema;
this.state = {
loading: true,
error: null
};
}
async componentDidMount() {
// 预加载Schema中用到的所有物料
await this.preloadMaterials();
}
// 预加载物料
async preloadMaterials() {
const materialsNeeded = this.collectMaterials(this.schema.componentTree);
for (const componentName of materialsNeeded) {
// 检查是否已加载
if (!MaterialRegistry.getComponent(componentName)) {
const meta = MaterialRegistry.getMeta(componentName);
if (meta?.packageName) {
await MaterialRegistry.loadMaterialPackage(meta.packageName);
}
}
}
this.setState({ loading: false });
}
// 收集Schema中使用的所有组件名
collectMaterials(node, set = new Set()) {
if (node.componentName) {
set.add(node.componentName);
}
node.children?.forEach(child => this.collectMaterials(child, set));
return set;
}
// 渲染节点
renderNode(nodeSchema) {
const { componentName, props, children, id } = nodeSchema;
// 从注册表获取组件
const Component = MaterialRegistry.getComponent(componentName);
if (!Component) {
return <div>Component {componentName} not found</div>;
}
const childNodes = children?.map(child => this.renderNode(child));
return React.createElement(
Component,
{ key: id, ...props },
childNodes
);
}
render() {
if (this.state.loading) {
return <div>Loading materials...</div>;
}
return this.renderNode(this.schema.componentTree);
}
}
3.5 物料开发工具
为了让开发者方便地开发物料,提供脚手架工具:
# 创建物料项目
npx @lowcode/create-material my-button
# 项目结构
my-button/
├── src/
│ └── index.jsx
├── demo/ # 本地预览
│ └── demo.jsx
├── lowcode-meta.json # 物料元信息
├── package.json
└── README.md
// 物料开发模板
// src/index.jsx
import React from 'react';
function MyButton({ type, children, onClick }) {
return (
<button
className={`my-btn my-btn-${type}`}
onClick={onClick}
>
{children}
</button>
);
}
// 导出配置
export default {
component: MyButton,
meta: {
name: 'MyButton',
title: '自定义按钮',
category: 'custom',
props: [
{
name: 'type',
title: '类型',
setter: 'SelectSetter',
options: ['primary', 'secondary']
}
],
snippets: {
componentName: 'MyButton',
props: { type: 'primary', children: '点击' }
}
}
};
3.6 物料发布流程
# 1. 开发物料
cd my-button
npm run dev # 本地预览
# 2. 构建
npm run build # 输出到 dist/
# 3. 发布到NPM
npm publish
# 4. 在低代码平台中安装
npm install @lowcode-materials/my-button
# 5. 注册到平台
import MyButton from '@lowcode-materials/my-button';
MaterialRegistry.register('@lowcode-materials/my-button', MyButton);
3.7 物料市场
提供一个物料市场,让开发者可以浏览、安装物料:
// 物料市场API
class MaterialMarket {
// 搜索物料
async search(keyword) {
const response = await fetch(`/api/materials/search?q=${keyword}`);
return response.json();
}
// 安装物料
async install(packageName) {
// 方式1: 后端NPM安装
await fetch('/api/materials/install', {
method: 'POST',
body: JSON.stringify({ packageName })
});
// 方式2: 前端动态加载
await MaterialRegistry.loadMaterialPackage(packageName);
}
// 获取物料详情
async getDetail(packageName) {
const response = await fetch(`/api/materials/${packageName}`);
return response.json();
}
}
3.8 阶段二总结
优点:
- ✅ 物料独立,可复用和发布
- ✅ 支持按需加载,减小打包体积
- ✅ 第三方可以开发和发布物料
- ✅ 物料可以单独版本管理
缺点:
- ❌ 物料版本管理复杂
- ❌ 缺少统一的构建规范
- ❌ 物料质量参差不齐
- ❌ 依赖管理困难
适用场景:
- 中型团队(5-20人)
- 需要物料复用
- 有第三方物料接入需求