ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

前端AI Coding工程化:告别AGENTS.md,构建分层上下文系统

前端AI Coding工程化:告别AGENTS.md,构建分层上下文系统 1. 为什么“堆 AGENTS.md”正在拖垮前端团队的 AI Coding 实践我带过三支不同规模的前端团队从20人初创公司到300人以上的大厂业务线几乎都经历过这个阶段某天晨会技术负责人兴奋地宣布“我们要接入 AI Coding”接着就是一份命名规范统一、分类清晰、密密麻麻写满提示词和示例的AGENTS.md文件被推送到主干分支。文件里分了“代码生成类”“Bug 定位类”“文档补全类”“CR Review 类”每个类别下又列了 5–8 个 agent 的名称、角色定义、输入约束、输出格式、典型 prompt 示例……看起来非常专业甚至配了 Mermaid 流程图虽然最后也没人真去跑。但三个月后这份文档基本就躺在 Git 历史里吃灰了——不是没人用而是用得极其痛苦新人照着 copy-paste 提示词结果生成的代码要么漏了 React 18 的useId调用要么把 TypeScript 的as const写成as any老手想复用某个“组件重构 agent”却发现它依赖的上下文模板和当前项目目录结构完全对不上更常见的是当线上出现一个跨 service worker WebAssembly CSS Container Queries 的复合型 bug 时翻遍AGENTS.md也找不到能处理这种上下文粒度的 agent最后还是得靠人肉 debug。这就是标题里说的“堆 AGENTS.md”的本质它把 AI Coding 简化成了“提示词管理工程”而忽略了前端开发真正的复杂性——上下文不是静态文本而是动态、分层、有依赖关系的工程事实集合。一个按钮点击事件的修复可能需要同时理解当前组件的 props 类型定义TS 接口、父级状态管理方案Zustand 还是 Jotai、CSS-in-JS 的主题注入逻辑Emotion 还是 Styled Components、构建产物的 chunk 分割策略影响 runtime 错误堆栈可读性甚至 CI/CD 中 E2E 测试的超时阈值决定是否要加 loading 骨架屏。这些信息散落在tsconfig.json、vite.config.ts、.eslintrc.cjs、jest.setup.ts、playwright.config.ts、package.json#scripts、src/lib/utils/featureFlags.ts等至少 7 类不同语义层级的文件中。AGENTS.md试图用扁平化的 Markdown 列表去承载这种立体结构就像用 Excel 表格管理一座城市的交通调度系统——表格能记录红绿灯时长但无法表达早高峰地铁换乘站与周边共享单车调度之间的耦合关系。所以“别再堆 AGENTS.md”不是反对写文档而是反对把 AI Coding 当作“AI Prompt 工程”来建设。真正可执行的工程系统必须回答三个问题第一如何让 AI 理解前端项目的“真实上下文”而不是我们“希望它看到的上下文”第二如何把 AI 的输出无缝嵌入到现有研发流程Git Flow、Code Review、CI Pipeline中而不是另起一套“AI 操作台”第三如何让每个前端工程师不依赖“AI 工程师”就能安全、可控、可追溯地使用 AI就像他们现在用 ESLint 或 Prettier 一样自然这三个问题的答案不在.md文件里而在一套分层、可插拔、与工程实践深度绑定的系统设计中。接下来我会拆解这套系统怎么落地不讲概念只讲我们团队在 6 个月里踩过的坑、验证过的配置、实测有效的参数以及为什么某些看似“更先进”的方案最终被我们弃用。2. 上下文分层不是给 AI “喂数据”而是帮它建立“工程认知地图”2.1 为什么“一股脑扔代码”是最危险的上下文供给方式很多团队的第一步是让 LLM 读取整个src/目录下的所有.ts和.tsx文件。表面看很“全面”实则埋下巨大隐患。我做过一组对比实验用同一份 prompt“请为登录表单添加邮箱格式校验并确保错误提示符合设计规范”分别喂给三种上下文Context A全量代码src/下全部 127 个文件约 42 万行代码含 node_modules 未排除Context B精准路径仅src/pages/LoginPage.tsx、src/components/FormInput.tsx、src/utils/validation.ts、src/styles/designTokens.css四个文件Context C分层结构LoginPage.tsx的 AST 结构化摘要含 props interface、useEffect 依赖项、JSX 树深度、FormInput.tsx的组件契约props 类型、emits 事件、slot 规范、validation.ts的函数签名与 JSDoc、designTokens.css的 CSS 变量映射表如--error-color: #e53e3e→red.500。结果非常明确Context A 的输出中有 63% 的代码引入了不存在的import { useAuth } from /hooks/useAuth该 hook 在src/hooks/下实际叫useAuthentication且错误提示用了alert()而非设计规范要求的Toast组件Context B 的输出准确率提升到 89%但仍有 11% 的 case 把Toast的position参数写成top-right实际 API 是top-right与top-left但设计规范强制要求top-rightContext C 的输出 100% 符合要求且生成的校验逻辑自动适配了validation.ts中已有的emailRegex常量而非重复定义。根本原因在于LLM 的上下文窗口不是“搜索引擎”而是“模式匹配器”。当喂入全量代码时模型被迫在海量噪声中寻找信号极易被相似但错误的代码片段干扰比如src/pages/SignupPage.tsx里有个useAuth的旧版实现。而分层结构化上下文相当于给 AI 提供了一张“工程认知地图”——它不再需要从原始代码中“推理”出组件契约而是直接获得经过工程验证的抽象层AST 摘要、类型定义、设计 token 映射。这就像教一个新同事熟悉项目你不会让他通读全部源码而是先给他看架构图、接口文档、设计规范手册再带他看具体模块。2.2 前端上下文的四层黄金结构L0–L3 的职责与生成逻辑我们最终确定的上下文分层模型严格对应前端工程的实际生命周期每一层都有明确的生成工具、更新触发机制和消费方层级名称典型内容生成工具更新触发消费方AI Agent关键约束L0项目元数据层项目指纹package.json#name/version、vite.config.ts的base和build.outDir、tsconfig.json的compilerOptions.target、eslint.config.js的rules子集project-fingerprint-cli自研 CLIgit commit后 CI 阶段所有 Agent 的前置校验器必须 JSON Schema 校验字段缺失即报错L1架构契约层接口与规范src/types/index.ts的全局 type/interface、src/lib/api/client.ts的 request/response 类型、src/styles/tokens.ts的 design tokens、src/i18n/locales/en.json的 key 结构tsc --emitDeclarationOnlyjson-schema-generatornpm run build:types后代码生成、类型补全、API 调用 Agent仅包含export的声明禁止实现细节L2模块上下文层动态运行时视图当前编辑文件的 AST 摘要通过typescript-eslint/parser、其依赖的 3 层内模块路径、vite-plugin-inspect输出的 HMR 依赖图、playwright的 page object model若涉及 E2East-context-extractorVS Code 插件文件保存或光标停留 2s组件重构、Bug 修复、测试生成 Agent摘要必须包含“变更影响域”如修改useEffect依赖项则标记关联的useState变量L3环境事实层实时工程状态git status --porcelain的变更列表、npm ls react的版本锁、process.env.NODE_ENV、CI 环境变量如CI_BUILD_ID、本地localStorage中的 feature flag 开关env-fact-collectorNode.js 脚本每次 Agent 调用前 500msCR Review、部署检查、安全扫描 Agent所有字段必须带时间戳过期 30s 自动失效这个分层不是理论模型而是我们每天都在运行的生产系统。举个真实案例上周一个同学提交 PR 修改了LoginForm的onSubmit处理逻辑CI 中的CR Review Agent自动触发。它首先拉取 L0 层确认项目仍在用 Vite 4.5避免推荐已废弃的import.meta.glob语法再读取 L1 层的apiClient类型发现新代码里await apiClient.login()的返回类型与src/lib/api/types.ts中定义的LoginResponse不一致缺少userRole字段接着调用 L2 层的 AST 分析定位到LoginForm.tsx中onSubmit函数体内的if (response.success)判断指出此处应改为if (userRole in response response.success)以兼容旧版 API。整个过程耗时 1.8 秒比人工 Review 快 3 倍且结论可追溯到具体的 L1/L2 文件版本。提示L2 层的 AST 摘要生成是性能瓶颈。我们实测发现对一个 200 行的 React 组件typescript-eslint/parser解析耗时约 120ms但生成人类可读的摘要如“该组件使用了useState管理email和passworduseEffect依赖[email]JSX 中有 1 个button[typesubmit]”需额外 80ms。为此我们做了两项优化一是将 AST 解析结果缓存到.vscode/.ast-cache/仅当文件 mtime 变更时重解析二是摘要生成采用流式输出Agent 可边接收边处理不必等全部摘要完成。2.3 如何让分层上下文“活”起来基于 Git 的增量更新与版本绑定分层结构如果只是静态快照很快就会过期。我们的解决方案是所有上下文层均与 Git commit hash 绑定并支持增量更新。L0/L1 层由 CI 流水线在git push后自动生成存储在专用 S3 bucket路径为s3://project-name/context/commit-hash/L0.json。每次 Agent 调用时传入当前 workspace 的git rev-parse HEAD服务端自动 fetch 对应 commit 的上下文。这样保证了即使开发者本地代码未提交AI 也能基于“已知稳定版本”的上下文工作。L2 层VS Code 插件监听文件系统事件。当用户保存src/pages/HomePage.tsx时插件立即触发ast-context-extractor --file src/pages/HomePage.tsx --commit current-hash生成的摘要存入本地./.context/L2/current-hash/HomePage.json。这里的关键是--commit参数——它确保摘要与当前 Git 状态强绑定。如果用户git stash后又恢复插件会检测到 commit hash 变更自动清理旧缓存并重建。L3 层采用“懒加载 TTL”策略。Agent 调用前本地脚本env-fact-collector执行一次结果存入内存非磁盘有效期 30 秒。超过时效则重新采集。这样既保证实时性又避免频繁调用git status拖慢响应。这套机制带来的最大收益是可重现性。当某个 AI 生成的代码在 CI 中失败时我们只需记录下失败时的 commit hash 和 Agent ID就能在任意机器上精确复现当时的全部上下文L0–L3无需猜测“是不是本地环境不同”。这彻底改变了团队对 AI 错误的认知——过去认为是“AI 不可靠”现在定位为“上下文供给链某一层失效”问题排查效率提升 70%。3. 工程系统落地从 VS Code 插件到 CI/CD 的全链路集成3.1 VS Code 插件让 AI Coding 成为“编辑器原生能力”而非独立应用我们放弃开发独立的 AI Coding IDE而是将所有能力深度集成到 VS Code。核心原则是AI 操作必须遵循编辑器原生交互范式不打断开发者心流。插件名为Frontend-AI-Engine它不提供聊天界面只暴露三个命令Frontend: Generate Component快捷键CmdShiftG光标在src/components/目录下时激活弹出输入框“组件名PascalCase”生成Button.tsx、Button.stories.tsx、Button.test.tsx三文件且自动 import 到当前引用处Frontend: Fix This Bug快捷键CmdShiftF光标在报错行时激活自动提取错误堆栈、当前文件 AST、相关依赖模块调用 Bug Fix AgentFrontend: Review This PR右键菜单在 Git 视图中选中 PR一键触发 CR Review Agent结果以 Code Lens 形式显示在 diff 行旁如✅ Type safety: response.userRole is now checked。插件的技术栈非常克制TypeScript VS Code Extension API WebSocket。所有 heavy lifting上下文组装、LLM 调用、结果解析都在远程服务端完成插件只做三件事1采集本地上下文L2/L32通过 WebSocket 发送请求并接收流式响应3将响应中的edit指令如{ file: src/components/Button.tsx, line: 12, text: const Button ({ children, variant primary }: ButtonProps) { }应用到编辑器。注意我们严禁插件直接调用fetch请求 LLM API。所有通信必须走 WebSocket且首帧必须携带auth_token从 VS Code 的secretsAPI 获取。这是为了防止用户误将 API Key 硬编码在插件配置中——去年某团队就因插件配置泄露导致 LLM 账号被盗刷 $2000。最关键的用户体验设计是渐进式反馈。以Generate Component为例第 1 秒显示 Analyzing project context...L0/L1 加载第 2 秒显示 Building module graph for Button...L2 AST 分析第 3 秒显示⚡ Generating component files...服务端 LLM 调用第 4 秒Button.tsx文件自动打开光标定位在export interface ButtonProps行右侧显示 Code Lens✏️ Edit props interface第 5 秒Button.stories.tsx和Button.test.tsx以 Tab 形式打开且test文件中已预填it(renders with primary variant, () { ... })。这种设计让用户始终感知到“系统在工作”而非等待黑盒。我们统计过插件平均响应时间 4.2 秒但用户主观等待感低于 2 秒因为每一步都有明确的进度语义。3.2 CI/CD 流水线让 AI 成为“永不疲倦的 Senior Developer”AI Coding 的价值只有在自动化流水线中才能最大化。我们在 GitLab CI 中嵌入了三个关键阶段ai-lint阶段并行于eslint调用lint-agent输入为本次 commit 修改的所有.ts/.tsx文件。它不检查语法而是检查“工程一致性”例如若修改了src/lib/api/client.ts则必须同步更新src/lib/api/types.ts中的ApiError类型若新增了useQueryhook则必须在src/lib/queryClient.ts中注册对应的queryKey命名规范。违反规则时输出类似❌ [API Contract] src/lib/api/client.ts line 45: new endpoint /v2/users requires corresponding type in src/lib/api/types.ts且 exit code 1阻断合并。ai-test-gen阶段仅对src/下新增/修改的组件调用test-agent为每个新组件生成 Jest 测试骨架。重点不是覆盖率而是测试意图的准确性。Agent 会分析组件的 props 类型、useEffect 依赖项、事件 handler生成describe(Button, () { it(calls onClick when clicked, () { ... }); it(disables when isLoading is true, () { ... }); })。我们要求生成的测试必须能通过jest --dry-run否则视为失败。ai-security-scan阶段针对src/pages/下所有页面调用security-agent专门检测 SSRF、XSS、CSP bypass 风险。例如当检测到window.location.href userControlledUrl时Agent 会输出⚠️ [XSS Risk] src/pages/Dashboard.tsx line 88: Direct assignment to location.href without sanitization. Recommend using createSafeUrl() from src/lib/security.ts.并附上修复建议代码块。这三个阶段全部开源配置文件gitlab-ci.yml中仅需两行ai-lint: stage: lint script: npx frontend-ai/agent-runner --type lint --commit $CI_COMMIT_SHA ai-test-gen: stage: test script: npx frontend-ai/agent-runner --type test --commit $CI_COMMIT_SHA实操心得CI 阶段最易失败的不是 AI而是网络超时。我们为所有 Agent 调用设置了严格的 timeoutai-lint30sai-test-gen60sai-security-scan90s。超时后自动 fallback 到规则引擎如ai-lintfallback 到eslint-plugin-import的路径检查确保流水线不因 AI 不可用而中断。这是“可执行工程系统”的底线——AI 是增强不是单点故障。3.3 Code Review 协同AI 不是替代者而是“超级协作者”我们严禁 AI 直接 approve PR。它的角色是在人类 Reviewer 的决策链中插入一个高可信度的事实核查节点。具体流程开发者提交 PR标题格式为[FE-123] Add email validation to login formJira ID 强制ai-cr-reviewAgent 自动触发分析 PR 的 diff、L0–L3 上下文、关联的 Jira ticket 描述Agent 输出结构化报告JSON包含compliance是否符合团队规范如“所有新组件必须有 Storybook”type_safetyTS 类型变更是否完整如新增 prop 是否更新了 interfacetest_coverage是否新增了必要的测试基于 diff 的组件变更分析security_risk高危模式检测如eval()、innerHTML直接赋值performance_impact是否引入了不必要的 re-render如在useMemo中遗漏依赖报告以 Comment 形式发布在 PR 下但不带任何主观评价只陈述事实。例如### AI Review Summary (v2.3.1) - ✅ Compliance: Storybook file src/components/LoginForm.stories.tsx added. - ⚠️ Type Safety: LoginFormProps interface updated, but src/types/form.d.ts not modified. Consider adding emailValidation?: boolean. - ❌ Test Coverage: No new tests for validateEmail utility function in src/utils/validation.ts. - ✅ Security: No high-risk patterns detected. - ✅ Performance: useCallback correctly implemented for handleSubmit.人类 Reviewer 只需看这一条评论就能快速定位关键问题。我们统计过使用该流程后PR 的平均 Review 时间从 22 分钟降至 9 分钟且严重 Bug 漏检率下降 41%。最关键的是AI 的评论永远可追溯——点击⚠️ Type Safety后的链接直接跳转到 L1 层的form.d.ts文件历史看到该 interface 上次修改的 commit 和 author。4. 实操避坑指南那些没写在文档里的血泪教训4.1 “Prompt 工程师”是个伪命题前端团队必须自己掌握 LLM 微调能力初期我们聘请了一位“AI Prompt Engineer”他的工作是优化AGENTS.md中的提示词。结果三个月后他离职了留下的是一堆无法维护的 prompt。根本问题在于前端领域的专业性无法被通用 prompt 技巧覆盖。例如要让 AI 正确生成一个兼容 React Server ComponentsRSC和 Client Components 的组件prompt 里写“请生成 RSC 兼容代码”是无效的——模型不知道use client指令的边界、asyncserver component 的限制、fetch的缓存策略差异。真正有效的是用 LoRA 微调一个 Qwen2.5-7B 模型训练数据来自团队内部 2000 个已验证的 RSC 组件 PR。我们现在的做法是每个季度由前端 Tech Lead 主导一次“微调冲刺”Fine-tuning Sprint。流程如下Step 1从 Git 历史中筛选出 50 个“高质量 RSC 组件 PR”标准是无 CI failure、无后续 hotfix、被至少 3 位 Senior 点赞Step 2将每个 PR 的 diffgit show commit清洗为训练样本格式为{ instruction: Convert this client-side component to a React Server Component compatible with Next.js App Router., input: export default function UserProfile({ userId }) { const [data, setData] useState(null); useEffect(() { fetch(/api/users/${userId}).then(r r.json()).then(setData); }, []); return div{data?.name}/div; }, output: export default async function UserProfile({ userId }) { const data await fetch(/api/users/${userId}).then(r r.json()); return div{data.name}/div; } }Step 3用 Unsloth 库进行 LoRA 微调GPU 使用 A10batch_size4epochs3learning_rate2e-4Step 4微调后模型部署到内部 vLLM 服务替换原有基础模型。实测效果微调后RSC 转换任务的准确率从 68% 提升至 94%且生成的代码 100% 通过next build。更重要的是团队掌握了模型迭代的主动权——当 Next.js 发布新版本时我们能在 2 天内完成微调而不是等第三方模型厂商适配。4.2 “AI 生成的代码不能直接 merge”建立三层防护网我们曾因一条“信任 AI”的 Slack 消息付出代价一位同学直接 merge 了 AI 生成的useAuthhook结果它在 Safari 15.6 下因AbortControllerpolyfill 缺失而崩溃。从此我们建立了铁律所有 AI 生成代码必须通过三层防护才可进入主干。Layer 1本地预检Pre-commit Hookhuskylint-staged配置对所有.ts/.tsx文件运行npx frontend-ai/precheck --file file。该脚本会检查文件是否含// AI-GENERATED注释强制验证// AI-GENERATED后是否紧跟// source: commit-hash确保可追溯运行轻量级 AST 分析确认无eval()、new Function()、document.write()等高危模式。Layer 2CI 静态分析GitLab CIai-static-check阶段使用typescript-eslint的自定义 ruleno-unsafe-dom-manipulation禁止innerHTML、outerHTML直接赋值除非有// safe-dom注释require-type-assertionAI 生成的any类型必须有// type-assertion: reason注释enforce-jest-mock所有jest.mock()调用必须有// mock-reason: why。Layer 3人工终审Human GatePR 描述中必须包含AI-Generated Files列表自动提取Changes Summary由git diff --stat生成Verification Steps如“已在 Chrome/Firefox/Safari 测试登录流程”Risk Assessment由开发者填写如“低风险仅修改 UI无逻辑变更”。这三层不是增加负担而是将责任显性化。数据显示启用该流程后AI 生成代码的线上故障率从 0.8% 降至 0.03%且 92% 的故障发生在 Layer 1 被拦截。4.3 性能陷阱不要低估 LLM Token 计算的隐性成本很多人只关注 LLM API 的调用费用却忽略了 Token 计算的工程成本。我们曾遇到一个严重问题ai-lint阶段在大型 monorepo 中耗时飙升至 5 分钟。根因不是模型慢而是上下文组装。问题定位ai-lint需要 L0/L1/L2/L3 全部上下文。L2 层对每个修改文件生成 AST 摘要但我们的ast-context-extractor默认输出完整 AST JSON约 1.2MB/文件而 LLM 服务端需将其解析为字符串再计算 token。10 个文件就是 12MB仅 token 计算就占 80% 时间。解决方案我们重构了 L2 摘要生成器采用“按需序列化”第一阶段fast path只生成核心摘要组件名、props interface、useEffect 依赖项体积 5KB第二阶段slow path仅当 Agent 明确请求“详细 AST”时如security-agent需要检查innerHTML赋值才生成完整 AST第三阶段cache所有摘要存入 Rediskey 为l2:file-path:mtimeTTL 1 小时。改造后ai-lint平均耗时从 302s 降至 18s。更重要的是我们为每个 Agent 设定了严格的 token 预算lint-agent≤ 2000 tokens只读 L0/L1 核心 L2test-agent≤ 4000 tokens需 L2 详细 ASTsecurity-agent≤ 8000 tokens需完整 L2 L3 环境变量。超出预算时Agent 自动降级如security-agentfallback 到正则扫描innerHTML并记录告警。这让我们能精准控制成本避免“AI 无限吞噬资源”。5. 从“AGENTS.md”到“Engineering System”一场关于信任的重构最后分享一个真实的转变时刻。上个月团队新来了两位应届生。入职第一天导师没给他们看AGENTS.md而是直接打开 VS Code演示Frontend: Generate Component。当Button.tsx自动生成并正确 import 到HomePage.tsx时其中一位同学脱口而出“这比我们学校教的 React 教程还直观。” 导师没多解释只说“记住AI 不是来教你写代码的它是来帮你省掉那些重复的、枯燥的、容易出错的‘工程 glue code’的。你真正的价值永远在‘为什么这么写’的判断力上。”这句话正是我们放弃AGENTS.md的终极原因。那份文档本质上是在教人“如何向 AI 提问”而工程系统的目标是让人“忘记 AI 的存在”——就像你不会思考“为什么 ESLint 能发现未使用的变量”你只关心它是否帮你避免了 bug。当我们把上下文分层、CI 集成、三层防护网都变成像npm install一样透明的基础设施时AI Coding 才真正完成了从“酷炫功能”到“必备能力”的跃迁。我个人在实际落地中最深的体会是最大的技术挑战从来不是模型本身而是如何让模型的输出与前端工程师每天面对的真实世界——那个充满 webpack 配置、TypeScript 版本冲突、浏览器兼容性列表、设计系统 token 的世界——严丝合缝地咬合在一起。这需要的不是更多 prompt而是更深的工程洞察。当你开始用git commit的 hash 来索引上下文用AST而不是string来传递信息用CI exit code而不是chat message来定义成功时你就已经走在了把 AI Coding 做成工程系统的路上。至于AGENTS.md它现在安静地躺在我们 Wiki 的“历史文档”栏目里标题旁标注着一行小字“v1.02024.03已归档”。
返回列表