返回博客列表

Compose Web:VS Code 插件驱动的全栈脚手架系统

深入探讨基于 VS Code 插件的全栈网站脚手架设计——三层积木结构、自然语言驱动、多栈支持与自验证自修复机制。

#VS Code Extension#Full-Stack#Scaffold#AI#TypeScript

引言

在现代 Web 开发中,脚手架工具已经非常成熟:Create React App、Vite、Next.js CLI 等。但这些工具解决的是项目初始化问题,而非业务代码生成问题。

Compose Web 试图填补这个空白:不是生成空白的项目骨架,而是通过自然语言对话,组装完整的业务功能。

核心定位

与现有工具的对比

工具解决问题输出
Create React App项目初始化空白项目骨架
Cursor/Copilot代码补全代码片段
v0.devUI 生成前端组件
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'
}

多栈支持

支持的技术栈组合

#前端后端数据库
1Vue 3Node (Express)PostgreSQL
2ReactNode (Express)PostgreSQL
3Vue 3Python (FastAPI)PostgreSQL
4ReactPython (FastAPI)PostgreSQL
5Next.js内置 API RoutesPostgreSQL
6Nuxt 3内置 ServerPostgreSQL
7Vue 3Go (Gin)PostgreSQL
8ReactGo (Gin)PostgreSQL
9SvelteNode (Express)PostgreSQL
10AngularNode (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 客户端设计
  • 项目初始化流程

等待实现阶段。


相关链接


最后更新: 2026-05-13