interview202602

# 问题

# 一个表格需要一次性展示 10 万条数据,用户需要支持搜索、排序、筛选、勾选,页面不能卡死,怎么设计?

  • 延伸问题
  1. 勾选状态存储:表格支持多选,用户全选 10 万条数据,怎么存储勾选状态?翻页后回来,勾选状态如何保留?
  2. 排序性能瓶颈:用户排序,10 万条数据时间复杂度 O(nlogn),几百万次比较,阻塞主线程 2s 左右,怎么优化?
  3. 如果后端不支持分页,一次性返回 10 万条数据,有什么方法可以使搜索、排序、筛选不依赖前端全量计算?

考察点:

  1. 数据量和交互复杂度的双重压力下,如何页面始终流畅
  2. 能不能识别内存爆炸、主线程阻塞、勾选状态存储等真实瓶颈
  3. 知不知道不依赖第三方库如何从计算架构层优化
  4. 有没有 web worker、位图存储、分片加载、IndexDB 降级等工程落地经验

大列表核心瓶颈:

  1. 内存占用:10 万条数据对象常驻内存
  2. 计算阻塞:排序、筛选、搜索在主线程执行
  3. 勾选状态存储:全选 10 万条记录的状态结构
  4. 滚动筛选后的状态保留

完整链路:数据获取 =》 DOM渲染 =》 交互响应 =》 内存管理

工程化方案:web worker + 分片加载 + 位图存储勾选状态 + 虚拟滚动

  1. 前端做分片加载:首次加载 2000 条(首屏 + 预滚区),滚动到底部再加载下一批,只保留最近的 3~5 个分片在内存中,老分片数据序列化到 IndexDB
  2. 排序、筛选、搜索放在web worker中:主线程将 10 万条数据发送给 web worker,web worker 在后台计算后,只将可视区域内几十条数据返回给主线程;配合虚拟滚动,用户滚动时主线程根据当前滚动位置向 worker 请求对应切片数据;

补充:“主线程把 10 万条数据发送给 Worker”可能会引入新瓶颈,postMessage 默认是 structured clone ,10 万条对象拷贝可能就很重;让 Worker 直接拿到原始数据 (在 Worker 内 fetch / 或主线程只传 ArrayBuffer/TypedArray 并用 Transferable 转移所有权),或者主线程传“列式数据/索引”而不是整对象数组

  1. 采用位图(BitMap)+范围压缩存储: 勾选状态存储不用 Set 存 10 万个 ID,采用位图(BitMap)+范围压缩存储:
    • 连续选中的 ID 段用[startld,endld]存储,如全选 10 万条只需存[{start: 1, end: 100000}]
    • 不连续的选中用位图压缩(每 8 个 ID 用一个字节存储),实际 10 万条数据的勾选状态内存可控制在12.5KB以内(10 万 bit= 12.5KB)
    • 勾选狀态存储在 Worker 或 IndexedDB 中,不阻塞主线程
    • 全选时只存“取消勾选的少数例外”(excluded);非全选时存“勾选的少数集合”(included)
    • 补充:位图适用于“ID 可映射到 0..N-1 的稠密索引”。如果后端 ID 很稀疏(比如雪花 ID、uuid),位图会爆炸
  2. 排序优化:排序不在主线程做,交给 Worker;如果用户频繁切换排序字段,Worker 任务带 taskId ,新任务来了就“作废旧 taskId 的结果”(丢弃旧结果),取消上一次未完成的排序任务对大数据量排序,可提前建立索引映射(排序只排索引数组,不排原始数据)
  3. 虚拟滚动:react-window,vue-virtual-scroller,或自己封装的虚拟滚动组件

内存管理:

  1. 监控performance.memory.usedJSHeapSize,超过阈值时触发降级(隐藏非可视区图片、释放缘存等)
  2. 页面卸载时主动释放 Worker 和大型数组引用

滚动流畅度:

  1. 使用 requestAnimationFrame 节流滚动事件
  2. 虚拟滚动容器的行高必须固定(或动态测量但做缓存)
  3. 预渲染当前可视区域上/下各一屏的数据,避免滚动白屏

后端不分页的兜底:

  1. 使用 IndexedDB 存储全量数据,利用索引做排序和筛选;但 IndexedDB 的索引能力主要是 按某个 keyPath 的范围查询/游标遍历 ,并不等于任意组合条件、多字段排序、全文检索。适合“单字段索引 + 范围过滤 + cursor 分段读”;复杂查询要么自己建索引结构,要么引入本地数据库方案(如 sqlite/duckdb-wasm 之类,但那属于三方/更重)。
  2. 主线程通过 IDB 游标分片读取,性能比全量内存计算差但不会卡死建索引,通过游标分片读取
  3. 配合 Service Worker 做离线缓存,二次访问秒开

监控:虚拟滚动渲染帧率(低干 30fps 告警)、Worker 响应时间、内存占用峰值、Long Task(>50ms)、交互延迟(INP/自定义点击到响应时间)

降级策略:当数据量超过 5 万条且用户设备为低端机(通过navigator.deviceMemory判断,<4GB)时,提示用户开信“精简模式”(仅展示前 1000 条,并提供搜索引导)

# 导致页面加载白屏时间长的原因有哪些?怎么优化?

真实case:h5页面,首屏是AI信息流,和实时视频流片段,及WebGL渲染的3D头像;上线后白屏时间>=5s,用户流失率较多

基础优化:图片压缩、脚本加defer、减少请求、预连接、AI推荐词计算逻辑放 web worker里...

延伸子问题:如果首屏某个元素初始是display:none,内部css样式规则很复杂,浏览器会不会在首屏解析它?

HTML 解析阶段仍然会解析 DOM 节点,CSS 也会被解析成 CSSOM。display:none 的影响主要是:元素不进入渲染树,不参与 layout/paint;但并不等于“浏览器不解析它、也不处理相关 CSS 规则”。CSS 规则本身解析是成本;全量 style recalc 主要发生在需要计算匹配/布局时,display:none 会减少 layout/paint,但不能把 CSS 复杂度问题一笔抹掉

SSR/CSR 混合页面白屏长,常见原因是:关键 CSS 缺失、主线程被 JS 执行占满、hydrate 期间长任务(CPU 占用)、首屏还在等数据、LCP 资源(大图/视频首帧)晚到。

优化思路:从”加载完整页面“升级为”引导浏览器尽快绘制第一个像素“;设计布局隔离,任务调度,投机提示和关键路径原子化

  1. 第一层:阻塞不再是单纯的文件加载而是“关键任务竞争”

传统阻塞大家都会:CSS阻塞渲染,JS阻塞解析。但2026年的新杀手是第三方AI脚本和实时数据流。

