关于 frontend-architecture
Exceptionless.Web 的前端开发规范技能,面向维护和扩展其界面的编码 Agent。它规定新界面默认使用 Svelte 5,并说明旧 Angular 界面的维护边界、代码组织和测试要求。
主要功能
- 01新界面默认采用 Svelte 5
- 02区分新旧 Angular 界面职责
- 03按功能切片组织代码
- 04规定 TypeScript 与组件约定
- 05涵盖无障碍和测试规范
适用场景
- 01为 Exceptionless.Web 新增页面或组件
- 02判断功能应修改 Svelte 还是 Angular
- 03为前端代码审查一致性规范
- 04为界面改动选择测试与验证方式
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ exceptionless/ exceptionless --skill frontend-architecture安装后在 Claude Code 中输入/frontend-architecture确认已加载。
详细介绍
前端架构
Exceptionless.Web 目前有两个前端代码库:
src/Exceptionless.Web/ClientApp.angular是旧版 Angular UI,目前仍为网站的大部分功能提供支持。请仅将其用于维护。除非用户明确要求修改 Angular 或旧版 UI,否则不要编辑它、向其中添加路由,也不要移植其中的模式。该目录下的主要文件夹有app/、components/、less/、img/、lang/和grunt/。src/Exceptionless.Web/ClientApp是 Svelte 5 应用,也是所有新前端 UI 开发的目标位置。
默认使用 Svelte。如果请求中提到“前端”“UI”“页面”“组件”“表单”或“路由”,且没有明确提到 Angular,请在 src/Exceptionless.Web/ClientApp 中开展工作。
仅当用户明确要求 Angular、旧版 UI,或要求修复仅存在于该目录中的屏幕问题时,才在 ClientApp.angular 中开展工作。
目录结构
src/
├── lib/
│ ├── features/ # Feature slices (vertical organization)
│ │ ├── auth/
│ │ │ ├── api.svelte.ts
│ │ │ ├── models.ts
│ │ │ ├── schemas.ts
│ │ │ └── validators.ts
│ │ ├── organizations/
│ │ ├── projects/
│ │ ├── events/
│ │ └── shared/ # Cross-feature shared code
│ ├── generated/ # API-generated types
│ └── utils/ # Utility functions
├── routes/
│ ├── (app)/ # Authenticated app routes
│ ├── (auth)/ # Authentication routes
│ ├── status/ # Public status route
│ ├── +layout.svelte
│ └── routes.svelte.ts
└── app.html
功能切片
按功能组织文件,并在添加文件前遵循最接近的现有功能结构:
features/organizations/
├── api.svelte.ts # TanStack Query hooks (see tanstack-query skill)
├── models.ts # Feature-local types and generated type aliases
├── schemas.ts # Zod validation schemas
├── options.ts # Dropdown options, enums
└── components/
└── *.svelte
格式化组件(必须使用)
如果存在对应组件,请使用格式化组件,而不是自定义格式化函数。
| 组件 | 路径 | 用途 |
|---|---|---|
<DateTime> | $comp/formatters/date-time.svelte | 日期和时间显示 |
<TimeAgo> | $comp/formatters/time-ago.svelte | 相对时间(“3 小时前”) |
<Duration> | $comp/formatters/duration.svelte | 时间长度 |
<Bytes> | $comp/formatters/bytes.svelte | 文件大小、内存 |
<Number> | $comp/formatters/number.svelte | 按区域格式显示数值 |
<NumberCompact> | $comp/formatters/number-compact.svelte | 紧凑格式的数值 |
<Boolean> | $comp/formatters/boolean.svelte | 真/假显示 |
<Currency> | $comp/formatters/currency.svelte | 金额 |
<Percentage> | $comp/formatters/percentage.svelte | 百分比数值 |
<DateMath> | $comp/formatters/date-math.svelte | Elasticsearch 日期数学表达式 |
<DateTime value={event.date} />
<Bytes value={event.size} />
{formatDateTime(event.date)}
{new Date(event.date).toLocaleString()}
导入别名
import { Button } from "$comp/ui/button"; // shared components
import { User } from "$features/users/models"; // $lib/features
import { cn } from "$lib/utils"; // $lib
项目 Svelte 规则
- 对计算状态优先使用
$derived,对副作用优先使用$effect。 - 必要时在
$effect中使用untrack(),以避免响应式循环。 - 对路由查询参数绑定,优先使用
$shared/query-params中的createQueryParameters,不要自行解析 URL。 - 使用 Svelte 5 事件属性,例如
onclick和oninput;新代码中不要使用旧版on:click语法。 - 新组件中使用片段(
{#snippet children(...)}/{@render children?.()}),而不是插槽。 - 条件类名使用数组语法或本地
cn()助手函数。
一致性规则
创建新内容前,先在 Svelte 应用中搜索现有模式:
- 找到与你要构建的内容最接近的 Svelte 实现。
- 遵循其文件结构、命名、导入方式和组件组合方式。
- 复用
$shared/和$comp/中的共享工具与组件。 - 如果现有工具几乎满足需求,请扩展它,而不是另行创建类似工具。
不要将旧版 Angular 应用的架构复制到 Svelte 中。
TypeScript 规则
- 文件和目录使用 kebab-case。
- 控制流语句始终使用花括号。
- 函数体包含语句时,使用块体箭头函数。
- 标识符不要使用缩写:使用
organization,而不是org;使用filter,而不是filt。 - 优先使用具名导入。对于 shadcn 复合组件(例如
Dialog、DropdownMenu、Field和Card),可以使用命名空间导入。 - 避免使用
any;请使用生成的类型、显式接口、unknown或类型守卫。 - 始终等待 Promise,或有意处理不等待结果的后台任务。
UI 组件
- 按钮、输入框、菜单、对话框、卡片、徽章、分隔线、空状态、骨架屏和表单字段优先使用
$comp/ui/*中已有的 shadcn-svelte 组件。 - 文档结构仍适合使用原生语义元素(
main、section、nav、form、table,以及无需使用应用组件时的button)。不要用通用的样式化div替代语义元素。 - 如需了解 shadcn 组件组合的详细规则,请使用
shadcn-svelte技能。 - 匹配 Exceptionless 的运营型产品 UI 风格:紧凑、克制、易于浏览,并与邻近页面保持一致。避免在应用内使用营销风格的主视觉布局和装饰性视觉实验。
无障碍
- 使用语义化地标,并保持清晰、唯一的标题层级。
- 每个表单控件都需要关联的标签或无障碍名称。
- 仅含图标的按钮需要
aria-label;装饰性图标应设置aria-hidden="true"。 - 对话框必须有标题,即使该标题在视觉上隐藏。
- 错误状态应设置
aria-invalid,并通过aria-describedby关联帮助或错误文本。 - 保留键盘导航和可见的焦点状态。
前端测试
- 单元测试和组件测试使用 Vitest 与 Testing Library,并与代码放在一起,文件扩展名为
.test.ts或.spec.ts。 - 优先使用无障碍查询:
getByRole、getByLabelText,然后是可见文本;只有在语义不足以定位时才使用测试 ID。 - E2E 测试使用 Playwright,且只能针对本地应用 URL。优先使用 role/label 选择器,而不是 CSS 选择器。
- 为改动的行为添加有针对性的测试;不要扩大与任务无关的覆盖范围。
- 迭代期间,运行最小范围的相关测试或针对性验证。每次小改动后都不要运行大范围的 Svelte 验证。只有在推送或提交 PR 前仍有未推送的前端改动时,或用户明确要求时,才运行
npm run validate。此命令会格式化文件,因此之后要检查git status,并在同一提交中纳入所有格式化改动。
导航偏好
优先使用 href 导航,而不是 onclick/goto。只有在需要异步逻辑(例如保存后再导航)时才使用 onclick。
复合组件模式
创建新组件前,先研究相邻的功能组件。共享选项集使用 options.ts;对话框、菜单、卡片和字段使用 shadcn 复合组件导入;表单使用 tanstack-form 技能。
评论
支持 Markdown