所属阶段:第四阶段「语言与框架」(第 17-22 课) 前置条件:第 17 课(后端语言) 本课收获:为你的前端框架配置 ECC,掌握 E2E 测试完整方案
一、本课概述
上节课我们学习了后端语言的 Skill 体系。前端领域有自己的独特挑战 --- 组件化架构、状态管理、服务端渲染、水合安全、视觉回归测试。ECC 为这些挑战提供了专门的 Skill。
本课回答三个问题:
- ECC 有哪些前端 Skill? --- 完整清单和适用场景
- E2E 测试如何配置? --- Playwright + POM 模式深入
- 前后端 Skill 如何协作? --- 从 UI 到数据库的完整覆盖
二、前端 Skill 全景
2.1 完整 Skill 清单
| Skill | 定位 | 核心内容 |
|---|---|---|
frontend-patterns |
通用前端模式 | React/Next.js 组件设计、状态管理、性能优化 |
frontend-design |
UI 设计质量 | 高质量 UI 设计原则、组件库选择、无障碍访问 |
e2e-testing |
端到端测试 | Playwright 配置、POM 模式、CI 集成 |
nuxt4-patterns |
Nuxt 4 框架 | SSR 模式、水合安全、自动导入 |
nextjs-turbopack |
Next.js 16+ | 增量打包、Turbopack 配置、App Router |
frontend-slides |
演示文稿 | 幻灯片组件、动画、演示模式 |
browser-qa |
浏览器质量 | 自动化视觉测试、截图对比、跨浏览器兼容 |
2.2 Skill 关系图
vbnet
┌──────────────────────────────────────────────┐
│ frontend-patterns │
│ (React/Next.js 通用:组件、状态、性能) │
├───────────────┬──────────────────────────────┤
│ │ │
│ ┌──────────▼──────────┐ ┌──────────────▼──────────┐
│ │ nextjs-turbopack │ │ nuxt4-patterns │
│ │ Next.js 16+ 专用 │ │ Nuxt 4 专用 │
│ └──────────┬──────────┘ └──────────────┬──────────┘
│ │ │
├───────────────┴──────────────────────────────┤
│ frontend-design │
│ (UI 质量:设计系统、无障碍) │
├──────────────────────────────────────────────┤
│ e2e-testing browser-qa │
│ (功能测试) (视觉测试) │
└──────────────────────────────────────────────┘
三、frontend-patterns 核心内容
3.1 React 组件设计原则
frontend-patterns Skill 强调以下 React 最佳实践:
组件分类:
| 类型 | 职责 | 状态 | 示例 |
|---|---|---|---|
| 展示组件 | 渲染 UI | 无/最少 | Button, Card, Avatar |
| 容器组件 | 数据获取和逻辑 | 有 | UserProfile, OrderList |
| 布局组件 | 页面结构 | 无 | PageLayout, Sidebar |
| 高阶组件 | 逻辑复用 | 取决于 | withAuth, withTheme |
不可变状态管理(呼应 SOUL.md 的 Immutability 原则):
jsx
// WRONG --- 直接修改状态
const handleAdd = (item) => {
state.items.push(item); // 变异!
setState(state); // React 不会重新渲染
};
// CORRECT --- 创建新数组
const handleAdd = (item) => {
setState(prev => ({
...prev,
items: [...prev.items, item] // 新数组,触发重新渲染
}));
};
3.2 状态管理策略
frontend-patterns 推荐分层的状态管理策略:
局部状态 → useState / useReducer (组件内部)
共享状态 → Context / Zustand / Jotai (跨组件)
服务器状态 → TanStack Query / SWR (API 数据)
URL 状态 → 路由参数 / searchParams (可分享)
原则 :状态应该放在最靠近使用它的地方。不要把所有状态都丢进全局 store。
3.3 性能优化
| 问题 | 解决方案 | 何时使用 |
|---|---|---|
| 不必要的重新渲染 | React.memo + useMemo |
大列表、复杂计算 |
| 大型 bundle | 代码分割 + lazy() |
路由级别 |
| 首屏加载慢 | SSR / SSG | 内容型页面 |
| 图片加载慢 | next/image + 懒加载 |
图片密集页面 |
| 长列表卡顿 | 虚拟滚动 | 1000+ 条记录 |
四、框架专用 Skill
4.1 nextjs-turbopack(Next.js 16+)
Next.js 16 引入了 Turbopack 作为默认打包工具,nextjs-turbopack Skill 覆盖:
- App Router:Server Components vs Client Components 的边界划分
- 增量打包:Turbopack 的增量编译策略,开发环境热更新优化
- Server Actions:表单处理、数据变更的服务端模式
- 缓存策略 :
fetch缓存、revalidate、ISR 配置
arduino
关键决策:何时使用 Server Component vs Client Component
Server Component(默认):
✓ 数据获取
✓ 访问后端资源
✓ 敏感信息(API key)
✗ 事件处理
✗ 浏览器 API
Client Component('use client'):
✓ 事件处理(onClick 等)
✓ useState / useEffect
✓ 浏览器 API(localStorage 等)
✗ 直接数据库查询
4.2 nuxt4-patterns(Nuxt 4)
Nuxt 4 的 Skill 重点关注 SSR 安全和 Vue 3 的组合式 API:
水合安全(Hydration Safety)是 Nuxt 4 最常见的坑:
css
服务端渲染 HTML → 客户端 JS 接管 → 对比 DOM 是否一致
↓
不一致 = 水合错误!
常见水合错误原因:
- 使用
Date.now()或Math.random()--- 服务端和客户端结果不同 - 直接访问
window或document--- 服务端没有这些对象 - 条件渲染依赖客户端状态 --- 服务端和客户端渲染结果不同
nuxt4-patterns 的解决方案:
- 使用
<ClientOnly>组件包裹仅客户端内容 - 使用
useNuxtApp()的$client标志做条件判断 - 自动导入系统避免手动 import 导致的 tree-shaking 问题
五、E2E 测试深入
5.1 e2e-testing Skill 核心
e2e-testing 是前端 Skill 中最重要的测试 Skill,基于 Playwright 构建完整的 E2E 测试方案。
Playwright 配置模板:
javascript
// playwright.config.js
const config = {
testDir: './e2e',
timeout: 30000,
retries: process.env.CI ? 2 : 0,
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'on-first-retry',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
],
};
5.2 POM(Page Object Model)模式
POM 是 e2e-testing Skill 强烈推荐的测试组织模式:
bash
e2e/
├── pages/ # Page Object 定义
│ ├── login.page.js # 登录页
│ ├── dashboard.page.js # 仪表盘页
│ └── settings.page.js # 设置页
├── fixtures/ # 测试夹具
│ └── auth.fixture.js # 认证状态
├── specs/ # 测试用例
│ ├── login.spec.js
│ └── dashboard.spec.js
└── playwright.config.js
Page Object 示例:
javascript
// e2e/pages/login.page.js
class LoginPage {
constructor(page) {
this.page = page;
this.emailInput = page.locator('[data-testid="email"]');
this.passwordInput = page.locator('[data-testid="password"]');
this.submitButton = page.locator('[data-testid="submit"]');
this.errorMessage = page.locator('[data-testid="error"]');
}
async goto() {
await this.page.goto('/login');
}
async login(email, password) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
测试用例示例:
javascript
// e2e/specs/login.spec.js
test('should login with valid credentials', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('user@example.com', 'password');
await expect(page).toHaveURL('/dashboard');
});
5.3 截图/视频/Trace 管理
| 产物 | 何时生成 | 存储策略 | CI 注意事项 |
|---|---|---|---|
| 截图 | 失败时自动 | test-results/ |
作为 CI artifact 上传 |
| 视频 | 首次重试时 | test-results/ |
仅保留失败用例的视频 |
| Trace | 首次重试时 | test-results/ |
用 npx playwright show-trace 回放 |
5.4 Flaky Test 隔离策略
Flaky test(时灵时不灵的测试)是 E2E 测试最大的痛点。e2e-testing Skill 推荐:
- 重试机制 :CI 环境设置
retries: 2,本地设置retries: 0 - 等待策略 :永远不要用
sleep,用 Playwright 的自动等待或waitFor - 数据隔离:每个测试创建自己的测试数据,不依赖其他测试的状态
- 标记隔离 :用
test.fixme()标记已知 flaky 测试,定期修复
javascript
// 不要这样写
await page.waitForTimeout(3000); // 硬等 3 秒
// 应该这样写
await page.waitForSelector('[data-testid="loaded"]'); // 等待确定信号
六、browser-qa Skill
6.1 自动化视觉测试
browser-qa Skill 补充了 e2e-testing 的功能测试,聚焦视觉回归:
r
功能测试(e2e-testing):按钮点击后跳转正确吗?
视觉测试(browser-qa):按钮的颜色、位置、大小变了吗?
视觉测试的核心流程:
markdown
基准截图(baseline)
↓
当前截图(current)
↓
像素级对比
↓
差异超过阈值? → 标记为回归
6.2 跨浏览器兼容性
browser-qa 结合 Playwright 的多浏览器支持,确保在 Chrome、Firefox、Safari 上的一致表现。
七、前后端 Skill 协作
7.1 全栈项目的 Skill 组合
一个典型的全栈项目需要三层 Skill 覆盖:
┌─────────────────────────────────────────────┐
│ 前端层 │
│ frontend-patterns + e2e-testing │
│ (React 组件 + Playwright 测试) │
├─────────────────────────────────────────────┤
│ API 层 │
│ api-design + backend-patterns │
│ (RESTful 设计 + 分层架构) │
├─────────────────────────────────────────────┤
│ 数据层 │
│ postgres-patterns + database-migrations │
│ (查询优化 + 零停机迁移) │
└─────────────────────────────────────────────┘
7.2 常见全栈 Skill 组合
| 技术栈 | 前端 Skill | API Skill | 数据 Skill |
|---|---|---|---|
| React + Node | frontend-patterns, e2e-testing |
api-design, nestjs-patterns |
postgres-patterns |
| Next.js 全栈 | frontend-patterns, nextjs-turbopack |
api-design, backend-patterns |
postgres-patterns, database-migrations |
| Vue + Django | nuxt4-patterns, e2e-testing |
api-design, django-patterns |
postgres-patterns |
| React + Spring | frontend-patterns, e2e-testing |
api-design, springboot-patterns |
jpa-patterns |
7.3 协作场景示例
场景:用户列表页面需要分页功能。
bash
前端 Skill 指导:
frontend-patterns → 分页组件设计、URL 状态同步
e2e-testing → 分页翻页的 E2E 测试
API Skill 指导:
api-design → 分页参数格式(page/limit)、响应信封格式
backend-patterns → Service 层分页逻辑
数据 Skill 指导:
postgres-patterns → OFFSET/LIMIT vs 游标分页性能
database-migrations → 添加分页所需索引
八、本课练习
练习 1:浏览前端 Skill(10 分钟)
bash
# 查看前端 Skill 列表
ls skills/frontend-patterns/
ls skills/e2e-testing/
回答问题:
frontend-patterns涵盖了哪些子主题?e2e-testing推荐的测试组织方式是什么?
练习 2:设计 POM 结构(15 分钟)
为一个包含以下页面的应用设计 Page Object 结构:
- 登录页
- 注册页
- 商品列表页
- 商品详情页
- 购物车页
- 结算页
写出 e2e/pages/ 目录下的文件列表,以及每个 Page Object 的关键定位器(locator)。
练习 3:规划全栈 Skill 组合(20 分钟)
这是本课最重要的练习。
为一个前后端分离项目规划 Skill 组合:
- 前端:Next.js App Router
- 后端:你的主力语言(Python/Go/Java 等)
- 数据库:PostgreSQL
列出每层需要的 Skill,并说明每个 Skill 在项目中解决什么具体问题。
练习 4(选做):思考题
Nuxt 4 的水合安全问题和 Next.js 的 Server/Client Component 边界问题,本质上是同一类问题吗?它们的共同根源是什么?
九、本课小结
| 你应该记住的 | 内容 |
|---|---|
| 前端 Skill | 7 个 Skill 覆盖组件设计、E2E、视觉测试、SSR 框架 |
| E2E 核心 | Playwright + POM 模式 + 失败时截图/视频/trace |
| Flaky Test | 不要 sleep,用自动等待;数据隔离;CI 重试 |
| 前后端协作 | 三层 Skill 覆盖:前端层 + API 层 + 数据层 |
| 全栈组合 | 按技术栈选择 Skill 组合,确保每层都有覆盖 |
十、下节预告
第 19 课:移动端开发 --- Swift / SwiftUI / Dart / Flutter
下节课我们将进入移动端领域。Swift 生态的 Skill 非常深入 --- 从 Swift 6.2 的并发模型到设备端 LLM,再到 Flutter 的跨平台架构。你将了解移动端开发与 Web 开发在 Skill 配置上的关键差异。
预习建议 :提前浏览 skills/swiftui-patterns 和 skills/dart-flutter-patterns 目录。