第三方脚本在首屏期间制造 Long Task、频繁 DOM 插入触发布局/样式抖动:比如一个智能推荐脚本,它会在下载后立即调用document.write(即使你用了async),或者持续轮询获取新的推荐卡片,每轮询一次就触发一次DOM插入,导致浏览器反复计算样式。

解决方案不是禁用AI,而是用任务分片调度——把第三方脚本统一放到一个空的iframe中运行,或者defer 、拆包、延后初始化、 requestIdleCallback (也有兼容性问题但更常见)、事件驱动加载、iframe sandbox/隔离等

进阶方案:用Scheduler API将其标记为“低优先级”,确保首屏渲染任务永远排在前面。

  1. 第二层:布局计算不再是确定性的,而是“推测性解析失败”

浏览器有投机预解析器,会提前扫描HTML并下载资源。但2026年的动态HTML(比如AI流式生成的内容)让预解析器经常失效。

更隐蔽的问题来自CSS容器查询和嵌套锚点定位,它们让元素尺寸的体赖关系变成动态图,浏览器可能被迫回退到“全量布局”模式,每次细微变化都要重算整个页面。

  • 优化方案是显式隔离:给独立卡片设置contain: layout style paint,告诉浏览器“这块的内容变化不会影响到外面”,从而阻止布局扩散。数据显示,正确使用contain属性在复杂布局/频繁变动区域可显著减少布局扩散,具体收益取决于页面结构。
  1. 第三层:资源加载不是越快越好而是“头键路径的原子化交付”

现在几乎没有纯HTTP/1.1,都是HTTP/2甚至HTTP/3,多路复用让资源并行看起来很美。但有一个反直觉的事实:同时发起太多请求反而会阻塞首帧。因为浏览器的主线程要花费大量时间去解析响应头、调度回调、处理收到的分块数据。

2026年的新做法是资源分水岭策略:首屏只允许同时存在6个关键请求(HTML、关键CSS、关键JS、英雄图、字体、一个数据接口),其余所有资源(非首屏图片、分析脚本、聊天气泡等)全部延迟到空闲时再请求。这需要对构建工具做精确的资源清单标记,甚至在后端注入“资源优先级”响应头,让CDN直接按优先级排队。

v2补充版:

  1. 先定位白屏属于哪类:是“没像素”还是“像素但不可用”
  • FCP (首个像素)慢:通常是关键 CSS、阻塞 JS、TTFB、HTML 体积、字体、渲染被长任务占用。
  • LCP (首屏主内容)慢:通常是英雄图/视频首帧、首屏数据、WebGL 初始化、骨架屏策略不当。并补一个: Long Task(>50ms)/ INP 来证明“为什么用户感觉卡”。
  1. 针对你的 case(AI 信息流 + 实时视频片段 + WebGL 头像),最该讲的三刀
  • 先渲染壳 :首屏先输出“骨架 + 关键文案 + 占位图/海报”,保证 FCP;AI 信息流和 3D、视频都可以延后填充。
  • 视频“先海报后首帧”:首屏不要把视频解码/拉流当关键路径。用 poster、首帧预生成、IntersectionObserver 进入视口再拉流;必要时先上低码率/短片段。
  • WebGL 延后初始化 :3D 头像往往是白屏杀手(shader compile、纹理上传、首帧渲染都重)。策略是:首屏先渲染静态占位(图片/序列帧/低模),等空闲或用户可见再启动 WebGL;并减少首帧资源(纹理分辨率、模型面数、延后非必要后处理)。
  1. 资源与执行:把“关键路径”讲得可操作
  • Critical CSS :内联关键 CSS 或拆出首屏 CSS,避免等整包 CSS 才出像素。
  • JS 执行预算 :把首屏必须的 JS 控制在一个可接受的执行窗口;非关键模块延后(动态 import、路由级拆包、组件级懒加载)。
  • 优先级提示 : preconnect / dns-prefetch 、 preload 关键字体/英雄图、合理的 fetchpriority (可作为加分点提一下)。
  • 第三方脚本治理 :首屏禁用/延后埋点、AB、客服等;或 iframe 隔离(你写的 iframe 方案可以保留,但强调“隔离不可信脚本、降低主线程扰动”即可)。
  1. SSR/水合相关:把话说到点子上
  • 白屏长的常见原因不是“标记多”,而是 hydrate 期间长任务 + 事件不可用 + 主线程被占满
  • 优化方向: 流式 SSR(尽早 flush 首屏 HTML)、局部/选择性 hydration(islands/partial hydration)、把首屏交互最小化 。

