AI就绪的前端架构:构建人机协作的新范式

本文探讨了在AI时代如何重构前端架构,涵盖AI指南制定、组件驱动UI、用例模式业务逻辑解耦和中间件链设计,为开发人员提供可测试、可扩展的AI增强开发方案。

AI就绪的前端架构

重新思考AI时代的前端架构

我们正进入一个前端系统不仅供人类使用,还被AI工具解析、生成和解释的时代。现代框架如shadcn/ui、设计到代码工具如V0.dev,以及IDE代理如Junie正在重新定义我们的构建方式。但随着这种加速,对结构的需求也更大。

本指南概述了一个实用架构,用于:

  • 使用AI工具增强UI创建
  • 设计开发者-AI协作协议
  • 维护可测试性和可扩展性

1. 为代码库定义AI指南

大多数AI工具缺乏直觉——所以给它们一个。创建一个guidelines.md文件来描述前端中使用的规则、技术栈和模式。

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Framework: Next.js
Styling: Tailwind CSS 4
Language: TypeScript
Tests: Vitest + Playwright

Architecture:
- Use Case pattern
- Middleware chaining

Standards:
- Named exports only
- Use union types, no enums
- FC with PropsWithChildren

像Junie这样的IDE代理将使用它来遵循您的约定,而无需重复提示。

2. 借助AI辅助采用组件驱动UI

使用V0.dev等工具,您可以在几秒钟内从提示转到JSX:

“创建一个带有两个输入字段和CTA按钮的暗模式注册表单”

V0使用shadcn/ui响应可访问的样式化JSX,准备放入您的仓库。结合Storybook、MDX文档和Junie指南,您在AI和设计系统之间获得反馈循环。

AI生成。您的系统验证。

3. 业务逻辑的用例模式

在AI增强的开发中,生成UI只是等式的一部分。真正的价值在于将业务逻辑与接口层解耦,以便AI代理(或人类)可以安全且可预测地触发行为。这就是用例模式变得至关重要的地方。

什么是用例模式?

核心上,每个用例封装一个单一的业务操作。例如:RegisterUser、CreatePost、SubmitFeedback等。它定义了这样的契约:

1
2
3
export interface UseCase<In = unknown, Out = unknown> {
  handle(param?: In, meta?: UseCaseOptions): Promise<Out>
}

每个用例都是一个隔离、可测试和可注入的单元,对输入进行操作并返回输出。它完全与UI框架或事件源解耦——意味着它可以被以下方式触发:

  • UI按钮
  • 后台作业
  • AI代理
  • Webhook
  • 或所有组合

为什么这对AI很重要?

通过提供稳定接口并隐藏内部逻辑,用例模式允许AI编排应用程序行为而无需知道实现细节。

它防止AI工具(或人类)将逻辑与组件或视图紧密耦合,这通常会导致脆弱、不可维护的代码。

使用useCaseService集中执行

要执行用例,我们使用一个服务层来抽象编排逻辑并允许中间件组合:

1
2
3
4
await useCaseService.execute(RegisterUserUseCase, {
  email: "test@example.com",
  password: "secure-password",
})

此调用不暴露RegisterUserUseCase内部的逻辑——AI只知道它需要传递有效载荷并接收结果。

AI增强系统的优势

  • 可测试性:每个用例都可以使用模拟或存根进行隔离测试
  • 安全性:可以通过中间件添加访问控制或权限检查
  • 可扩展性:可以分层添加新行为(例如分析、错误报告)而无需触及用例逻辑
  • AI就绪性:代理可以通过稳定、定义良好的API表面安全地与您的后端交互

4. 中间件链:通过可组合性扩展逻辑

在结构良好的前端架构中,横切关注点——如日志记录、错误处理和缓存——如果管理不当,很容易污染业务逻辑。中间件提供了一种受责任链模式启发的干净、模块化方法。

不是将此逻辑嵌入每个用例中,而是使用中间件类包装它,这些类在核心逻辑运行之前和之后拦截执行:

1
2
3
4
5
6
7
interface Middleware {
  intercept<In, Out>(
    param: In,
    next: UseCase<In, Out>,
    options: UseCaseOptions
  ): Promise<Out>
}

每个中间件负责单一关注点并沿链传递控制。

错误中间件

