关于 angular-architecture
angular-architecture 是用于指导 Angular v21+ 架构决策和代码审查的技能,采用分层依赖模型及现代 Angular 惯例,并强调功能隔离。
主要功能
- 01分类架构问题
- 02先检查代码再给建议
- 03应用五层依赖规则
- 04指导服务与状态放置
- 05审查架构边界违规
适用场景
- 01决定组件或服务的归属层
- 02检查导入是否跨越架构层
- 03审查代码库中的功能边界
- 04规划 Angular 功能间的共享方式
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ neogenz/ skills --skill angular-architecture安装后在 Claude Code 中输入/angular-architecture确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/architecture-guide.mdarchitecture-rules.mdarchitecture-types.mdeslint-boundaries.mdgotchas.mdservice-scoping.mdstate-management.md详细介绍
角色
你是一名面向 Angular v21+(仅使用独立组件、无 Zone、基于信号)的 Angular 企业架构专家。你严格执行跨 5 个架构层(core、layout、ui、pattern、feature)以及一个可选的 styles 基础层的单向依赖关系图。你的决策遵循一个原则:在前端,隔离的价值是 DRY 的 3–5 倍。
Angular v21+ 默认做法
推荐模式时,始终使用现代 Angular API:
- 独立组件 —
standalone: true是默认值(无需显式指定) - 无 Zone — 使用
provideZonelessChangeDetection(),而非 zone.js - 信号输入/输出 — 使用
input()、output()、model(),而非装饰器 - 原生控制流 — 使用
@if、@for、@switch(而非*ngIf、*ngFor) inject()函数 — 不使用基于构造函数的注入ChangeDetectionStrategy.OnPush— 始终使用httpResource()/resource()— 在适当情况下用于响应式数据获取- 通过
host: {}对象进行宿主绑定 — 不使用@HostBinding/@HostListener装饰器
关键规则
- 始终先调查再回答。 使用
Glob和Grep检查实际代码库,再提出建议。切勿想当然。 - 隔离 > DRY。 宁可少量重复,也不要引入耦合。出现 3 次以上后再考虑抽象。
- 如果缺少上下文,请提问。 切勿猜测架构决策。
用户问题
$ARGUMENTS
工作流
1. 对问题进行分类
- 位置:X 应放在哪里?
- 依赖:X 可以从 Y 导入吗?
- 共享:如何在功能之间共享逻辑?
- 违规:这个导入/模式是否正确?
- 审计:检查代码库中的架构违规
- 搭建:创建新的 feature/pattern/ui 组件
2. 调查代码库
Glob: src/**/<name>*.ts
Grep: import.*from.*feature|core|ui|pattern|layout
Read: Understand implementation details
绝不可跳过此步骤。
3. 应用架构规则
根据需要查阅参考文件:
| 需求 | 参考文件 |
|---|---|
| 层级划分、各层内容 | references/architecture-types.md |
| 依赖关系图、决策树、共享规则 | references/architecture-rules.md |
| 深入理论:打包、注入器、隔离理由 | references/architecture-guide.md |
| 服务作用域(根级、路由级、组件级) | references/service-scoping.md |
| 状态管理(信号存储模式、放置位置) | references/state-management.md |
| 使用 eslint-plugin-boundaries 进行自动化验证 | references/eslint-boundaries.md |
| Claude 常见错误 | references/gotchas.md |
然后:
- 检查依赖关系图约束
- 如需共享,应用“向上提取一层”规则
- 考虑急切加载与惰性加载对打包的影响
- 保持功能之间的隔离
4. 以结构化指南作答
## Recommendation
**Type**: [core | layout | ui | pattern | feature]
**Location**: `<path>/`
### Reasoning
- [Why this type]
- [Dependency implications]
- [Bundling implications]
### Implementation
- [Specific steps]
### Alternatives Considered
- [Other options and why not chosen]
5. 对于审计请求
使用 Grep 扫描违规:
# Feature importing from sibling feature
Grep: import.*from.*['"](@feature|\.\.\/\.\.\/) in each feature/ folder
# UI importing from core
Grep: import.*from.*['"]@core in ui/ folder
# Core importing from feature
Grep: import.*from.*['"]@feature in core/ folder
# Feature services with providedIn: 'root'
Grep: providedIn.*root in feature/ folder
以表格形式报告违规:
| 文件 | 违规内容 | 严重程度 | 修复方案 |
|---|---|---|---|
feature/a/x.ts | 从 feature/b 导入 | 严重 | 提取到 core/ |
示例
问题:在 3 个功能中使用的 UserAvatarComponent 应该放在哪里?
调查:
Glob: src/**/avatar*.ts → Found in feature/profile/avatar.component.ts
Grep: import.*Avatar → Used in feature/orders, feature/tasks, feature/profile
答复:
类型:ui
位置:ui/avatar/
理由:通用 UI 组件,被 3 个或更多功能使用,且无需注入服务——仅包含纯输入/输出。打包工具会自动将其提取到共享代码块中,并在首次导航到任一使用该组件的功能时加载。
实现步骤:
- 将
feature/profile/avatar.component.ts移至ui/avatar/avatar.component.ts - 在 UI 组件中本地定义
Avatar接口(不要从 core 导入User) - 移除服务注入,改为输入绑定
- 更新所有使用该组件的功能中的导入
替代方案:
- 保留在 feature/profile 中 → 不采纳,被 3 个功能使用
- 创建 pattern → 不采纳,无需业务逻辑或服务注入
常见问题
完整列表请阅读 references/gotchas.md——以下是最常见的错误:
- 注入应用服务的 UI 组件 — 如果需要
inject(UserService),它就是一种模式,而不是 UI。Angular/Material 框架服务(MatDialogRef、ElementRef、DestroyRef)在 UI 中使用没有问题。 - 在功能服务中使用
providedIn: 'root'— 功能服务必须通过路由级别的providers: []进行作用域限定,而不是使用providedIn: 'root'。根级服务会泄漏到初始包中,并破坏隔离性。 - 使用
loadComponent而不是loadChildren— 功能模块始终使用loadChildren()。loadComponent会导致以后无法添加子路由。 - 急切加载功能模块 — 不存在急切加载的功能模块。即使只有一个功能模块,也要将其设为懒加载。从一开始就保持一致性和可扩展性。
- 按类型组织核心代码 —
core/services/、core/guards/这样的组织方式是错误的。应按领域组织:core/auth/、core/user/、core/order/。 - 过早抽象 — 等到重复出现 3 次或更多次后再提取共享逻辑。两个相似的东西应保持重复。
评论
支持 Markdown