引言
在现代 Web 开发中,脚手架工具已经非常成熟:Create React App、Vite、Next.js CLI 等。但这些工具解决的是项目初始化问题,而非业务代码生成问题。
Compose Web 试图填补这个空白:不是生成空白的项目骨架,而是通过自然语言对话,组装完整的业务功能。
核心定位
与现有工具的对比
| 工具 | 解决问题 | 输出 |
|---|---|---|
| Create React App | 项目初始化 | 空白项目骨架 |
| Cursor/Copilot | 代码补全 | 代码片段 |
| v0.dev | UI 生成 | 前端组件 |
| compose-web | 业务功能组装 | 完整功能模块 |
核心价值
用户描述: "添加一个用户管理页面,支持增删改查"
传统方式:
1. 创建路由
2. 编写表格组件
3. 实现增删改查逻辑
4. 连接 API
5. 添加表单验证
...(可能需要数小时)
compose-web:
Agent 分析意图 → 选择积木 → 组装生成 → 自验证修复
...(分钟级完成)
三层积木结构
设计理念
积木的设计遵循最小可组合单元原则:
┌─────────────────────────────────────────────────────────────┐
│ Composite 层 │
│ 完整页面/系统 │
│ 例如:用户管理后台、博客前台、电商首页 │
├─────────────────────────────────────────────────────────────┤
│ Component 层 │
│ 功能组合 │
│ 例如:登录表单、用户卡片、数据表格、搜索栏 │
├─────────────────────────────────────────────────────────────┤
│ Atom 层 │
│ 最小功能单元 │
│ 例如:按钮、输入框、API 路由、数据库字段 │
└─────────────────────────────────────────────────────────────┘
Atom 层定义
interface Atom {
id: string
type: 'ui' | 'api' | 'data'
name: string
description: string
// 技术栈适配
adapters: {
[frontend: string]: {
template: string
dependencies: string[]
}
}
// 使用约束
constraints: {
requires?: string[]
conflicts?: string[]
}
}
// 示例:按钮 Atom
const ButtonAtom: Atom = {
id: 'atom-button',
type: 'ui',
name: 'Button',
description: '通用按钮',
adapters: {
'vue': {
template: `<button class="btn {{variant}}" @click="onClick">{{label}}</button>`,
dependencies: []
},
'react': {
template: `<button className="btn {{variant}}" onClick={onClick}>{label}</button>`,
dependencies: []
},
'svelte': {
template: `<button class="btn {{variant}}" on:click={onClick}>{label}</button>`,
dependencies: []
}
},
constraints: {}
}Component 层组合
interface Component {
id: string
name: string
description: string
// 组成的 Atom
atoms: AtomReference[]
// 组合逻辑
composition: {
layout: LayoutTemplate
wiring: WiringScript
}
// 支持的技术栈
supportedStacks: string[]
}
// 示例:登录表单 Component
const LoginFormComponent: Component = {
id: 'comp-login-form',
name: 'LoginForm',
description: '用户登录表单',
atoms: [
{ ref: 'atom-input', props: { type: 'text', label: '用户名' } },
{ ref: 'atom-input', props: { type: 'password', label: '密码' } },
{ ref: 'atom-button', props: { label: '登录', variant: 'primary' } },
{ ref: 'atom-button', props: { label: '注册', variant: 'secondary' } }
],
composition: {
layout: 'vertical-form',
wiring: 'connect-form-submit'
},
supportedStacks: ['vue', 'react', 'svelte']
}Composite 层系统
interface Composite {
id: string
name: string
description: string
// 组成的 Component
components: ComponentReference[]
// 页面结构
structure: {
routes: RouteDefinition[]
layout: LayoutDefinition
}
}
// 示例:用户管理后台 Composite
const UserManagementComposite: Composite = {
id: 'comp-user-management',
name: 'UserManagement',
description: '用户管理后台',
components: [
{ ref: 'comp-data-table', slot: 'main' },
{ ref: 'comp-search-bar', slot: 'header' },
{ ref: 'comp-user-form', slot: 'modal' },
{ ref: 'comp-pagination', slot: 'footer' }
],
structure: {
routes: [
{ path: '/users', component: 'UserList' },
{ path: '/users/:id', component: 'UserDetail' }
],
layout: 'admin-layout'
}
}VS Code 插件架构
整体架构
┌─────────────────────────────────────────────────────────────┐
│ VS Code Extension │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Extension Host │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Command │ │ Status │ │ File │ │ │
│ │ │ Handler │ │ Bar │ │ Watcher │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────▼──────────────────────────────────────────────┐ │
│ │ Webview Panel │ │
│ │ ┌─────────────────────────────────────────────────┐│ │
│ │ │ Chat Interface ││ │
│ │ │ • 用户输入 ││ │
│ │ │ • AI 回复显示 ││ │
│ │ │ • 行动日志 ││ │
│ │ └─────────────────────────────────────────────────┘│ │
│ │ ┌─────────────────────────────────────────────────┐│ │
│ │ │ Diff Preview ││ │
│ │ │ • 显示将要修改的文件 ││ │
│ │ │ • Diff 高亮 ││ │
│ │ └─────────────────────────────────────────────────┘│ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────▼──────────────────────────────────────────────┐ │
│ │ Core Services │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Agent │ │ Block │ │ Verification│ │ │
│ │ │ Core │ │ Manager │ │ Service │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Context │ │ LLM │ │ Project │ │ │
│ │ │ Reader │ │ Client │ │ Initializer│ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Webview 通信机制
// Extension Host → Webview
interface ExtensionToWebview {
type: 'response' | 'progress' | 'diff' | 'error'
payload: any
}
// Webview → Extension Host
interface WebviewToExtension {
type: 'input' | 'confirm' | 'cancel' | 'config'
payload: any
}
// 通信示例
webview.postMessage({
type: 'diff',
payload: {
files: [
{ path: 'src/pages/UserManagement.vue', diff: '...' },
{ path: 'src/api/user.ts', diff: '...' }
]
}
})增量上下文读取
问题背景
在大型项目中,如果每次生成都要读取完整项目上下文,成本太高。需要增量读取策略。
双模式设计
interface ContextReader {
// 快速扫描:秒级,用于定位插入点
quickScan(project: Project): Promise<QuickContext>
// 深度分析:分钟级,用于理解项目结构
deepAnalyze(project: Project): Promise<DeepContext>
}
// QuickContext:仅包含结构信息
interface QuickContext {
structure: {
directories: string[]
entryPoints: string[]
configFiles: string[]
}
patterns: string[] // 识别的设计模式
}
// DeepContext:包含完整理解
interface DeepContext {
...QuickContext
components: ComponentAnalysis[]
apis: ApiAnalysis[]
dependencies: DependencyGraph
}智能触发策略
function determineContextMode(request: UserRequest): 'quick' | 'deep' {
// 简单添加:quick
if (request.type === 'add-component' && request.target) {
return 'quick'
}
// 架构变更:deep
if (request.type === 'add-feature' || request.type === 'refactor') {
return 'deep'
}
// 默认:quick
return 'quick'
}多栈支持
支持的技术栈组合
| # | 前端 | 后端 | 数据库 |
|---|---|---|---|
| 1 | Vue 3 | Node (Express) | PostgreSQL |
| 2 | React | Node (Express) | PostgreSQL |
| 3 | Vue 3 | Python (FastAPI) | PostgreSQL |
| 4 | React | Python (FastAPI) | PostgreSQL |
| 5 | Next.js | 内置 API Routes | PostgreSQL |
| 6 | Nuxt 3 | 内置 Server | PostgreSQL |
| 7 | Vue 3 | Go (Gin) | PostgreSQL |
| 8 | React | Go (Gin) | PostgreSQL |
| 9 | Svelte | Node (Express) | PostgreSQL |
| 10 | Angular | Node (NestJS) | PostgreSQL |
Adapter 模式实现
interface StackAdapter {
frontend: FrontendAdapter
backend: BackendAdapter
database: DatabaseAdapter
}
class VueExpressPostgresAdapter implements StackAdapter {
frontend = {
name: 'vue',
transformAtom: (atom: Atom) => string,
transformComponent: (comp: Component) => string
}
backend = {
name: 'express',
transformApi: (api: ApiDefinition) => string,
generateRoute: (route: RouteDefinition) => string
}
database = {
name: 'postgresql',
transformSchema: (schema: SchemaDefinition) => string,
generateMigration: (migration: MigrationDefinition) => string
}
}自验证自修复机制
三级策略降级
normal → conservative → minimal
↓ ↓ ↓
完整生成 安全模式 最小化
interface GenerationStrategy {
level: 'normal' | 'conservative' | 'minimal'
// normal: 完整功能
generateFull(request: UserRequest): Promise<GeneratedCode>
// conservative: 安全模式
generateSafe(request: UserRequest): Promise<GeneratedCode>
// minimal: 最小化
generateMinimal(request: UserRequest): Promise<GeneratedCode>
}
async function generateWithFallback(
request: UserRequest,
strategy: GenerationStrategy
): Promise<GeneratedCode> {
try {
// 尝试完整生成
const code = await strategy.generateFull(request)
const validation = await validate(code)
if (validation.passed) return code
// 降级到安全模式
strategy.level = 'conservative'
const safeCode = await strategy.generateSafe(request)
const safeValidation = await validate(safeCode)
if (safeValidation.passed) return safeCode
// 降级到最小化
strategy.level = 'minimal'
return strategy.generateMinimal(request)
} catch (error) {
// 异常时直接降级
strategy.level = 'conservative'
return strategy.generateSafe(request)
}
}验证流程
async function validate(code: GeneratedCode): Promise<ValidationResult> {
const results: ValidationResult[] = []
// 1. Lint 检查
results.push(await runLint(code))
// 2. 类型检查
results.push(await runTypeCheck(code))
// 3. 单元测试(如果有)
if (code.tests) {
results.push(await runTests(code.tests))
}
// 4. 运行时检查(可选)
if (code.hasRuntimeCheck) {
results.push(await runRuntimeCheck(code))
}
return {
passed: results.every(r => r.passed),
errors: results.flatMap(r => r.errors)
}
}多文件拓扑排序
问题背景
当生成涉及多个文件的修改时,需要按照依赖顺序进行修改,否则可能导致中间状态不可用。
拓扑排序算法
function sortFilesByDependency(
files: FileModification[]
): FileModification[] {
// 构建依赖图
const graph = new Map<string, Set<string>>()
for (const file of files) {
const deps = analyzeDependencies(file)
graph.set(file.path, deps)
}
// 拓扑排序
const sorted: string[] = []
const visited = new Set<string>()
const visiting = new Set<string>()
function visit(path: string) {
if (visited.has(path)) return
if (visiting.has(path)) {
throw new Error('Circular dependency detected')
}
visiting.add(path)
const deps = graph.get(path) || new Set()
for (const dep of deps) {
visit(dep)
}
visiting.delete(path)
visited.add(path)
sorted.push(path)
}
for (const file of files) {
visit(file.path)
}
return sorted.map(path => files.find(f => f.path === path)!)
}当前状态
设计阶段完成。架构文档产出:
- 系统设计文档
- 积木系统设计
- Agent 系统设计
- VS Code 插件设计
- LLM 客户端设计
- 项目初始化流程
等待实现阶段。
相关链接
- GitHub 仓库(opens in a new tab)
- compose-web 项目页
- VS Code Extension API(opens in a new tab)
- v0.dev(opens in a new tab) - 参考产品
最后更新: 2026-05-13