无需编写重复的try/catch块,您可以将错误管理委托给中间件。当发生异常时,它会分派错误事件,您的UI可以监听——显示toast或记录问题——而无需触及业务逻辑。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
export class ErrorMiddleware implements Middleware {
  constructor(private readonly eventEmitter: EventEmitter) {}

  async intercept(params: unknown, next: UseCase, options: UseCaseOptions): Promise<unknown> {
    try {
      return await next.handle(params)
    } catch (error) {
      if (!options.silentError) {
        this.eventEmitter.dispatch(EventType.ERROR, error)
      }
      throw error
    }
  }
}

日志中间件

此中间件记录每个用例执行,包括名称和参数。您可以插入不同的记录器实现——开发中的控制台,生产中的远程日志记录——而无需更改任何用例代码。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
export class LogMiddleware implements Middleware {
  constructor(private readonly logger: Logger) {}

  intercept(params: unknown, useCase: UseCase): Promise<unknown> {
    this.logger.log(
      `[${DateTime.fromNow().toISO()}] ${this.getName(useCase)} / ${this.printResult(params)}`
    )
    return useCase.handle(params)
  }

  private getName(useCase: UseCase): string {
    if (useCase instanceof UseCaseHandler) {
      return this.getName(useCase.useCase)
    }
    return useCase.constructor.name
  }

  private printResult(result: unknown) {
    return JSON.stringify(result, null, 2)
  }
}

缓存中间件

如果您使用CQRS分离查询和命令,此中间件可以自动缓存查询结果。提供cacheKey选项的用例将在设定的生存时间内返回缓存结果,减少不必要的处理。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
type CacheEntry = {
  value: unknown
  expiresAt: number
}

export class CacheMiddleware implements Middleware {
  private readonly store = new Map<string, CacheEntry>()

  constructor(private readonly ttlInSeconds: number = 60) {}

  async intercept<In, Out>(
    params: In,
    next: UseCase<In, Out>,
    options: UseCaseOptions,
  ): Promise<Out> {
    const key = options.cacheKey
    if (!key) return next.handle(params, options)

    const now = Date.now()
    const cached = this.store.get(key)

    if (cached && now < cached.expiresAt) {
      return cached.value as Out
    }

    const result = await next.handle(params, options)
    this.store.set(key, { value: result, expiresAt: now + this.ttlInSeconds * 1000 })

    return result
  }
}

使用UseCaseService组合中间件

要应用多个中间件,您使用服务将它们包装在用例周围。此服务从最外层到最内层组合中间件链。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
export class UseCaseService {
  constructor(
    private middlewares: Middleware[],
    private readonly container: Container,
  ) {}

  async execute<In, Out>(
    useCase: Type<UseCase<In, Out>>,
    param?: In,
    options?: UseCaseOptions,
  ): Promise<Out> {
    const requiredOptions = options ?? { silentError: false }

    let next = UseCaseHandler.create({
      next: this.container.create(useCase),
      middleware: this.container.get<EmptyMiddleware>(EmptyMiddleware.name),
      options: requiredOptions,
    })

    for (let i = this.middlewares.length - 1; i >= 0; i--) {
      const current = this.middlewares[i]
      next = UseCaseHandler.create({
        next,
        middleware: current,
        options: requiredOptions,
      })
    }

    return next.handle(param) as Promise<Out>
  }
}

为什么这很重要

有了中间件,您的系统获得:

  • 集中式错误处理
  • 一致的日志记录
  • 自动缓存
  • 更清晰的用例,零重复

您可以在应用程序中扩展功能,而不会增加核心业务逻辑的复杂性。

总结表:AI增强架构

工具/模式 AI角色
UI原型设计 V0.dev + shadcn/ui 从提示生成JSX
UI文档 MDX + Storybook 从示例学习
逻辑层 用例模式 按照定义的模式创建和调用逻辑
粘合层 中间件链 增强而不耦合
IDE协作 .junie/guidelines.md 将AI与您的约定对齐

最后思考

我们不再仅仅为浏览器构建——我们正在构建人类和智能代理都能理解和扩展的系统。

前端的未来不是自动化的。它是增强的。

为以下方面设计您的架构:

  • 可解释性(对人和机器)
  • 结构(通过约定和模式)
  • 可扩展性(通过用例和中间件)

这就是我们如何与AI一起编码,而不是尽管有AI。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计