# js中async和defer有什么区别?

  1. 第一层:基础区别
  • 普通script:遇到就暂停HTML解析,下载并立即执行,执行完才继续解析
  • async:异步下载,下载完立即执行,执行期间阻塞HTML解析
  • defer:异步下载,等HTML解析完成后、DOMContentLoaded之前,按顺序执行
  1. 第二层:执行时机与顺序
  • 多个async:谁先下载完谁先执行,顺序不确定,不能依赖
  • 多个defer:严格按服书写顺序执行,保证体赖关系
  • 如果普通script和async/defer混用:
    • 普通script会立即阻塞,优先于任何异步脚本
    • 执行顺序:普通script → 下载完成的async → HTML解析完后的defer
  1. 第三层:与DOMContentLoaded、load的关系
  • defer: 在HTML解析完成后、DOMContentLoaded之前执行;所有defer执行完后才触发DOMContentLoaded
  • async: 在下载完成后执行,可能在DOMContentLoaded之前或之后,不确定;如果async在DOM解析完成前下载完并执行,会延迟DOMContentLoaded
  • load:所有资源(包括async、图片等)加载完后触发,defer已经执行完
  1. 第四层:应用场景
  • defer适合:需要操作DOM的脚本、有依赖关系的库(比如jQuery之后再用jQuery插件)
  • async适合:独立、无依赖、不操作DOM的脚本(比如统计脚本、广告脚本)
  • 普通script头部:关键路径脚本,页面渲染前必须执行的(比如配置、环境检测
  • preload/prefetch:更精细的资源加载控制,配合async/defer使用
  1. 第五层:浏览器底层机制

浏览器解析到script标签时,如果是普通script,会创建parser阻塞,等待网络请求和执行;defer和async都使用非阻塞的加载器,HTML解析继续;但是async执行时,仍然会阻塞主线程,只是不阻塞解析(解析已经暂停)。

现代浏览器优化:预加载扫描器(preload scanner)会在解析HTML时提前发现async/defer脚本,更早开始下载

结论:async和defer都不是“不阻塞”,只是把阻塞延迟到了执行阶段

# 从代码提交到用户访问中间经历了什么?

核心考察点有三个:

  1. 能否说清HTML短缓存加靜态资源长缓存的部署策略,以及蓝绿部署和金丝雀发布的区别。
  2. 知不知道CDN预热和资源加载容灾的设计。
  3. 能不能理解sourcemap安全处理、灰度监控联动、自动回滚的工程闭环。

前端CI/CD的完整流程与部署策略:

  • CI阶段执行代码检查、单元测试、构建打包。
  • 构建产物分为两类,带哈希值的靜态资源如JS、CSS、图片,和入口文件index.html。
  • 靜态资源上传到CDN配置强缓存一年;index.html部署到Web服务器配置协商缓存或不缓存。

代码提交 =》 ci/cd流水线编译打包,生成静态资源,生成版本号 =》 部署到服务器,用户访问

静态资源上传CDN或OSS(对象存储),html模板上传ngnix服务器;

用户访问流程:

  1. 浏览器请求index.html,服务器返回最新版本。
  2. HTML里引用的靜态资源带哈希值,浏览器下载并强缓存。
  3. 下次访问时HTML可能变化,引用新的哈希资源,自然拿到新版本。
  4. 核心是让HTML永远最新,靜态资源永远不更新只新增。

Q:蓝绿部署和金丝雀发布有什么不同?

蓝绿部署是准备两套完全一样的环境,当前版本是蓝环境,新版本部署到绿环境。验证通过后切换流量指向绿环境,蓝环境备用

回滚只需切回蓝环境。金丝雀发布是新版本先给少量用户使用,比如1%到5%,监控没问题逐步扩大,最后全量。两者可以结合,金丝雀发布到绿环境逐步放量。

CDN预热与资容灾:

  • CDN预热是在部署时主动将靜态资源推送到CDN边缘节点,用户访问时值接从边缘节点获取,避免回源延迟。没预热时用户首次访问可能回源到OSS,产生延迟但不影响功能,如果CDN预热未完成,用户访问静态资源,边缘节点 cache miss 会去OSS源站回源拉取。
  • 资源容灾设计是靜态资源加载失败时自动重试。Webpack配置output.publicPath为CDN地址;同时在runtimeChunk配置时对 chunk load error 做监听和重试;必要时切备用静态资源域名或刷新到上一版本 HTML。
  • preload预加载关键资源,提前下载。

正确发布顺序应该是: 先上传静态资源到 OSS/CDN -> 校验资源可访问 -> 再切 HTML

Q:打包时生成的manifest.json,有什么用?

manifest.json 常用于服务端渲染、模板注入、部署校验、资源映射。manifest.json是构建时生成的资源映射文件,记录了入口文件、异步chunk、CSS、字体等所有资源构建产物与逻辑入口的映射关系。服务端渲染时需要读取manifest.json确定引用哪些资源。运行时动态加载也需要通过manifest.json找到对应chunk。

Q:前段监控在部署流程中怎么配合?部署后怎么快速发现新版本有问题?灰度发布和监控怎么联动?如果新版本错误率上升怎么回滚?

部署后的监控指标包括JS错误率、接口错误率、首屏加载时间、白屏率。灰度发布时这些指标按灰度组和对照组分别统计。

自动回滚规则是灰度组的错误率超过对照组一定阈值比如50%或绝对错误率超过1%时自动触发回滚。回滚操作是切流到蓝环境或重新部署旧版本。回滚后自动发送告警通知团队。

监控联动的关键是部署版本号关联。每次都署打上版本标签,监控平台按版本聚合数据。新版本发布后对比前一个版本的指标,判断是否异常。

生产环境的最佳实践如下:

  • index.html使用Cache-Control: no-cache, must-revalidate或较短缓存时间,让浏览器每次访问都先校验 HTML 是否为最新版本
  • 静态资源使用带 hash 的文件名 + Cache-Control: max-age=31536000, immutable永久缓存。
  • CDN开Gzip压缩。部署前做CDN预热。sourcemap只传到Sentry不暴露公网。
  • 金丝雀发布从1%流量开始,维度包括按用户 ID、按 Cookie、按地域、按设备类型、按员工白名单,每5分钟增加5%,错误率超过值自动回滚。
  • 部署完成后跑核心流程的冒烟测试。

# 假设你要从0设计一个类似Taro的跨端框架,核心的代码转换和运行时适配怎么做?

核心问题:

  1. 编译与运行的职责边界:不能仅停留在框架选型,必须清晰界定编译期与运行时的分工。这是跨端框架能否高效、轻量、且具备良好扩展性的底层逻辑。

编译时做静态分析与代码预转换,运行时做动态环境检测与接口桥接。二者如同前端与后端的协作,共同完成从通用代码到原生执行的完整链路。

  1. 抽象语法的跨端映射:核心解决JSX或Vue模板如何被不同平台理解的问题。本质是一种中间层的“翻译”工作,将开发者的统一输入转化为各端原生的执行指令。

通过解析器生成抽象语法树(AST),再基于平台配置(如小程序WXML、RN的原生组件)进行代码生成。这一步实现了“一次编写”的核心价值,屏蔽了各端的语法差异。

  1. 底层能力的统一适配:不同平台的原生能力(路由、存储、事件系统)是异构的。如何在运行时让同一套业务逻辑适配不同的宿主环境,是跨端方案的关键挑战。

通过适配器模式封装统一接口。在运行时根据当前宿主环境,动态切换底层的 API实现,让业务层无需关心具体平台的差异细节,实现逻辑的一致性。

技术难点:

  1. JSX表达不对等:Taro 框架通过编译时方案将JSX转换为小程序的 WXML,是跨端开发的核心技术路径。但二者在语法设计上存在天然的表达能力鸿沟,这种不对等会引发哪些核心技术挑战?又有哪些JSX高级特性在转换中面临难以逾越的障碍?

比如:

  • JSX的动态灵活性:允许在渲染逻辑中嵌入任意JavaScript表达式,包括复杂的三元运算、函数调用和动态数据计算。开发者可以用原生的编程思维实现高度动态、逻辑复杂的UI渲染,这是现代前端开发的核心优势之一。
  • WXML的静态约束:wx:if等指令仅支持简单的变量与字面量判断,无法处理运行时的复杂计算逻辑。这种静态的模板语法设计,导致在将JSX高级特性向小程序转换时,必须付出额外的编译时处理或运行时适配成本。
  1. 全局对象差异:跨端开发的本质是抹平不同运行环境的底层差异。在从传统Web开发向小程序架构迁移的过程中,我们首先会遇到顶层运行环境的断层——浏览器标准API与小程序沙箱环境的核心对象并不互通。这不仅是语法的差异,更是运行时机制的根本不同。

核心技术追问:若用户业务代码中直接使用了浏览器标准的window.location进行页面路由跳转,而小程序的JS引擎执行环境中天然不存在window/document等全局宿主对象,框架在编译转换阶段应当采用何种策略,才能让这段代码在小程序端无报错地平稳运行?

  1. API差异:运行时环境的异构适配

如果用户在业务代码中习惯使用Web标准的localStorage进行数据持久化,但在小程序端对应的原生API是wx,setStorageSync,那么框架在运行时是如何实现无感的自动适配与调用转发?

这不仅仅是简单的函数名映射,更涉及到异步策略、数据格式转换以及错误处理机制的对齐。优秀的跨端框架需要在此处构建透明的适配层,让上层业务逻辑脱离具体的平台实现细节,从而真正实现“一次编写,多端运行”。

  1. 生命周期不一致:运行时行为的一致性鸿沟

React 的 useEffect 钩子在 H5 浏览器与小程序容器中,由于底层事件循环机制、宿主环境的渲染策略差异,其执行时机往往存在难以察觉的微妙偏差。如何设计一套脱离具体宿主的统一运行时生命周期调度器,从框架层面屏蔽平台特性带来的副作用,让开发者编写的业务代码在不同端上表现出完全一致的生命周期行为,是构建高性能、高一致性跨端框架时必须解决的底层架构命题。

  1. 性能优化传递:跨端技术的核心不仅是API的统一,更在于将开发者的优化策略无损地传递到底层运行时。

你的框架支持性能优化的意图传递吗?例如在列表渲染时,用户在DSL中声明了标准的key用于diff算法优化,框架层是如何将其准确映射到各端的?是在小程序环境中自动转换为wx:key,还是在 H5 环境中对应 React 的原生key属性?这种跨平台的标识统一与底层透传逻辑,直接决定了复杂长列表的渲染流畅度与内存消耗表现。

跨端框架三层核心逻辑:

  1. 编译时(Compile-time):负责代码转换、语法降级与API替换。将跨端DSL或高级语法静态编译为目标平台原生代码,是跨端框架的“前端加工工厂”,决定了代码的最终形态与基础性能。

  2. 运行时(Runtime):负责环境模拟、动态API适配与生命周期管理。在应用执行阶段处理平台差异,提供统一的运行沙箱,是跨端逻辑的“动态执行引擎”,保障业务在不同终端的行为一致性。

  3. 桥接层(Bridge):连接编译时与运行时的关键枢纽。高效传递编译优化元信息与运行时上下文,打通静态产物与动态执行环境的数据流,是实现跨端框架“一次编写,多端运行”的核心通信协议。

跨端框架两个核心:

  • 编译时:将框架代码转换成各平台原生代码
  • 运行时:提供统一的API和运行时环境,抹平平台差异

【例1】JSX→ WXML的转换难点: JSX支持任意JS表达式,WXML只支持简单表达式

解法:复杂表达式(如{list.filter(i=> i.visible).map(i=>i.name)})在编译时拆解生成中间变量:const __temp = list.filter(i=>i.visible).map(i=> i.name);然后在WXML中引用这个变量;无法转换的语法(如动态组件)禁止使用或提供替代方案。

  • 补充:小程序模板拿到的数据必须来自 data (或组件 state),__temp 不是天然在模板作用域可见;编译器把表达式下沉到渲染函数/计算阶段,运行时在合适时机计算并通过 setData (或框架的 state 同步机制)把结果喂给模板。复杂表达式每次 state 变化都重算会非常贵,所以往往还需要依赖收集/脏检查/缓存策略(哪怕是很粗的 memo)。

【例2】平台API抹平(运行时适配):

  • 统一API层:框架提供Taro.navigateTo、Taro.setStorageSync
  • 运行时根据平台环境调用对应实现:
    • H5:调用window.location、 localStorage;Web 的 localStorage 是同步 API;小程序同时有 sync/async 版本,但容量、序列化、失败策略都不同。
    • 小程序:调用wx.navigateTo、 wx.setStorageSync;小程序路由是栈模型(navigateTo/redirectTo/switchTab/reLaunch),并且存在页面栈上限、tab 限制等

【例3】生命周期统一:React的 useEffect 在不同平台执行时机不同

  • 解法:框架提供统一的生命周期钩子,如useDidShow(页面显示)、useDidHide(页面隐藏)
  • 底层实现:H5监听pageshow/pagehide事件,小程序监听onShow/onHide

【例4】性能优化传递:列表渲染:用户写的key,编译时转换成各平台对应属性

  • React/H5:直接透传key
  • 小程序:转换成wx:key
  • 虚拟列表:各平台实现方式不同,框架需要封装统一组件

编译器管线:Parse(jsx/ts/vue template) → IR/AST Transform(语法降级、指令化、静态提升、表达式下沉)→ Codegen(WXML/WXSS/JS 或 H5/RN 目标)→ Bundling(依赖图、分包、tree-shaking、平台条件编译)→ 产物携带元信息(用于 runtime)。

组件与事件系统的适配:

  • 组件映射: View/Text/Image 这种基础组件如何抽象?属性差异(class/style/hidden/catchtap)怎么对齐?
  • 事件模型:H5 有事件冒泡/捕获与委托;小程序事件也有冒泡但细节不同,还有 catch 阻止冒泡语义。统一 SyntheticEvent 时要解决:事件名归一、事件对象字段对齐、this/target/currentTarget、性能(频繁 setData + 事件触发)。

样式与布局差异(实际跨端落地经常卡在这里)

  • CSS vs WXSS 支持集差异、选择器限制、单位体系(px/rpx)、样式隔离与作用域、动态 style 的表达(内联 style 在小程序的限制与性能)。

  • 从 0 设计时通常要说明:哪些能力编译期解决(如选择器降级/作用域)、哪些运行时解决(如 style 字符串注入、className 映射)

  • 不是所有 Web API/DOM 能 polyfill: document 、真实 DOM 操作、复杂布局测量等,在小程序里要么重写为抽象 API,要么明确禁止/提供替代(SelectorQuery、createSelectorQuery 等)。

  • JSX 高级能力边界:动态组件( const C = cond ? A : B; )、portal、某些 ref/命令式 DOM、依赖布局回流的逻辑,在小程序目标上通常需要限制或特殊实现。

延伸问题:编译时和运行时的分工?jsx/vue模板如何转换成不同平台支持的模板语法?不同平台的差异(路由/存储/事件)如何抹平?

# 在日均千万级请求的SSR场景下,如何设计一个高可用的Vue服务端渲染状态同步架构?

问题的核心场景

我们的页面既有服务端直出的 HTML,又有客户端激活(Hydration)后的动态交互,需要保证服务端异步数据(比如用户信息、权限菜单)在两端绝对一致,且不能出现客户端二次请求导致的数据闪烁。

注意:

  1. 拒绝粗暴挂载:严禁使用window._INITIAL_STATE_简单挂载数据,必须探索更安全、更规范的状态传递机制。
  2. 坚持SSR架构:不可回退为纯客户端SPA模式,必须保留服务端渲染在首屏性能和SEO上的核心优势。
  3. 全链路数据闭环:方案需覆盖从Node.js服务层数据获取,到浏览器内存状态同步的完整技术链路,确保端到端一致。

考察核心:SSR项目中,在高并发下,如何保证渲染性能与数据一致性的机制平衡。

  1. 能不能识别SSR进程状态隔离、水合失败、异步超时等真实生产问题
  2. 知不知道不依赖window.__INITIAL_STATE_如何做精细化数据注入
  3. 有没有流式渲染、超时熔断、缓存策略等工程落地经验

简单回答:在serverPrefetch里把接口数据取好,塞进context.state,然后客户端在mounted里直接用store.replaceState替换掉就行了。

追问一:(进程状态隔离)你的 Node.js服务是集群部署的,每个进程的内存状态是隔离的。如果用户第一次请求落在A进程,第二次刷新落在了B进程,window.__INITIAL_STATE_只能保证单次请求内的数据同步,你怎么保证用户在不同进程间切换时,Store 数据的一致性?

核心痛点:Node.js进程沙箱隔离导致内存状态无法跨进程共享,负载均衡的请求分发机制会直接打破基于内存的状态同步策略

追问二:(水合匹配报错)页面中使用异步组件(如复杂图表库)时,为避免服务端无效渲染,采用ClientOnly组件跳过服务端编译。但该组件的 Props依赖父组件响应式数据,导致 Hydration阶段客户端虚拟DOM与服务端 HTML结构不一致,触发Text contents did not match致命报错,该如何破局?

  • 核心成因:状态断层。服务端渲染时,Clientonly内部内容被注释或留白,而客户端挂载时才渲染真实内容。若Props依赖的响应式数据在两端初始值不同,DOM结构会发生突变,导致水合校验失败。

  • 关键解法:数据锚定与惰性加载。确保服务端与客户端初始数据严格一致;或在onMounted生命周期中延迟初始化依赖数据,让ClientOnly组件在客户端完全挂载后再接收动态 Props,彻底消除两端渲染差导。

追问三:(异步超时降级)接口网关偶发3秒超时,导致SSR服务挂起,Node.js事件循环微任务堆积、内存暴涨。如何为异步数据设置超时中断,并智能降级为客户端渲染(CSR),保障服务稳定性?

  1. 异步超时强制熔断:利用 Promise.race()封装请求逻辑,设定合理超时阈值(如500ms),超时即中断异步请求,释放事件循环资源,防止微任务队列阻塞堆积。
  2. SSR转CSR优雅降级:超时后返回“骨架屏”或核心静态HTML,前端接管数据请求。通过hydration机制复用DOM结构,确保页面核心内容可用,非关键数据客户端异步补充。
  3. 内存监控与兜底防护:建立 Node.js内存水位告警机制,配合进程管理工具(如PM2)进行自动重启兜底。同时对关键接口实施缓存策略,降低对不稳定网关的依赖。

追问四:(流式渲染优化)如果线上突然爆发流量峰值,SSR服务CPU飙到 90%,渲染一个完整页面需要500ms,响应太慢。你不能扩容机器,怎么通过流式渲染(Streaming SSR)或者Fragment分段渲染,让浏览器能边接收边渲染,首屏时间缩短50%?

  1. 核心重构:从整体到片段。摒弃传统的一次性全量渲染,将页面拆分为独立的渲染片段(Fragment)。浏览器无需等待完整HTML传输完毕,可“接收一块、解析一块、渲染一块”,彻底打破渲染阻塞。

  2. 优先级调度:首屏资源优先。在服务端渲染时,优先处理并输出首屏关键内容(导航、核心文案),延迟加载非关键区域(页脚、推荐列表)。最大化利用有限的CPU资源,确保用户最关注的内容最先呈现。

  3. 架构落地:分块编码与Suspense。利用HTTP/1.1的Chunked Encoding实现分块传输,结合Suspense 、streaming、分块 flush、首屏壳优先输出等技术实现组件级流式交付。实测可将首屏渲染耗时降低50%以上,显著提升高负载下的用户体验。

第一层:先明确状态同步的边界。先区分数据维度:

  • 全局靜态数据:比如网站配置、字典表,服务端注入后客户端直接消费,无需更新
  • 用户私密数据:比如登录态、个人信息,必须严格一致,不能出现服务端展示Admin,客户端闪一下变成 Guest
  • 动态异步数据:比如实时排行榜、评论列表,允许秒级延迟,但必须在Hydration完成后静默更新

以高并发内容型页面为例,必须严格区分这三类数据的注入和更新策略。

第二层:选一种核心方案,落地高可用设计。以改进版“分层数据注入+渐进式 Hydration”为例(最经典、抗 Node抖动):

  1. 数据预取分层:
  • 同步数据:在createServer阶段直接读取内存配置,通过renderToStringcontext传给模板,直接内联在 HTML的data-属性中

补充:script[type="application/json"] 注入非执行型 JSON;

  • 异步核心数据:通过 asyncData配合Promise.allSettled发起请求,设置600ms超时中断,超时后道接抛出错误,走CSR降级
  • 非关键数据:不阻塞渲染,在客户端mounted后用useAsyncData靜默拉取,并配合骨架屏
  1. 进程状态隔离方案:
  • 放弃在Node内存中存Store,每次请求通过createStore 工厂函数新生一个Store实例,挂载在 context.store
  • 序列化Store时,去掉大型非必要字段,用flatted库或者自定义toJSON处理循环引用,控制 HTML 体积
  • 补充:createStore 工厂函数只能解决“单次请求污染”和“请求隔离”,解决不了 A 进程渲染、B 进程刷新 的数据一致性。状态源不能放在 Node 进程内存里 ,要外置到 DB / Redis / Session / JWT / 配置中心 / BFF ,SSR 每次都基于请求上下文重新拉取同一份权威数据源。
  1. 水合匹配兜底:
  • 异步组件用defineAsyncComponent配合ssr: false,在服务端完全忽略
  • 涉及客户端动态数据(如 window.innerWidth)的部分,用onMounted钩子配合nextTick延迟到水合完成后渲染,避免匹配报错
  • 开Vue 的compilerOptions.isCustomElement,对复杂第三方UI库直接跳过SSR;它的作用是告诉编译器“把某个标签当原生自定义元素处理”,避免当成 Vue 组件解析,不会帮你解决 hydration mismatch。

时序图:请求到达 => 数据预取超时分流 => Factory Store 生成 => HTML注入 => 客户端水合 => 非关键数据补拉

第三层:生产落址的异常处理细节

  1. Node.js内存与性能:监控 eventLoopLag,一旦延迟超过50ms,触发报警。使用cls-hooked维护请求上下文,避免AsyncLocalStorage在旧版Node中的内存泄漏
  2. 接口降级熔断:利用axios-retrycircuit-breaker-js,当下游接口错误率超过10%时,直接熔断并走本地Mock数据,优先保证页面道出
  3. 缓存策略:在Nginx或CDN层缓存完整HTML,设置 Cache-Control: s-maxage=1, stale-while-revalidate=59,允许过期缓存短暂复用,扛住流量尖峰
  4. Streaming流式传输:将页面拆分为Header、Content、 Footer多个 Slot,利用pipe 流边渲染边发送,首字节时间(TTFB)直接降至200ms以内

状态同步链路:

  • 浏览器请求带上 cookie / token / request headers
  • BFF/SSR 层按请求上下文并行拉取用户态、权限、页面数据
  • 生成 request-scoped store
  • 只序列化首屏 hydration 必需字段
  • 客户端启动时先消费该快照,再决定哪些数据后台静默刷新

如果面试里让我给这题一个更稳的回答骨架

  • 第一句定原则 :状态真源在外部系统,SSR 节点只做请求级快照组装,不保存跨请求用户态。
  • 第二句讲同步机制 :每次请求创建独立 store,服务端并行拉取首屏必需数据,序列化最小必要快照,通过安全 JSON payload 注入 HTML,客户端启动时直接消费同一份快照,避免二次请求闪烁。
  • 第三句讲一致性 :用户态、权限、AB 实验、地区信息都必须来自同一份 request context,保证服务端首屏和客户端 hydration 输入一致。
  • 第四句讲高可用 :异步请求设置超时和取消,核心接口失败走缓存或降级壳,非核心接口延后到 hydration 后补拉。
  • 第五句讲高并发 :公共页面做 CDN/片段缓存,SSR 节点无状态化部署,配合流式渲染优先输出首屏壳和关键内容。

# 打开 A 页面,发送了一些请求,这时切换的 B 页面,一般会做什么优化?

  1. 页面切换时,对 A 页面的在途请求做取消: AbortController (fetch)/ axios cancel token(旧)/ axios signal (新)/ 自研 request client 支持取消。
  • 可取消:列表分页、搜索联想、曝光上报、推荐流等,切页就停。
  • 不建议取消:支付、提交表单、关键埋点落库等(改为后台继续 + 结果可追踪)。
  1. 组件卸载后禁止回写 UI;给每次路由实例一个 requestScopeId (或 routeKey),A 页请求的响应只允许落到 A 页对应 scope,避免切到 B 后 A 的响应把全局 store 覆盖掉。

比如像属于A页面的弹窗还是展示就切到B页面,需禁止弹窗展示在B页面

  1. 去重与缓存复用(减少重复请求 + 提升切换体验);
  • 请求去重:同一资源短时间重复触发(A->B->A)时复用同一个 in-flight promise(dedupe),避免打爆后端。
  • 对 B 页面“可预期会用到”的数据做预取
  1. 用户体验优化
  • B 页切换时避免白屏/闪烁:骨架屏 + keepPreviousData (保留上一次数据)+ 渐进更新。
  • A 页返回(back)体验:决定是否 keep-alive (Vue)/ 页面缓存(React router cache)以减少重建与重复请求;同时要注意缓存页面的“过期刷新策略”。

# 前端加载超大图片(>=100M),如何实现秒开?

前端加载超大图片时,一般可以采取以下措施实现加速:图片压缩、图片分割、懒加载、预加载、CDN、HTTP2、WebP格式

100MB 超大图不能直接整图加载并解码,否则网络、解码、内存都会爆。真正可落地的方案是: 首屏预览图 + 分辨率金字塔 + 分块切片 + 按需加载 + 渐进渲染

优化目标:不是“1 秒下载完 100MB”,而是“1 秒内让用户看到可用画面,并且缩放/拖拽时继续补高清细节”。

工程上的完整方案:

预处理阶段:

  • 服务端把原图生成多套分辨率金字塔,比如 256x256 或 512x512;同时生成一张极小的 preview 图。
  • 把原图预处理成多层级瓦片(tile),类似地图方案,不同缩放级别对应不同分辨率,只加载当前视口需要的那几块。

首屏阶段:

  • 页面先展示 preview 图,占位并立即可见。
  • 同时根据当前容器尺寸和缩放级别,请求首屏需要的 tile。

交互阶段:

  • 用户拖拽时优先请求视口内 tile;用户缩放时先用低分辨率过渡,再补高分辨率。
  • 预取相邻区域 tile,减少拖动时空白感。

性能阶段:

  • 控制并发请求数,避免同时拉太多 tile;做 LRU 缓存,保留最近浏览区域;视口外 tile 及时释放,避免内存暴涨。
  • 解码和渲染要异步化:图片解码不要阻塞主线程,可以结合 createImageBitmap 、 OffscreenCanvas 、 Web Worker 。

典型场景:地图、医学影像、遥感图、设计稿预览

# 上线过程中后端接口有修复,如何保证线上不受影响?

这题本质考的是:后端接口在发布窗口内发生变更或修复时,前端怎么保证线上用户无感、业务不中断。

第一层:接口必须向后兼容

  • 后端修复时,尽量 只新增、不删除、不改语义 。
  • 老字段先保留,新字段并行输出,给前端留迁移窗口。
  • 如果确实有 breaking change,就走 API version ,比如 /v1 、 /v2 ,不能直接覆盖老协议。

第二层:灰度发布,不一次全量

  • 后端先灰度到小流量机器或部分用户。
  • 观察错误率、超时率、返回结构、核心业务指标,再逐步放量。
  • 出问题可以快速摘流或回滚,不影响全部用户。

第三层:前端要有容错和兜底

  • 前端解析接口时不能写得过于脆弱,要做 字段缺省兼容 、 默认值兜底 、 异常分支处理 。
  • 对非核心字段,缺失时不让页面白屏,而是降级展示。
  • 对关键接口失败,要有 fallback,比如缓存数据、骨架屏、错误提示、重试按钮。

第四层:前后端开关解耦

  • 新逻辑不要和新接口强绑定,最好加 feature flag 。
  • 后端接口修好了,先不开前端入口;或者前端代码已发,但功能默认关闭。
  • 这样后端有问题时,只关开关,不必紧急发版前端。

第五层:监控 + 快速回滚

  • 上线期间重点盯 接口成功率 、 4xx/5xx 、 超时率 、 页面白屏率 、 JS error 、 核心转化指标 。
  • 一旦发现异常,优先回滚后端版本或切旧接口,不要现场硬修。
  • 前端如果做了兼容层,后端回滚后也能继续跑,不至于一起挂。

一个更像实战的回答: 比如上线过程中后端把 status 字段语义修了,我不会让它直接替换老字段,而是要求后端先并存输出 oldStatus + status ,网关或 BFF 层做兼容转换,前端通过开关逐步切到新字段;同时后端走灰度发布,监控错误率和核心页面指标。如果发现问题,优先切回旧协议或回滚服务,而前端页面因为有默认值和降级逻辑,不会白屏或功能中断。

# 性能优化

# 浏览器行为与资源更新策略

不同用户操作触发的缓存行为不同:

  • 地址栏回车或点击链接,浏览器正常走强制缓存,命中缓存则完全不请求。
  • F5刷新或点击刷新按钮,浏览器会给请求头加上 Cache-Control: max-age=0,跳过强制缓存,直接走协商缓存。
  • Ctrl+F5强制刷新,浏览器加上 Cache-Control: no-cache,且不发送 If-Modified-Since 和 If-None-Match,强制服务器返回完整资源。
  • 代码中location.reload()呢?

html 文件应该用协商缓存或不缓存;带 hash 的 js 和 css 用强缓存;图片等不常变的资源也用强缓存。

Service Worker是上 HTTP 缓存更底层的缓存控制能力,它通过拦截fetch事件可以精细控制缓存策略,优先级高干 HTTP 缓存。比如可以缓存整个页面离线访问,或者实现 Stale-While-Revalidate 策略,即先返回缓存,后台异步更新。但注册 Service Worker 本身会延迟首屏加载,需要在性能和功能间权衡。对干普通静态资源缓存,用 HTTP 缓存已经足够。需要离线访问和更精细控制时才引入 Service Worker。

# 性能优化工程化流程

  1. 性能优化的第一步是“测量”,而不是“动手”

    使用正确的工具:

  • Chrome DevTools→ Performance 面板:录制加载过程,分析每个阶段耗时。
  • Lighthouse:快速评分,但不要迷信分数,要理解每一条建议背后的原理。
  • WebPageTest:多地域、多网络环境测试,模拟真实用户。
  • Performance API:在代码中埋点,获取真实的用户数据(RUM)。

    关键问题:在动手优化前,先回答:瓶颈在网络层?渲染层?还是计算层?

  1. 理解“关键渲染路径”,才能精准打击 关键渲染路径(Critical Rendering Path)是浏览器从接收 HTML 到首次渲染的全过程,分为 5 个步骤:
  • 构建 DOM 树:解析 HTML,遇到外部 CSS/JS 会阻塞吗?
  • 构建 CSSOM 树:CSS 是渲染阻塞资源,CSS 没下载解析完,页面不会渲染。
  • 构建渲染树:DOM+CSSOM= Render Tree。
  • 布局(Layout):计算每个节点的几何位置。
  • 绘制(Paint):填充像素到屏幕上。

优化策略:

  1. 减少关键资源数量:内联首屏 CSS,延迟加载非关键 CSS。JS 使用 async 或 defer 避免阻塞。

  2. 减少关键字节数:压缩、Tree Shaking、按需加载、图片格式优化(WebP/AVIF)

  3. 缩短关键路径长度:减少 HTTP 请求次数(合并请求、HTTP12 多路复用)、使用 CDN、预加载关键资源(<link rel="preload">)。

  4. 从用户视角出发的性能优化体系

网络层优化:

  • HTTP/2 多路复用:解决队头阻塞,减少连接数。
  • 预加载与预连接:<link rel="preconnect">提前建立连接,<link rel="prefetch">预加载下一页资源。
  • Service Worker+缓存策略:离线可用,二次加载秒开。

资源层优化:

  • 代码分割(Code Splitting):Webpack 的动态 import, React 的 lazy。
  • Tree Shaking:消除未引用的代码。
  • 图片优化:响应式图片(srcset),懶加载(loading="lazy"),占位符避免布局偏移。

渲染层优化:

  • 避免大型内联脚本:阻塞 DOM 构建。
  • 减少回流和重绘:使用 transform、opacity,读写 DOM 分离。
  • 骨架屏:提升感知性能,比 Loading 动画效果好 10 倍。

计算层优化:

  • web worker:将计算密集型任务放到后台线程,不阻塞主线程。
  • 异步计算:使用 Promise、async/await 等异步操作,避免阻塞主线程。
  • 长任务拆分:使用 requestIdleCallback 分片执行,避免阻塞 UI 渲染。

# 可视化

# 微前端

# 通信方案

# AI

上下文是耗材,得省着花

有个经验值:上下文用到七成左右,模型精度就开始往下掉;到八成五,容易开始胡编(也就是 hallucination);过了九成,输出基本不稳了。

对应的做法是:用到五成以内可以放开手;五到七成留点神;七到九成主动用 /compact 压一压;过了九成就别犹豫,/clear 重开。

# SDD 与 Harness

存量应用中,AI 编程必须从"氛围"走向"规范",必须有明确的验收标准。

AI 编程要从"个人技能"升级为"团队级工程能力",要从"氛围编程"进化为"规范驱动、工程治理"的研发范式。

SDD(Specification-Driven Development,规范驱动开发),SDD 的核心思想是:在 AI 写代码之前,必须先将人类模糊的想法转化为清晰、无歧义的结构化规范,让 AI 在可控的轨道上运行。

SDD 的核心思想是颠覆性的:规范不再是写给人类看的散文,而是结构化的、可被 AI Agent 精确理解和执行的"意图代码"。

SDD 的工作流包含四个阶段:

  1. 第一,Specify(定义规范)。 开发者与 AI 探讨,输出一份结构化规范,定义好用户故事、验收标准和系统约束。这是"原始需求"阶段。
  2. 第二,Plan(制定计划)。 AI 像编译器一样,将规范"编译"成详细的技术方案和任务拆解列表。这是"技术文档"阶段。
  3. 第三,Implement(执行落地)。 AI Agent 逐个执行任务列表,自动生成高质量代码。这是"软件开发"阶段。
  4. 第四,Validate(验证闭环)。 根据规范自动生成测试用例并执行,确保生成的代码与规范完全契合。这是"功能及代码规范测试"阶段。

SDD 解决的是"做什么"的问题,Harness 解决的就是"如何可控地做"的问题。

Harness 这个词很形象。想象一匹野马——AI 大模型拥有无穷的力量,但没有马具,你根本骑不上去,甚至可能被它甩下来。Harness Engineering 的核心,不是去改变马的基因(模型本身),而是为这匹野马设计一套精密的控制系统

一个成熟的 Harness 系统包含四个核心支柱:

  1. 第一,上下文工程。 不再是简单的 RAG(检索增强生成),而是结构化的信息投喂。维护一个"单一事实来源",让 Agent 知道项目的目录结构、当前的执行计划以及哪些文档是最新的。
  2. 第二,架构约束。 这是 Harness 最硬核的部分。通过物理手段强制 AI 遵守规则。例如,规定 UI 层的代码绝对禁止直接访问数据库层。如果 AI 试图违反架构分层,代码甚至无法通过语法检查,从而在提交前就被拦截。
  3. 第三,反馈回路与熵管理。 AI 一定会犯错,关键在于如何发现并修正。建立自动化的测试沙箱:Agent 写完代码 → 自动运行测试 → 失败 → 读取错误日志 → 自我修正并重试。更重要的是,将人类修复错误的经验固化为新的规则,确保 AI 永远不会犯同样的错误两次。
  4. 第四,人类监督。 人类从"写代码的人"变成了"审核员"和"环境设计师"。职责是定义复杂的业务边界,处理那 5% AI 无法判断的模糊逻辑,以及优化 Harness 本身的规则。

从提示词工程到上下文工程,再到 Harness Engineering,这是一个范式转移:从"怎么跟 AI 说话",到"AI 应该看到什么",再到"AI 如何在受控环境中运行"。

# SDD实践流程

  1. 设计知识库
  • 项目层知识包括项目的概述、目录结构、架构设计、技术选型等。这些是 AI 理解项目上下文的基础。根据按需加载的思想,我们维护一个 顶层README.md 文件,作为 Qoder 的"单一事实来源"——如果某个信息不在文档里,对 Qoder 来说它就不存在。
  • 技术层知识包括通用的技术知识、编码规范、中间件、三方库文档、最佳实践、常见问题解决方案等。这些知识可以跨项目复用,是团队技术沉淀的体现。
  • 资产层知识包括可复用的代码片段、组件、模板、历史需求 PRD、技术方案、归档的测试 Case等。这些是团队多年积累的"砖块",AI 可以直接使用它们来构建新的功能。

在实际项目中,文档按照知识库三层分层结构设计目录,然后通过一个 README.md 文档来进行索引,按需加载。这种分层索引机制既保证了知识的结构化组织,又实现了按需加载的灵活性,让 AI 智能体能够高效获取所需知识,避免上下文过载。

  1. 处理需求 PRD

有了知识库,下一步是处理需求 PRD。可以使用 Qoder 的 Quest Spec 模式来生成规范化的 design.md 文档。

Spec模式 和 HITL(Human-in-the-Loop,人工干预)

为什么要 HITL?

因为需求文档中有很多"隐性知识"——那些产品经理认为理所当然、但实际上需要澄清的信息。比如"用户登录"这个简单的功能,背后可能有:支持哪些登录方式?是否需要记住登录状态?密码强度有什么要求?登录失败怎么处理?等等。

通过 Spec 模式,AI 会主动提问,引导开发者澄清这些隐性知识,逐步补齐完整的 Spec。Spec 中会包含:

  • 数据模型:涉及哪些数据表,字段定义是什么,关系是什么。
  • 接口规范:API 的输入输出、错误码、幂等性要求等。
  • 最重要的是:验收标准。这是 SDD 的核心。验收标准必须是可测试的、无歧义的。比如"用户登录成功后跳转到首页"是一个模糊的描述,而"用户登录成功后,3 秒内跳转到首页,并在首页显示用户昵称"就是一个可测试的验收标准。

有了完整的 Spec,AI 就有了明确的"施工图纸",不再是"氛围编程"。

  1. 专家团执行任务

Spec 准备好后,进入执行阶段。可以使用 Qoder 的专家团模式(Experts Mode)。

专家团模式的核心思想是:不同的任务由不同角色的 Agent 来完成。就像一个真实的开发团队,有前端工程师、后端工程师、测试工程师、架构师等角色。

AI 会根据 Spec 生成执行计划,把大型任务拆解成可管理的小任务。每个小任务都有明确的输入、输出和验收标准。然后,根据任务类型,分配给不同角色的 Agent。

此外,要重点强调下用户角色的转变:用户也是协调链路的一部分。你可以在专家团运行时随时介入,Experts Leader 在下一轮循环中处理,调整任务方向或取消不再需要的任务。你的角色变了:和 Experts Leader 澄清意图、对齐方向、审核计划、验收结果,更像带一个有经验的研发小组。

  1. 任务部署

代码生成和测试通过后,进入部署阶段。可通过提供的 MCP(Model Context Protocol)工具,将构建产物交付给运维 Agent 进行部署。

通过 MCP,运维 Agent 可以:触发 CI/CD 流水线;执行部署脚本;查询部署状态;处理部署异常。这样,就打通了从需求到部署的全链路。开发者不再需要手动操作各种工具,只需要在 AI 的引导下完成关键决策。

# Skill 最佳实践?

  • SKILL.md 的正文应该是"路由器"而非"知识仓库"。SKILL.md 只保留路由表和全局规则,业务细节下沉到模块文件。

应控制在 500行 以内,500行文本等于2000~3000 token,是单个 Skill 激活后比较合理的上下文开销。

  • 将确定性计算逻辑封装为脚本,由 Agent 调用执行而非自行推导。脚本是 Skill 突破 LLM 能力边界的利器。

配置文件读写、环境检测、日志采集、复杂计算

知识分层策略:

  • 当一个文件超过 300 行,或某个 Step 的规则超过 100 行时,就是拆分信号。文件太长不光浪费token,还会让 Agent 的注意力在大段文本中迷失。
  • 越频繁用到的知识,离入口越近;越偶尔查阅的知识,越往深处放。这样 Agent 每次只加载当前步骤真正需要的内容,不会把上下文窗口塞满无关信息。
trade-ab-skill/
├── SKILL.md             ← 意图路由表、全局安全红线(每次激活必读)
├── modules/creator/creator.md           ← 创建流程 Step 编排、scenarioId 对照表(进入创建模块才读)
├── modules/creator/collect-phase.md     ← 参数填充的 11 项执行清单(仅 Step 2 才读)
├── modules/creator/validate-phase.md    ← 校验规则(仅 Step 3 才读)
├── modules/creator/tools.md             ← MCP 工具接口列表(调接口时按需查阅)
└── modules/creator/safety.md            ← 安全约束详细规则(validate 阶段按需加载)

Tool 的权限设计与工具隔离:

当 Skill 涉及多个模块、调用多个 MCP 接口时,必须实施模块级的工具隔离:

  1. 白名单制:每个模块的 tools.md 明确列出可用接口,白名单外一律禁止;
  2. 危险接口显式禁用:万能工具(如直接 HTTP 调用)全局禁止;
  3. 工具隔离:不同模块使用不同的接口集合,防止误调用。

微前端 node.js ssr 监控 taro跨端 组件库 性能优化

上次更新: 9/11/2026, 7:47:52 PM
最近更新
01
interview202601
09-06
02
20-尾声正文
09-01
03
19-第十五章正文
09-01
更多文章>