Me

表现

  1. 乐观积极

  2. 主动沟通

  3. 逻辑顺畅

  4. 上进有责任心

  5. 有主张、做事果断

  6. 业务能力

  7. 思考能力

  8. 学习能力

  9. 无上限的付出

  10. 目标是什么

    • 业务上专家,技术上大牛
  11. 近阶段的目标

    • 融入团队,提高团队,能打的一个团队
  12. 长期目标

    • 做出一个界内优秀案例
  13. 方式方法

    • 整合现有问题,结合自身经验改进
    • 积极投入到业务建设
    • 技术上攻坚,带领团队
    • 借鉴其他部门、其他公司
  14. 多赞美公司、多赞美面试官

自我介绍

面试官你好,我叫 xx,从事前端相关的工作至今约 9 年多。

16 年 8 月,第一家公司,技术 100 多人,在这家公司主要 红酒商城系统、旅游系统、企业应用、政务系统等,主要用到 react、vue、小程序 xxxx 技术,前端 6 人,前期主要承担主力开发人员,后期一些项目的主要负责人,同时开始带人开发。获得 2017 年团队最佳员工奖 1/40。

18 年 4 月,第二家公司,技术 300 多人,APP 端内嵌的 h5 项目,小程序,客服系统、大数据系统、冬奥会系统、车联网系统等十几个项目,主要用到 xxx 技术,前端 20 人,前期主要承担主力开发人员,后期开始带小伙伴一起做项目。

20 年 11 月,第三家公司,在 xxx 技术中台,部门 100 个人,云服务产品(容器、日志、网关、mlops、运维平台),大数据产品(日志、数据查询、服务、质量),自研低代码问卷平台等。自研信息,埋点等,主要用到 xxx 技术。前期带几个外包一起开发,后期主力开发人员。2022 年度团队协作奖。

24 年 3 月,第四家公司, xx科技,主要负责 前端 项目(coco ai, es 后台管理平台,cloud 管理平台,前端公共组件库,官网等),主要用到 react、tauri 技术,主要负责项目的需求分析、项目的设计、项目的开发、项目的测试、项目的上线。24年度最佳新人,25 年最具创新奖。25 参加 gitCode 全国线上演讲。

总得来说,这几年做的各类项目比较多,同时也注重工程化建设,提高开发效率等,帮助团队,喜欢做团队中难度高的项目,后期也开始关注业务,关注用户体验,优化项目。偶尔也会参与一些开源项目。

主要技术栈是 React/Vue/Node/小程序/移动端/桌面端/ 等。

最新关注 Agent

未来适配岗位的 3 类人: 1️⃣会用 AI:驾驭 AI 写代码、改代码,做审核和优化,人机协作 2️⃣懂业务 + 懂架构:能拆解需求、设计系统、解决复杂问题 3️⃣有判断力:懂安全、懂落地、懂成本,创造商业价值

简单说:别做 “码字工人”,要做解决问题的人、指挥 AI 的人。

Why You?

  1. 技术广度与深度的结合:
    • 不仅精通 Vue/React 业务开发,更深入 Rust/Tauri 系统级开发,是市场上稀缺的 "前端 + 桌面端 + AI" 复合型人才。
  2. 解决复杂工程问题的能力:
    • 从 Monorepo 治理到 微前端 落地,再到 WebGL 性能优化,我有处理大规模、高复杂度前端架构的实战经验,而不仅仅是写页面。
  3. AI Native 产品思维:
    • 深刻理解 AI 应用的交互范式(流式、引用、工具调用),能从产品角度提出技术解决方案(如可视化的思维链),弥补大模型的体验缺陷。
  4. 结果导向与团队赋能:
    • 善于造轮子(脚手架、组件库),也善于用数据说话(性能提升 40%、效率提升 30%),具备带领团队攻坚的能力。

项目

1. 微前端架构 (Micro-Frontends)

背景与痛点:

  • 多项目合一:公司内部有十几个独立运行的系统(SaaS、数据中台、容器、运维平台等),用户需要在不同系统间频繁跳转,体验割裂。
  • 技术栈混乱:遗留项目有 Vue2、React,新项目想用 Vue3/Vite,难以统一升级。
  • 公共能力复用难:登录、菜单、权限、全局样式等公共模块在每个项目中重复开发,维护成本高。

我的解决方案演进:

阶段一:基于 Qiankun 的微前端落地 (上家公司)

选型理由: 当时(2020-2022)qiankun 是最成熟的方案,基于 single-spa 封装,社区活跃,解决了 single-spa 的痛点(样式隔离、JS 沙箱、HTML Entry)。

核心原理:

  1. HTML Entry:通过 import-html-entry 解析子应用的 HTML,提取 Script 和 Style,避免了 JS Entry 的硬编码问题。
  2. JS 沙箱 (Sandbox):
    • ProxySandbox:在支持 ES6 Proxy 的浏览器中,代理 window 对象,记录子应用的修改,卸载时还原。
    • SnapshotSandbox:在不支持 Proxy 的低版本浏览器中,通过快照 diff 实现(性能较差)。
  3. 样式隔离:
    • Strict Style Isolation:基于 Shadow DOM(开启后会有弹窗挂载 body 丢失样式等兼容性问题,我们没开)。
    • Scoped CSS:实验性功能,类似 Vue scoped,给 CSS 选择器加前缀(我们主要靠 BEM 命名规范 + CSS Modules 解决冲突)。

遇到的坑与解决:

  1. 全局事件不生效:子应用直接 window.addEventListener 有时会失效。
    • 解决:Qiankun 的沙箱会劫持事件监听,必须确保在卸载生命周期中正确 removeEventListener。
  2. 静态资源 404:子应用的 CSS 中引用的字体/图片路径,在主应用中加载时会变成相对主应用的路径。
    • 解决:在 Webpack 构建时,将 publicPath 设置为子应用的完整 URL;或者使用 url-loader 将小资源转 base64。
  3. 循环依赖部署问题:主应用部署在 K8s 容器,容器平台前端又依赖主应用(套娃)。
    • 解决:将主应用在阿里云 OSS 和 K8s 各部署一份,通过网关路由规则,切分流量避免死循环。
  4. Q: 微前端中,子应用之间如何通信? * A: 我们主要用了三种方式:
    1. URL 参数:最简单,适合带 ID 跳转。
    2. EventBus:发布订阅模式,适合松耦合通知(如“刷新列表”)。
    3. 全局状态 (Props/Global Store):主应用下发 UserInfo、Token 等共享数据。在 Wujie 中,还可以通过 props 直接注入方法。

阶段二:基于 无界 (Wujie) 的极速方案 (当前公司)

选型理由 (Why Switch?): 在开发 AI Agent 和新中台时,我们需要极致的加载速度和更好的隔离性(特别是 Vite 项目)。Qiankun 对 Vite 支持不友好(需关闭沙箱或使用插件),且 JS 沙箱有一定的性能开销。 无界 (Wujie) 采用了 Web Components + iframe 的架构,完美解决了这些问题。

核心原理 (WebComponent + iframe):

  1. JS 沙箱 (极致隔离):直接利用 iframe 天然的 JS 隔离能力。子应用的 JS 运行在 iframe 中,完全独立,不污染主应用 window。
  2. 渲染 (Web Components):虽然 JS 在 iframe 里跑,但页面是渲染在主应用的 Web Component (Shadow DOM) 里的。
    • 优势:既有 iframe 的强隔离,又没有 iframe 的 UI 体验问题(弹窗遮罩无法覆盖主应用、页面刷新状态丢失等)。
  3. 预加载与保活:无界支持预加载和 keep-alive(类似 Vue 的 keep-alive),子应用切换后状态不丢失,且秒开。

对比总结:

特性Qiankun (上家公司)无界 Wujie (当前公司)
技术栈基于 single-spa基于 Web Components + iframe
JS 沙箱Proxy / 快照 (模拟沙箱)iframe (原生沙箱,0成本)
样式隔离弱 (靠约定或 ShadowDOM)强 (Shadow DOM)
Vite 支持差 (需额外配置)完美 (原生支持)
加载速度一般 (需解析 HTML/JS)极快 (支持预加载)
应用场景传统 Webpack 老项目迁移新项目、Vite 项目、对隔离要求高

我的贡献:

  1. 封装了通用的 MicroApp 组件,统一了 Qiankun 和 Wujie 的接入方式,让业务方无感知。
  2. 解决了子应用通信问题:基于 CustomEvent 封装了一套全局事件总线 (EventBus),实现了主子应用、子子应用间的数据同步。
  3. 针对 AI Agent 场景,利用无界的 预加载 能力,提前加载好大模型对话组件,实现了用户点击即用的“秒开”体验。

2. 埋点

见 ./frontend/log_sdk.md 内容

数据埋点 SDK 的设计

设计一个优秀的前端 SDK(如数据埋点 SDK、性能监控 SDK、开放平台 API 封装 SDK 等)不仅考验代码能力,更考验架构思维。以下是面试中常被问到的核心维度与解答:

1. SDK 设计的核心原则是什么?

  • 易用性(User-Friendly):接入成本极低,最好是 "Zero-Config"(零配置)或者只需传入一个 Token 即可初始化。API 命名需语义化,符合开发者直觉。
  • 稳定性与安全性(Stability & Security):SDK 代码绝不能导致宿主应用崩溃。所有的核心流程都应该有 try...catch 包裹,绝不能污染全局变量(避免变量冲突)。
  • 轻量化(Lightweight):体积要尽可能小。不要引入庞大的第三方库(如 lodash/axios),尽量使用原生 JavaScript(如 fetch/XHR)实现。按需加载和 Tree-shaking 支持。
  • 扩展性(Extensibility):支持插件化机制(Plugin System),允许开发者自定义生命周期钩子(Hooks)拦截和修改数据。

2. SDK 的整体架构如何划分?

一个成熟的 SDK 通常分为以下几个模块:

  1. 入口模块 (Core/Entry):负责 SDK 的初始化、配置合并、插件挂载、暴露全局 API。
  2. 环境处理模块 (Environment):判断当前运行环境(浏览器/Node.js/小程序),抹平环境差异。
  3. 数据采集模块 (Collector):例如拦截 XHR/Fetch,监听 Error/UnhandledRejection,监听路由变化,或是监听 DOM 点击事件(无痕埋点)。
  4. 数据处理模块 (Processor/Formatter):对采集到的数据进行格式化、过滤(如去除敏感信息)、添加公共参数(如 UUID、设备信息、时间戳)。
  5. 上报/通信模块 (Sender/Transport):负责将数据发送给服务端。需要处理网络异常、重试机制、数据批量上报策略。

3. 如何保证 SDK 不污染全局环境?

  • 使用闭包或立即执行函数 (IIFE) 封装代码,避免内部变量泄露。
  • 使用 ES Modules (ESM) 或 CommonJS 进行模块化开发,打包时通过 Rollup/Webpack 输出 UMD 或 ESM 格式。
  • 唯一命名空间:如果必须挂载到 window 上,使用特殊且唯一的名字,如 window.__MyMonitorSDK__,而不是通用的 window.utils。

4. 数据上报模块(Sender)如何设计?

这是监控/埋点 SDK 最关键的部分,需要考虑性能和数据丢失问题:

  • 上报方式选择:
    • navigator.sendBeacon(url, data):首选方案。它是异步非阻塞的,即使页面卸载(Unload)也能保证数据成功发送,不影响下一个页面的加载。
    • Image Beacon(new Image().src = url + '?data=xxx'):兼容性极好,不会跨域拦截,通常作为降级方案(但只能用 GET 请求,有长度限制)。
    • Fetch/XHR:常用于数据量较大或需要接收服务端返回结果的场景。
  • 上报策略(降本增效):
    • 批量上报:将数据存入内存队列,当队列满(如 10条)或达到定时器时间(如 5秒)时再一次性合并发送。
    • 空闲上报:利用 requestIdleCallback 在浏览器主线程空闲时处理数据并上报,不抢占用户交互资源。
    • 本地缓存(容灾):遇到断网或发送失败时,将数据存入 localStorage 或 IndexedDB,待网络恢复后重发。

5. SDK 如何实现插件化(Plugin System)?

为了保持核心(Core)的轻量,将不同功能拆分成独立插件。 借鉴类似 Vue/Webpack 的插件机制:

  • 定义生命周期 Hooks,如 beforeInit, beforeSend, afterSend。
  • 提供 use(plugin) 方法注册插件。
class SDKCore {
  constructor() {
    this.plugins = [];
  }
  use(plugin) {
    plugin.install(this); // 将当前 SDK 实例传入插件
    this.plugins.push(plugin);
  }
  // 在关键节点触发钩子
  notifyHooks(hookName, data) {
    this.plugins.forEach(plugin => {
      if (typeof plugin[hookName] === 'function') {
        plugin[hookName](data);
      }
    });
  }
}

6. 如何保证 SDK 的代码质量?

  • TypeScript:使用 TS 编写,提供完善的 .d.ts 类型声明文件,让使用者在 IDE 中有极好的代码提示体验。
  • 单元测试:使用 Jest/Vitest 进行核心逻辑(如队列合并、配置解析)的单元测试。
  • 打包构建:使用 Rollup 进行打包,因为它相比 Webpack 打包出来的代码更干净、冗余代码更少,非常适合构建 Library/SDK。

7. 遇到过哪些 SDK 兼容性问题,如何解决?

  • 跨端兼容:一套代码想跑在浏览器、Node.js 和小程序中。解决方案是在构建时(或运行时注入适配器),针对不同环境提供不同的 Transport 层(如浏览器用 XHR,小程序用 wx.request,Node 用 http 模块)。
  • API 兼容:某些老浏览器不支持 sendBeacon 或 Promise。SDK 内部应做降级处理(如退化为 Image 上报),并尽量避免直接引入 polyfill 以免增加体积,让宿主环境自己决定是否引入 polyfill。

3. 站内信

见 ./frontend/mail.md 内容

4. 图表大盘

图表库的选择

主流的 web 图表库有:ECharts、Highcharts、D3.js、antv(G2,G6,F2)...

ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Safari等),底层依赖矢量图形库 ZRender,提供直观,交互丰富,可高度个性化定制的数据可视化图表。

ECharts 提供了常规的折线图、柱状图、散点图、饼图、K线图,用于统计的盒形图,用于地理数据可视化的地图、热力图、线图,用于关系数据可视化的关系图、treemap、旭日图,多维数据可视化的平行坐标,还有用于 BI 的漏斗图,仪表盘,并且支持图与图之间的混搭。

Highcharts 是一个用纯 JavaScript 编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,HighCharts 支持的图表类型有曲线图、区域图、柱状图、饼状图、散状点图和综合图表。但非商业免费,商业需授权。

D3 的全称是(Data-Driven Documents)。D3.js是一个 JavaScript 库(是一个被数据驱动的文档),用于在浏览器中创建交互式可视化。

D3 js库允许我们在数据集的上下文中操作网页的元素。这些元素可以是 HTML,SVG,或画布元素,可以根据数据集的内容进行引入,删除或编辑.它是一个用于操作 DOM 对象的库. D3.js 可以成为数据探索的宝贵帮助,它可以让您控制数据的表示,并允许您添加交互性。

@antv/g2 是一套基于可视化编码的图形语法,以数据驱动,具有高度的易用性和扩展性,用户无需关注各种繁琐的实现细节,一条语句即可构建出各种各样的可交互的统计图表。

@antv/g2 是一个图形语法, 通过数据之间的关系, 来生成一张图. 所以 G2 的定制化确实更加强大, 但是我们做业务的, 一般就是需要一个特定的图然后填充数据, 和将数据和数据之间的关系描述出来再实现图表有点出入,还有 G2 的文档一般,上手难度。

其中最后的选择落在 echarts 和 G2,echart 使用就是一些配置项,G2 是图形语法,通过数据之间关系,来生成一张图,虽说这样 G2 定制化更加强大。但是我们的业务,一般就是需要一个特定的图然后再填充数据,还能支持配置,无疑 Echarts 更符合我们的业务场景。所以最终图表库选择 echarts 。

5. 智能检索

6. 工程规范、项目模板

7. 低代码

  • 背景 内部没有、外部暴漏公司用户信息、文档无法当 url 用

  • 技术 Function("use strict";const formData = ${JSON.stringify(formData)};return (${string}))()

  • 技术 动态关联

  • 撤销、重做(快照、限制保存快照的容量,超出容量直接删除前面最早的快照即可)

  • 撤销、重做(两个栈记录每次操作记录,维护的难度也会越来越高)

  • 成果 生成 url、10 分钟/人、4 期 7 个产品

  • 见掘金文章地址open in new window

8. 性能优化

  • 首次内容绘制 (First Contentful Paint,FCP) 1.8s 3s
  • 最大内容绘制 (Largest Contentful Paint,LCP) 2.5s 4s
  • 首次输入延迟 (First Input Delay ,FID) 100ms 300ms
  • 交互到绘制延迟(Interaction to Next Paint,INP)200ms 500ms
  • 累积布局偏移 (Cumulative Layout Shift,CLS) 0.1 0.25
  • 第一字节时间 (Time to First Byte,TTFB) 800ms 1800ms
  • 预取回 Prefetch <link rel="prefetch"
  • 预加载 Preload <link rel="preload"
  • 预连接 Preconnect <link rel="preconnect"
  • DNS预取回 DNS-Prefetch <link rel="dns-prefetch"
  • 加载指标:秒开率
  • 稳定性指标:资源错误,JS报错,Crash,内存堆栈,接口报错等
  • 操作体验指标:响应延迟,卡顿,滚动流畅性,TTI(可交互时间) FID(用户首次和页面交互到页面响应交互的时间)
  • 加载链路的优化:从访问url到页面呈现,整个加载渲染链路可以做优化的思路
  • CRP 关键渲染路径
  • 减少请求数量、减少请求体积、加载顺序、资源合并压缩、GZIP
  • 元素背景图使用雪碧图模式,是前端基本优化手段,可以显著降低请求次数。
  • 缓存(Service Worke、HttpCache)
  • DNS 解析
  • 图片处理优化(选择合适的图片、压缩、svg、base64、异步加载)
  • url-》页面
  • url 解析
  • 缓存(强缓存 Expires / Cache-Control、协商缓存 Last-Modified / ETag、数据缓存)
  • DNS解析(20~120毫秒、dns-prefetch、CDN 加速)
  • TCP三次握手(SYN、AYN+ACK、ACK)
  • 数据传输
  • TCP四次挥手(FIN、ACK、ACK+FIN、ACK)
  • 页面渲染(async、defer)
  • vue
  • 路由懒加载
  • 按需引入
  • KeepAlive
  • react
    • 用 memo、PureComponent 避免子组件重复渲染
    • 用 useMemo、useCallback 缓存计算和函数
    • 列表用 唯一 key,长列表用 虚拟滚动
    • 懒加载路由与组件,代码分割
    • 拆分状态与 Context,减少渲染范围
    • 避免匿名函数、内联对象作为 props

高并发场景

  • 春晚活动页
  • 首屏资源主要包括:HTML文档、JavaScript、CSS以及样式图片。
  • 由于这是单页面应用,我们可以通过常规技术将JS和CSS进行打包。
  • 对于样式图片,我们可以通过按需加载的方式,显著减小首屏资源体积。
  • 通过拆分优化,首屏的样式图片体积减少约41%。
  • 再加上 CDN 降质和 WebP 参数的优化,样式图片的体积可以降低到 178KB。
  • 同时,我们将需要单独加载的击鼓游戏精灵动画图从首屏加载清单中剥离,使得首屏样式图片的加载次数从2次减少到1次。
  • 这样一来,用户在打开页面时,所需的请求次数和资源体积都得到了显著降低,进而提高了用户体验。
  • 设计团队将3D动画转化为精灵图,并将不变部分(如鼓架)单独抽离。
  • 精灵图仅包含运动部分(如鼓面敲击动画),有效降低资源消耗。
  • 通过抽帧方式将击鼓精灵图从24帧降至4帧,大小从1236KB降至265KB。
  • 结合降质参数和WebP格式,最终大小仅为78KB,下降了93%。
  • 此外,我们将主光效换成放大一倍的一倍图,并通过CSS属性scale实现放大,进一步节省资源。
  • 流量消峰,页面随机加载1-3秒 loading 后跳转到活动页面
  • 流量消峰,游戏时长次数随机,完成要求随机
  • 选择了localStorage作为优化方案。它具有较长的生命周期和较大的储存空间(2.5M-4M),能满足业务需求。
  • 采用localStorage缓存数据,不仅可以简化调用链路、降低风险和节约成本,
  • 还能直接从本地读取券的领取状态,避免网络延迟导致的响应时间过长,提升用户体验。
  • 在静态资源优化方面,团队通过首屏资源拆分、帧动画方案替代3D模型、动态雪碧图和WebP格式优化等技术手段,显著降低了资源消耗和请求次数。
  • 在降低服务器成本及风险方面,选择localStorage作为非常规优化方案,提升用户体验。在容错方面,流量削峰和降级处理,确保系统稳定运行。
  • 在工程化方面,统一处理通用解决方案、提供拟真的MOCK环境和编写稳定高效的发布脚本,降低开发难度,确保每个环境稳定部署。

BFF

  • 透传、转发
  • 业务逻辑串联
  • 数据聚合
  • 服务端渲染

工程化、模块化

  • 工具化:以针对各自业务场景开发脚手架为主,内置常用的前端组件库,提供代码格式检查、埋点及监控等插件,提升项目初始化的效率。

  • 规范化:面向完成需求的整个研发流程,梳理需求管理、视觉交互设计、评审、开发、联调、测试验收、上线部署和质量监控等相关的规范,进一步建设工具来约束研发过程中的不确定性。

  • 平台化:将支撑研发的有关工具和系统聚合起来,通过套件和插件的设计模式,实现对不同场景的支撑,支持在线初始化项目,横向打通研发的整体链路。

  • 体系化:紧跟前沿技术,集成低代码、在线IDE、代码智能生成或推荐等能力,建设需求、设计、研发、运营一体化的云开发平台。

  • 原始模块:一个函数即可称为一个模块。这个是最常见的,最简单的模块。

  • AMD 是一种异步模块加载规范,专为浏览器端设计,浏览器并不支持 AMD 模块,在浏览器端,需要借助 RequireJS 才能加载 AMD 模块

  • CommonJS 是一种同步模块加载规范,目前主要用于 Node.js 环境中。

  • UMD 是一种通用模块加载规范,UMD 规范是对不同模块规范的简单整合。

  • ES Module 是 ES6 带来的原生系统。目前部分浏览器已经支持直接使用,而不兼容的浏览器可以通过构建工具来使用。

webpack

  • JS 模块打包工具

    • 通过分析模块之间的依赖,最终将所有模块打包成一份或者多份代码包 (bundler),供 HTML 直接引用
    • 打包功能 和一套 文件处理机制,然后通过生态中的各种 Loader 和 Plugin 对代码进行预编译和打包
  • Entry: 入口文件,Webpack 会从该文件开始进行分析与编译;

  • Output: 出口路径,打包后创建 bundler 的文件路径以及文件名;

  • Module: 模块,在 Webpack 中任何文件都可以作为一个模块,会根据配置的不同的 Loader 进行加载和打包;

  • Chunk: 代码块,可以根据配置,将所有模块代码合并成一个或多个代码块,以便按需加载,提高性能;

  • Loader: 模块加载器,进行各种文件类型的加载与转换;

  • Plugin: 拓展插件,可以通过 Webpack 相应的事件钩子,介入到打包过程中的任意环节,从而对代码按需修改;

工作流程 (加载 - 编译 - 输出)

  1. 读取配置文件,按命令 初始化 配置参数,创建 Compiler 对象;
  2. 调用插件的 apply 方法 挂载插件 监听,然后从入口文件开始执行编译;
  3. 按文件类型,调用相应的 Loader 对模块进行 编译,并在合适的时机点触发对应的事件,调用 Plugin 执行,最后再根据模块 依赖查找 到所依赖的模块,递归执行第三步;
  4. 将编译后的所有代码包装成一个个代码块 (Chuck), 并按依赖和配置确定 输出内容。这个步骤,仍然可以通过 Plugin 进行文件的修改;
  5. 最后,根据 Output 把文件内容一一写入到指定的文件夹中,完成整个过程;
  • 模块机制: webpack 自己实现了一套模拟模块的机制,将其包裹于业务代码的外部,从而提供了一套模块机制;
  • 文件编译: webpack 规定了一套编译规则,通过 Loader 和 Plugin,以管道的形式对文件字符串进行处理;

Loader

  • Webpack 其实是只能识别 js 模块,Loader 不同格式文件转换器,对 Webpack 传入的字符串进行按需修改
  • 将代码进行分析,构建 AST (抽象语法树), 遍历进行定向的修改后,再重新生成新的代码字符串

*** Babel-loader 会执行以下步骤: ***

  1. babylon 将 ES6/ES7 代码解析成 AST
  2. babel-traverse 对 AST 进行遍历转译,得到新的 AST
  3. 新 AST 通过 babel-generator 转换成 ES5

Loader 特性:

  • 链式传递,按照配置时相反的顺序链式执行;
  • 基于 Node 环境,拥有 较高权限,比如文件的增删查改;
  • 可同步也可异步;

编写原则:

  • 单一原则: 每个 Loader 只做一件事;
  • 链式调用: Webpack 会按顺序链式调用每个 Loader;
  • 统一原则: 遵循 Webpack 制定的设计规则和结构,输入与输出均为字符串,各个 Loader 完全独立,即插即用;

Plugin

见网页

vite

  • esbuild(10~100 倍)(go 直接转机器码、go 多线程共享内存、多核 cpu、零造轮子、复用 AST 节点)

    • 预构建依赖
    • go 直接转机器码,而非 js 先解析字节码再转机器码,js 解释性语言,go 编译性语言
    • go 多线程共享内存、多核 cpu 运行打包算法
    • 零造轮子
    • 复用 AST 节点,高效的内存利用
    • 在资源打包这种 CPU 密集场景下,Go 性能更优。一般来说,JS 的操作是毫秒级,而 Go 则是纳秒级。
    • js:解释运行、parse、解释运行、link、解释运行、generation
    • go:parse、link、generation
    • Go 在线程之间共享内存,而 js 必须在线程之间序列化数据。
    • Go 和 JavaScript 都有并行的垃圾收集器,Go 的堆在所有线程之间共享,而每个 JS 线程中都有一个单独的堆。
  • rollup

  • rolldown 3.8号开源,基于 rust 的 js 打包器,为 vite 设计,兼容 rollup api 和插件体系,贴近 esbulid 设计理念

Rust

vivo 蓝河操作系统采用 Rust 编写「系统框架」—— 从源头避免了内存使用不当引起的安全漏洞

  • 高性能 内存利用率极高、没有运行时和垃圾回收
  • 可靠性 丰富的类型系统和所有权模型保证了内存安全和线程安全
  • 生产力 出色的文档、友好的编译器和清晰的错误提示信息, 还集成了一流的工具 —— 包管理器和构建工具, 智能地自动补全和类型检验的多编辑器支持, 以及自动格式化代码等等

Rust 语言可以用于开发:

  • 传统命令行程序 - 直接生成目标可执行程序,不需要任何解释程序。
  • Web 应用 - 被编译成 WebAssembly,WebAssembly 是一种 JS 的高效替代品。
    • WebAssembly,是通过虚拟机的方式,可以在服务端、客户端如浏览器等环境执行的二进制程序。他有速度快、效率高、可移植的特点。
    • 对我们 Web 前端工程最大的好处就是可以在浏览器端使用二进制程序处理一些计算量大的处理,使用他比 javascript 快的特点优化性能。
  • 网络服务器 - 用极低的资源消耗做到安全高效,且具备很强的大规模并发处理能力,十分适合开发普通或极端的服务器程序。
  • 嵌入式设备 - 同时具有 JS 一般的高效开发语法和 C 语言的执行效率,支持底层平台的开发。

前端打包工具对比

四款前端主流的打包工具:grunt , gulp,webpack, rollup,以发布时间为顺序。

Grunt:

最老牌的打包工具,它运用配置的思想来写打包脚本,一切皆配置,所以会出现比较多的配置项,诸如option,src,dest等等。而且不同的插件可能会有自己扩展字段,认知成本高,运用的时候需要明白各种插件的配置规则。

MPA,老牌打包工具,基于文件为媒介(运行慢,零散的脚本文件一当多起来就受到影响

Gulp:

用代码方式来写打包脚本,并且代码采用流式的写法,只抽象出了gulp.src, gulp.pipe, gulp.dest, gulp.watch 接口,运用相当简单。更易于学习和使用,使用gulp的代码量能比grunt少一半左右。

MPA,易学,基于 nodejs 的 steam 流打包

webpack:

是模块化管理工具和打包工具。通过 loader 的转换,任何形式的资源都可以视作模块,比如 Commonjs 模块、AMD 模块、ES6 模块、css、图片等。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。它定位是模块打包器,而 Gulp/Grunt 属于构建工具。Webpack 可以代替 Gulp/Grunt 的一些功能,但不是一个职能的工具,可以配合使用。

SPA,目前最强大的打包工具,但是过于臃肿,如何单纯打包js不推荐

Rollup:

下一代 ES6 模块化工具,最大的亮点是利用 ES6 模块设计,利用 tree-shaking生成更简洁、更简单的代码。一般而言,对于应用使用 Webpack,对于类库使用 Rollup;需要代码拆分(Code Splitting),或者很多静态资源需要处理,再或者构建的项目需要引入很多 Commonjs 模块的依赖时,使用 webpack。代码库是基于 ES6 模块,而且希望代码能够被其他人直接使用,使用 Rollup。

MPA,tree-shaking特性(针对es6,按需打包,多余的不要,目前(2018,vuex,react主流使用)

设计模式

在前端和 Node.js/Nest.js 开发中,设计模式不仅是理论,更是解决实际工程问题的利器。以下是常用的设计模式及其实际应用场景:

1. 前端常用设计模式

  • 单例模式 (Singleton Pattern)
    • 概念:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
    • 前端举例:
      • 全局状态管理:Vuex / Pinia / Redux 的 Store 实例,整个应用中全局唯一。
      • 全局 UI 组件:全局唯一的 Loading 遮罩层、Message 消息提示框、全局唯一的登录弹窗(多次点击只渲染一个)。
      • 网络请求:项目中封装的 Axios 实例(包含统一的拦截器配置)。
  • 发布-订阅模式 / 观察者模式 (Pub-Sub / Observer Pattern)
    • 概念:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
    • 前端举例:
      • Vue 响应式原理:数据劫持结合发布订阅(Dep 收集 Watcher,数据更新时 notify 通知视图更新)。
      • 事件总线 (EventBus):组件间的跨层级通信(通过 on 监听,emit 触发)。
      • DOM 事件监听:document.addEventListener 本质上就是最经典的观察者模式。
  • 策略模式 (Strategy Pattern)
    • 概念:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。
    • 前端举例:
      • 表单校验:将“非空”、“正则匹配”、“长度限制”等规则封装成独立的策略对象,避免在提交函数里写一堆臃肿的 if-else。
      • 多状态处理:例如根据不同的用户角色(Admin, User, Guest)渲染不同的菜单栏,使用 Map 或对象字面量映射代替冗长的 switch-case。
  • 代理模式 (Proxy Pattern)
    • 概念:为一个对象提供一个代用品或占位符,以便控制对它的访问。
    • 前端举例:
      • Vue3 响应式原理:使用 ES6 的 Proxy 代理原始对象,拦截对对象的 get 和 set 操作。
      • 开发环境跨域:Webpack / Vite 的 proxy 配置,或者 Nginx 反向代理服务器。
      • 事件委托:把子节点的点击事件绑定在父节点上(利用事件冒泡机制代理事件)。
  • 装饰器模式 (Decorator Pattern)
    • 概念:在不改变对象自身代码的基础上,在程序运行期间给对象动态地添加职责。
    • 前端举例:
      • React 高阶组件 (HOC):用一个函数包裹普通组件,返回一个注入了新属性或逻辑(如路由、权限控制)的增强版新组件。
      • 工具函数装饰器:通过 TS/ES 提案的 @debounce 等语法糖装饰类的方法,实现防抖或节流。

2. Node.js 中的设计模式

  • 观察者模式 (Observer Pattern)
    • 应用:EventEmitter。这是 Node.js 异步非阻塞 I/O 的基石。几乎所有 Node 的核心模块(如 http.Server、fs.ReadStream、process)都继承自 EventEmitter。通过 .on() 监听事件,.emit() 触发事件。
  • 中间件模式 (Middleware Pattern / 责任链模式变种)
    • 应用:Express 和 Koa 框架。HTTP 请求(Request)像流水一样穿过一个个中间件,每个中间件只负责自己特定的功能(如解析 Body、鉴权、记录日志)。Koa 更是结合 async/await 实现了著名的“洋葱模型”。
  • 流模式 (Stream Pattern)
    • 应用:大文件处理。处理大文件或网络传输时,不把文件一次性读入内存,而是将大块数据切分成小块(Buffer),一点点流动处理(例如 fs.createReadStream(src).pipe(res)),极大降低内存占用。

3. Nest.js 中的核心设计模式

Nest.js 是一个重度使用设计模式的现代化 Node 框架(深受 Angular 启发),非常适合用来展示架构能力:

  • 依赖注入 / 控制反转 (DI / IoC - Dependency Injection)
    • 应用:Nest.js 的核心架构灵魂。将类的实例化控制权交给框架的 IoC 容器管理,而不是在类内部去 new 实例。
    • 优势:极大地解耦了 Controller 和 Service。在进行单元测试时,可以非常方便地注入 Mock 的 Service 实例,提高了代码的可测试性和可维护性。
  • 装饰器模式 (Decorator Pattern)
    • 应用:Nest.js 大量使用了 TS 的装饰器。通过 @Controller(), @Get(), @Injectable(), @UseGuards() 等装饰器,结合元数据反射(Reflect Metadata),优雅且直观地定义了路由、提供者和守卫,使代码声明式、极具可读性。
  • 单例模式 (Singleton Pattern)
    • 应用:在 Nest.js 中,默认情况下所有的 Provider(各种 Service 服务)在整个应用程序的生命周期内都是单例的。IoC 容器会在应用启动时实例化它们并缓存,之后所有的注入点都会共享这同一个实例。
  • 适配器模式 (Adapter Pattern)
    • 应用:抹平底层框架差异。Nest.js 的底层 HTTP 服务器默认使用 Express,但也支持切换到性能更高的 Fastify。Nest 通过提供 ExpressAdapter 和 FastifyAdapter,向开发者屏蔽了底层的差异,上层业务代码无需修改即可运行在不同的 HTTP 框架之上。

领导面 (总监/业务线负责人) 准备指南

1. 业务与价值导向 (Business & ROI)

Q: 你在团队中是如何推行新技术的(比如 Rust 或 Monorepo)? * A: 小步快跑,试点先行。 1. 先在一个非核心、边缘模块进行试点(Demo)。 2. 用数据证明收益(如:打包速度快了多少,代码复用率高了多少)。 3. 编写详细的文档和脚手架,降低队友上手门槛。 4. 组织 Tech Talk 分享经验,最后才全面推广。 Q: 遇到过最棘手的 Bug 是什么? * A: (可以说 WebGL 上下文丢失的问题,或者微前端下的弹窗挂载问题)。 * 例子:Next.js 路由切换时 3D 场景重建导致 GPU 飙升。 * 解决:引入 View Tunneling 技术,将 Canvas 放在顶层,路由切换时只改变“视图窗口”的位置和相机参数,而不销毁 Canvas 实例,实现了无缝过渡且显存不泄露。

  • Q1: “你做过最有成就感(或最有价值)的项目是什么?它给公司带来了什么业务收益?”

    • 避坑:不要一上来就沉浸在技术细节(如“我用 Rust 优化了什么算法”)。
    • 【参考答案】: “我最有成就感的项目是主导了公司中后台表单的低代码引擎建设以及微前端架构的改造。 当时业务痛点很明显:随着业务扩张,中后台系统数量激增,各种复杂的审批表单开发极慢,前端资源成了业务上线的瓶颈;同时多个系统独立部署,用户要在不同域名间来回跳,体验很差。 我带头做了两件事:一是引入了基于 Schema 的低代码表单引擎,将复杂的表单联动和校验抽象成配置;二是推动了从 iframe/无界 到统一微前端底座的改造。 带来的业务价值是直接的:新页面或复杂表单的开发时间从平均 3 天缩短到了半天,甚至产品经理自己就能配置一部分;微前端改造后,多系统实现了无缝切换和统一的权限登录,用户操作效率大幅提升,内部客诉率明显下降。这让我深刻体会到,技术的价值最终要体现在为业务提效上。”
  • Q2: “你对 AI 赋能协同办公(咱们这个岗位的方向)有什么看法和思考?”

    • 【参考答案】: “我认为目前很多系统的 AI 只是加了一个‘右侧对话框’,这还停留在比较浅层的 Copilot 阶段。 我理解的未来协同办公 AI,应该是走向 Agentic Workflow(智能体工作流),AI 会深度融入甚至重塑现有的审批流和工作流。比如:
      1. 数据处理自动化:系统能自动总结长篇的历史审批意见,甚至基于上下文自动填充极其复杂的表单。
      2. 交互范式转变:从 GUI(图形界面)走向 LUI(语言界面)或两者的融合(UI 即 Prompt)。前端不再只是画页面,而是要提供流式的、无缝的交互体验,比如流式输出时的页面防抖、局部重绘,以及如何用前端手段(如 WebWorker 计算 Token)去优化 AI 的首字响应时间(TTFT)。 所以在这个方向上,前端不仅是展现层,更是连接 AI 大模型和用户体验的核心枢纽。”

2. 技术决策与方法论 (Technical Leadership)

  • Q3: “在微前端(或某项新技术)选型时,你是怎么做决策的?如果团队里有人反对怎么办?”
    • 【参考答案】: “我的选型原则一直是**‘业务诉求优先,兼顾团队现状’**。比如我们在选型微前端时,一开始内部对 Qiankun 和 无界 有分歧。 我的决策过程是:首先明确我们最痛的痛点是什么?我们需要的是极其彻底的沙箱隔离(因为有些老旧的 jQuery/Vue2 项目很难改代码),并且希望接入成本极低。 然后我拉了一个横向对比,并花了两天时间做了一个核心痛点的 POC(概念验证)Demo。数据显示无界基于 Web Components + iframe 的方案在我们的特定场景下,改造成本和隔离效果更优。 面对反对意见:技术没有银弹,反对通常是因为看到了潜在风险或学习成本。我会倾听他们的顾虑,用 POC 的数据去拉齐认知。如果新技术确实带来了额外的工作量,我会主动承担‘铺路’的工作——比如写好无缝接入的脚手架、整理排坑指南和最佳实践文档,甚至组织一次内部的 Code Review 演练,把大家接入的阻力降到最低。”

3. 团队协作与项目推进 (Collaboration)

  • Q4: “在和后端、产品或者 AI 算法团队协作时,遇到过什么冲突?你是怎么解决的?”

    • 【参考答案】: “冲突比较典型的一个场景是:在做 AI 应用时,大模型接口返回的数据结构极其复杂,且因为算法在不断调优,字段频繁变动,导致前端这边经常需要跟着返工,甚至引发线上报错。 我的解决方式是推动建立强约束的‘接口契约(API Contract)’机制。 我不去抱怨他们改动快,而是拉着后端和算法团队开会,达成一个共识:在开发前,必须先在 YAPI/Swagger 或通过 JSON Schema 定义好接口结构。只要 Schema 定了,前端就基于 Mock 数据开发。如果后续他们要修改字段,必须在平台上走变更通知。 遇到需求边界模糊时,我会拉着产品一起,回到最原始的‘业务目标’上来倒推。通过这种流程化、契约化的方式,我们将跨团队的扯皮减少了至少一半,沟通效率显著提升。”
  • Q5: “你之前是怎么带团队的?怎么保证团队的代码质量?”

    • 【参考答案】: “我在带团队时,核心理念是:‘少靠人治,多靠工具和流程’。因为人的状态会有起伏,但工具不会。
      1. 在流程上:我严格推行了 Code Review 制度。CR 的目的不仅是为了抓 Bug,更是为了团队内的知识共享和架构风格统一。我要求核心模块的提交必须有两个以上的 Approve。
      2. 在工具上:我把大量的代码规范沉淀到了工程化基建里。通过 ESLint、Prettier 统一格式,通过 Husky 在 Commit 阶段拦截不合规代码,最后在 CI/CD 流水线上设置自动化卡点。 我的目标是:让写出高质量、符合规范的代码,变成开发者‘阻力最小的一条路’。”

4. 个人反思与稳定性 (Reflection & Future)

  • Q6: “你过去遇到过最大的挫折/技术失误是什么?怎么走出来的?”

    • 【参考答案】: “一个比较深刻的教训是在做微前端改造初期。当时我们上线了一个子应用,由于子应用内部一个不规范的第三方库修改了全局的 window.Promise(或者某个全局变量),导致 Qiankun 的沙箱未能完全拦截,引发了主应用的白屏,影响了部分用户的访问。 止损:我第一时间通过 CI/CD 的快照回滚机制,将线上版本退回了上一版,在 5 分钟内恢复了业务。 复盘与改进:事后我没有简单地去责怪写那个代码的同学。而是深度复盘了沙箱逃逸的底层原因。随后,我们在工程化层面加了两个动作:一是在流水线中加入了对产物的 AST 扫描,禁止某些危险的全局变量修改;二是完善了灰度发布策略和前端页面的白屏监控报警。这个教训让我明白,架构设计的容错性(兜底机制)比追求单纯的技术新颖度更重要。”
  • Q7: “你未来 3-5 年的职业规划是什么?”

    • 【参考答案】: “结合我过去 9 年的积累,我未来的规划是非常清晰的: 短期(前半年到 1 年):我会快速深入咱们公司的业务场景,熟悉现有的技术栈和团队协作模式。特别是在‘AI 协同办公’这条线上,利用我之前在 AI Agent 和跨端架构上的经验,产出能直接提升用户体验或开发效率的实际业务价值。 中期(1-3 年):我希望在前端工程化和复杂业务架构上持续深耕,沉淀出一套能支撑公司未来几年业务高速扩张的通用架构方案或基建生态,成为不仅技术过硬,还能用技术驱动业务发展的核心骨干。 长期:我希望在 AI Native 应用的前端架构领域建立起自己的技术壁垒,成为这个细分领域有影响力的复合型技术专家。”

5. 面试最后:向领导反问什么? (Ask the Leader)

当领导问“你有什么想问我的吗?”时,提出高质量的问题能展现你的战略思维:

  1. 问业务/方向:“您如何看待咱们部门未来一年在‘AI + 协同办公’领域最重要的业务突破点在哪里?前端团队在其中扮演怎样的核心角色?”
  2. 问团队/期望:“对于今天应聘的这个岗位,您期望候选人在入职后的前三个月内,能帮团队解决的最急迫的问题是什么?”
  3. 问工程化:“咱们团队目前在前端工程化、或跨端架构的演进上,主要面临的瓶颈是什么?”
  4. web3:行业监管政策还在完善中,对未来怎么看,以及咱们公司的策略是什么?或者怎么适配合规的问题。

XBot

JD 信息拆解(基于两张截图)

  • 核心职责
    • 体育/视频类 AI 平台前端架构设计与实现:VideoEditor、赛事数据分析可视化、AI 事件检测叠加、统计分析看板
    • 参与需求评审与技术方案,配合后端/算法,保障功能按版本快速迭代
    • 建设可复用、可扩展的前端组件与工具链,推动端到端提效与维护性
  • 必备能力
    • 精通 HTML5/CSS3/ES6+,深刻理解模块化/工程化/组件化设计
    • 熟练 React/Vue,掌握 Next.js(SSR/SSG/ISR,服务端渲染与边缘部署)
    • 视频方向经验:播放器二次开发、流媒体协议(HLS/DASH)、码流/解码基础、切片与码率自适应
    • Canvas/WebGL 数据可视化:轨迹、热图、雷达、时间序列图,实时流数据渲染
    • ToB/工具型产品性能优化:大数据量/实时场景卡顿治理、内存泄漏分析、长列表/虚拟化
    • 至少一种后端语言(Node/Python),能协作 BFF/算法侧
    • 加分:Shopify 经验(电商侧扩展)
  • 面试关注点
    • 视频低延迟播放(LL-HLS/LL-DASH)与缓冲策略、ABR、自定义控制层
    • 画布叠加与视频时间轴对齐:时间戳/帧对齐、rAF 时序、精准寻帧
    • 实时数据可视化与稳定帧率(60fps):OffscreenCanvas/WebWorker/合成层、批量绘制
    • Next.js 在 B 端系统中的价值:首屏/SEO 次要,重点是数据与鉴权、RSC、ISR 与缓存
    • ToB 工程化与治理:规范、门禁、监控、灰度、回滚、SLO

能力映射与准备清单

  • 流媒体播放与控制
    • hls.js / dash.js 与 MSE 基本原理、分片(TS/CMAF)、GOP/关键帧、DVR、直播/点播差异
    • 低延迟策略:短分片、CMAF、低缓冲、ABR 策略微调(带宽估计/缓冲阈值)
  • 画布叠加(Canvas/WebGL)
    • 视频帧与事件时间戳(PTS/Wall-clock)对齐,滚动/拖动时的绘制策略
    • OffscreenCanvas + Worker 下沉重计算;批处理 draw、避免 layout thrash
  • 实时可视化
    • 数据摄取(WebSocket/SSE)、环形缓冲区、窗口聚合;虚拟化列表/图层
  • Next.js 工程化
    • RSC/SSR/ISR、边缘运行时、缓存层(Cache-Control/标签)、鉴权与 RBAC
  • 性能与治理
    • Core Web Vitals(LCP/INP/CLS)与视频页面的特殊优化;Sentry/埋点/Tracing

高频面试题(含参考答案)

  1. 问:HLS 与 DASH 的核心差异?为何选择其中之一?
    • 答:二者都是基于分片的自适应流媒体协议;HLS 起源苹果、M3U8 索引更常见,生态上移动端支持好;DASH 标准化程度更高、编解码更开放。选择取决于终端覆盖与现有 CDN/打包链;若 iOS 原生兼容优先 HLS,若多编解码场景与可扩展性可考虑 DASH。
  2. 问:如何降低直播首帧/首字节延迟并避免卡顿?
    • 答:采用 LL-HLS/LL-DASH(CMAF 短分片)、减小 targetDuration、播放器端降低初始缓冲阈值与快速起播、带宽估计与 ABR 保守策略、预连接与 HTTP/2 复用、弱网采用降级(分辨率/帧率)。
  3. 问:MSE 播放器卡顿定位与优化思路?
    • 答:区分下载卡顿与解码卡顿;监控 buffer length、append/evict 次数、丢帧率;保障关键帧间隔合理(GOP),避免跨段切换非关键帧;控制 SourceBuffer 更新批次,避免频繁 small append;必要时降码率/分辨率/帧率。
  4. 问:如何在视频上叠加 AI 事件轨迹且与时间轴精准同步?
    • 答:以视频的 currentTime 为主时钟,事件使用 PTS/毫秒对齐;绘制使用 rAF,计算每帧需要显示的事件集合;拖动/seek 时重放关键节点;高频轨迹绘制用 OffscreenCanvas + Worker 计算路径,主线程只合成。
  5. 问:Canvas 与 WebGL 的选型?
    • 答:少量形状/静态标注 Canvas2D 足够;海量点/线/热力、需要着色器与 GPU 加速选 WebGL(或 regl/pixi)。统一抽象图层接口,便于按场景切换渲染器。
  6. 问:如何保证复杂可视化下的 60fps?
    • 答:合并绘制批次、持久化路径、避免全量重绘(脏矩形/区域刷新)、rAF 节流、Worker 下沉重计算、纹理复用、减少文本度量与像素级操作。
  7. 问:Next.js 在该类平台中的价值是什么?
    • 答:统一路由与数据获取模式(RSC/SSR/ISR),边缘渲染提升接口聚合与鉴权体验;对 SEO 加成次要,更看重 BFF 能力、缓存策略与稳定首屏。
  8. 问:ToB 工具型系统的性能与稳定性如何治理?
    • 答:门禁(ESLint/TypeCheck/Husky/CI)、灰度/金丝雀、特性开关、可观测(埋点/日志/Trace)、SLO 与报警、快照回滚;前端侧虚拟化/按需加载/预取。
  9. 问:如何设计播放器二次开发的插件体系?
    • 答:事件总线/生命周期(onInit/onPlay/onPause/onSeek)、UI 插件与核心解耦、配置化与能力探测、错误边界、版本/能力检查。
  10. 问:弱网或丢包严重时的容错策略?
    • 答:切到低码率/低分辨率、拉长缓冲、关闭高代价滤镜、降帧;提示用户网络状态,必要时切直出流或纯音频。
  11. 问:如何与算法/后端约定视频事件数据契约?
    • 答:统一时间基(毫秒/PTS)、坐标系(相对/绝对)、采样率、精度;用 JSON Schema/Protobuf 规范并版本化;提供回放对齐工具。
  12. 问:在多页面/多模块中共享实时连接(WS)?
    • 答:Service Worker 或共享单例连接层;主题发布-订阅分发数据;断线重连与指数退避。
  13. 问:前端如何做视频内容安全与授权?
    • 答:签名 URL/一次性 token、CORS 与防盗链、必要时 EME/DRM;埋点追踪盗链来源与异常访问。
  14. 问:数据可视化大屏卡顿怎么排查?
    • 答:分层定位:数据摄取(批次/频率)→转换(聚合/采样)→渲染(批次/纹理/合成层)→浏览器性能面板(长任务/JS Heap/帧时);逐层优化与降级策略。
  15. 问:如何组织跨端协作(前端/后端/算法)?
    • 答:接口契约先行,Mock 并行开发;对齐数据口径与落地节奏;上线走灰度与回滚,日志/埋点对齐以便端到端排障。

2 分钟项目陈述模板(可直接复述)

  • 开场:我负责体育视频 AI 平台的前端架构,包含视频编辑器、AI 事件叠加与数据看板。核心挑战在低延迟直播下的稳定播放与实时可视化的流畅度。
  • 技术要点:
    • 播放层:基于 hls.js/dash.js + MSE,按 LL-HLS 调短分片与缓冲,ABR 保守起播,弱网降级;监控 buffer/丢帧/append 指标定位卡顿。
    • 叠加层:以视频 currentTime 为时钟,事件按毫秒对齐;轨迹计算下沉 Worker,主线程 rAF 合成;大规模点线用 WebGL。
    • 可视化层:WebSocket 输入 → 环形缓冲 → 窗口聚合 → 虚拟化渲染,保持 55–60fps。
    • 工程化:Next.js 做数据聚合与鉴权、ISR 缓存;门禁与监控完善,灰度/回滚保障稳定。
  • 业务结果:弱网场景卡顿率下降显著,编辑器复杂场景仍保持流畅;上线周期对比原系统缩短,功能迭代节奏稳定可控。

面试官通常在乎什么

  • 能否把视频/流媒体的核心概念说清:分片、关键帧、缓冲、ABR、低延迟策略
  • 能否把叠加渲染与时间轴对齐的技术细节讲清:rAF、时间基、拖动/seek 对齐、Worker/OffscreenCanvas
  • 实时可视化的帧率保障方法:合并绘制/区域刷新/虚拟化/显存与纹理管理
  • Next.js 在 B 端的工程化价值:数据聚合、鉴权、缓存与边缘 Runtime
  • ToB 产品的稳定性与治理:门禁、监控、SLO、灰度、回滚与故障演练

web3

1. 什么是 Web3.0?它与 Web1.0 和 Web2.0 有什么区别?

  • Web 1.0 (Read-Only):信息的单向传递,用户只能阅读内容(如早期的门户网站)。
  • Web 2.0 (Read-Write):用户可以创造内容并进行交互(如社交媒体、博客),但数据和控制权掌握在中心化大公司手中。
  • Web 3.0 (Read-Write-Own):基于区块链技术的去中心化互联网。用户不仅可以读写,还通过钱包(私钥)真正拥有自己的数据和数字资产(Token、NFT),打破了平台垄断。

2. 什么是智能合约(Smart Contract)?

智能合约是运行在区块链(如以太坊)上的自动执行的计算机程序。

  • 特点:代码即法律。当预先编程的条件被触发时,它会自动执行相应的操作(如转账、状态更新),无需第三方中介。
  • 不可篡改性:一旦部署到区块链上,代码通常是无法修改的(除非使用了代理升级模式)。

3. DApp (去中心化应用) 的架构与传统 Web 应用有什么不同?

  • 前端:类似传统 Web,使用 React/Vue 等框架,但通过 Ethers.js 或 Web3.js 等库与区块链交互。
  • 后端(逻辑):核心业务逻辑被写成智能合约,部署在区块链上,而不是传统的中心化服务器。
  • 数据库:交易数据和关键状态存储在区块链上。非关键的大型数据(如图片、视频)通常存储在 IPFS 或 Arweave 等去中心化存储网络中。
  • 身份认证:传统应用使用账号密码/JWT,DApp 使用加密钱包(如 MetaMask)签名来验证身份。

4. 什么是 ERC-20 和 ERC-721 标准?

  • ERC-20:以太坊上的**同质化代币(Fungible Token)**标准。每个代币都是相同的,可以互相替换和分割(就像现实中的货币,如 USDT、UNI)。
  • ERC-721:以太坊上的**非同质化代币(Non-Fungible Token, NFT)**标准。每个代币都是独一无二的,不可分割(用于代表数字艺术品、虚拟地产、游戏道具等)。

5. Web3 前端开发中,如何连接用户的钱包并获取余额?(以 ethers.js 为例)

用户通常通过浏览器插件钱包(如 MetaMask)注入的 window.ethereum 对象来交互。

import { ethers } from "ethers";

async function connectWallet() {
  // 1. 检查是否安装了 MetaMask
  if (typeof window.ethereum !== 'undefined') {
    try {
      // 2. 请求用户授权连接钱包
      await window.ethereum.request({ method: 'eth_requestAccounts' });
      
      // 3. 创建 provider
      const provider = new ethers.BrowserProvider(window.ethereum);
      
      // 4. 获取 signer (当前用户)
      const signer = await provider.getSigner();
      const address = await signer.getAddress();
      
      // 5. 获取余额 (返回的是 Wei 单位)
      const balanceWei = await provider.getBalance(address);
      // 转换成 Ether 显示
      const balanceEth = ethers.formatEther(balanceWei);
      
      console.log(`Address: ${address}, Balance: ${balanceEth} ETH`);
    } catch (error) {
      console.error("用户拒绝连接或发生错误", error);
    }
  } else {
    console.log("请安装 MetaMask!");
  }
}

Q1: 在设计一个 dApp 架构时,你是如何划分链上 (On-chain) 和链下 (Off-chain) 逻辑的?为什么?

“dApp 的核心架构原则是:‘将资产和核心共识放在链上,将计算和体验放在链下’。

  1. 链上 (On-chain) 部分:只保留最核心的价值转移(如 Token 转移、NFT 铸造)、状态校验和核心业务规则(AMM 曲线计算等)。因为链上计算和存储极其昂贵(Gas 费)。
  2. 链下 (Off-chain) 存储与计算:
    • 数据索引与查询:我会使用 The Graph (子图) 或自行搭建一个 Go/Node.js 的后台服务,监听链上 Event 事件,将数据同步到 PostgreSQL 或 MongoDB 中。因为如果让前端直接向 RPC 节点发送复杂的查询过滤,性能极差。
    • 元数据存储:像 NFT 的 JSON 元数据和图片,我会存储在 IPFS 或 Arweave 等去中心化存储中,合约里只存一个 CID (URI)。
  3. 前端 (Client):使用 Next.js 结合 viem 或 wagmi 库,与用户钱包(如 MetaMask)交互,发送签名交易。”

Q2: Solidity、Rust 和 Go 在区块链开发中分别扮演什么角色?你的技术栈偏好是什么?

“这三门语言在区块链领域生态定位不同:

  • Solidity:EVM (以太坊虚拟机) 生态的绝对霸主。开发 DeFi、NFT 必备,语法类似 JS,但有着极度严苛的安全和 Gas 优化要求。
  • Rust:高性能、内存安全的代表。它是 Solana、Polkadot 以及很多高性能 Layer 1/Layer 2 的首选合约语言。相比 Solidity,Rust 的学习曲线更陡峭,但几乎杜绝了内存泄漏和数据竞争问题。
  • Go:基础设施之王。以太坊的主流客户端 Geth 就是用 Go 写的。Go 通常用于编写公链的底层共识层、P2P 网络,或者高性能的链下索引服务。 作为全栈,我倾向于用 Solidity/Rust 写核心合约,用 Go 或 Node.js (NestJS) 写链下高并发的监听和撮合服务。”

Q3: 你在编写 Solidity 智能合约时,遇到过哪些常见的安全漏洞?你是如何防范的?

“智能合约发布后不可篡改,安全是第一位的。最核心的防御点是:

  1. 重入攻击 (Reentrancy):这是最臭名昭著的漏洞(如 DAO 被黑事件)。攻击者在合约向外发送以太坊时,利用 fallback 或 receive 函数再次调用原合约。
    • 防范:严格遵循 CEI 模式 (Checks-Effects-Interactions)(先检查状态,再更新状态,最后才与其他合约交互)。并在关键提款函数上使用 OpenZeppelin 的 ReentrancyGuard (nonReentrant 修饰符)。
  2. 整型溢出 (Integer Overflow/Underflow):
    • 防范:在 Solidity 0.8.0 之前必须用 SafeMath 库,0.8.0 之后编译器原生内置了溢出检查,所以我通常确保编译器版本 >=0.8.x。
  3. 权限控制不当与未初始化的代理合约:
    • 防范:严格使用 Ownable 或 AccessControl 控制敏感函数。对于可升级合约(UUPS 模式),部署后必须第一时间调用 initialize 函数,防止被攻击者接管逻辑合约。”

Q4: 当前 AI Agent 经济正在兴起,如果你要设计一个“AI 代理自动使用加密货币支付 API 费用”的系统,你会怎么设计?

让 AI Agent 拥有钱包,核心是权限委托和自动流支付。

  1. 钱包架构选型:我不会给 Agent 直接配置私钥,这太危险。我会采用 账户抽象 (Account Abstraction, ERC-4337) 架构。创建一个智能合约钱包 (Smart Contract Wallet)。
  2. 权限委托 (Session Keys):用户授权给 Agent 一把‘会话密钥 (Session Key)’。这个密钥只能在特定时间段内、调用特定的合约(比如支付 OpenAI 的计费合约)、并且有最高消费额度限制。这样即使 Agent 失控,用户的资金也是安全的。
  3. 高频微支付处理:AI 调用的 Token 是微小且高频的(比如每次对话扣 0.001 U)。如果每笔都在主网确认,Gas 费会远超 API 费用。我会使用 状态通道 (State Channels) 或建立在 Layer 2 (如 Base, Arbitrum) 上的微支付系统。Agent 和 API 提供方在链下不断更新余额状态,最后只在链上结算一次总账。”

Q5: 如果要用 Go 开发一个监听链上 DEX (如 Uniswap) 的高频套利/交易机器人,关键的技术挑战是什么?

“高频交易 (MEV/套利) 的核心是‘延迟’。在链上,谁的交易先被打包,谁就赢。

  1. 网络延迟层:不能依赖公共的 RPC 节点(如 Infura/Alchemy),必须在 AWS 或同数据中心部署自己的全节点 (Full Node),甚至是定制化的 Geth 客户端,以毫秒级速度获取最新的 Mempool (内存池) 数据。
  2. 并发与语言特性:我会选择 Go 语言。利用 Goroutines 处理高并发的事件监听和多条套利路径的并行计算。
  3. MEV 保护与私密交易:如果直接将套利交易广播到公开的 Mempool,很容易被别人利用 Flashbots 抢跑 (Front-running)。因此,我会直接将签名的 Bundle 发送给特定的 Builder 或 MEV Relay(如 Flashbots RPC),确保交易要么成功打包,要么不被公开。”

科技

1. JD 深度解析与个人匹配度

核心能力图谱与我们的优势(结合 ai-data-analyzer 项目):

  1. 前端生态 (Next.js/React/TS):要求熟练使用 Next.js 进行生产级开发。
    • 匹配点:我们的项目中前端就是基于 Next.js (App Router) + React 19 + TailwindCSS v4 搭建的。我们深入使用了 Server Components、ISR、Edge Runtime (网关代理) 等高级特性。
  2. 后端与数据库 (Node.js/PostgreSQL/ORM):JD 提到了 PostgreSQL 和 ORM (Drizzle 优先)。
    • 匹配点:我们使用了 NestJS + PostgreSQL + TypeORM。虽然 JD 倾向 Drizzle(因为其轻量、SQL-like、对 Edge 友好),但我们可以强调 TypeORM 的复杂关系处理能力,并表示对 Drizzle 这种轻量级现代 ORM 也有关注和理解。
  3. AI 核心能力落地 (LLM, Agent, Function Calling, Streaming):
    • 匹配点:这完全命中了我们当前项目的核心!我们在项目中实现了Agent 编排(从数据上传到清洗、分析)、实时流式反馈 (SSE)、状态推送 (Socket.io)。完全契合 JD 要求的“Agent编排、对话流、工具调用”。
  4. 工程效能 (重度 AI 工具使用者):要求 Cursor, Claude Code 等作为日常开发方式。
    • 匹配点:这是你的强项,你就是通过这类 AI 助手(如当前对话的 Trae/Claude 引擎)进行结对编程和项目推进的,可以分享你通过 Prompt 驱动开发、利用 AI 解决复杂架构设计、重构代码的实际体验。
  5. 独立闭环与产品 Sense:能独立完成从需求理解到上线部署。
    • 匹配点:你一个人构建了涵盖 Next.js、NestJS、Redis 队列、PostgreSQL 的全栈项目架构,这就是最强的背书。

2. 核心面试题与高分回答话术

Q1: 你在项目中是如何实现大模型(LLM)的流式输出和状态同步的?(考察 Streaming, Vercel AI SDK/SSE)

💡 回答思路(结合 ai-data-analyzer): “在我们的 AI 数据分析 Agent 项目中,为了保证极致的用户体验,不能让用户干等大模型长达几十秒的推理。我没有使用传统的短轮询,而是采用了 SSE (Server-Sent Events) + WebSocket (Socket.io) 的双通道架构。

  1. 内容流式输出 (Streaming):后端的 NestJS 接收到大模型(如 OpenAI)的 stream 流后,直接通过 SSE 转发给前端的 Next.js。前端利用类似于 Vercel AI SDK 的思想(或直接使用其 useChat hook),将流式块 (chunks) 实时拼接成打字机效果。
  2. Agent 状态推送:因为一个复杂任务(如:上传 -> 清洗 -> 生成图表代码 -> 渲染)包含多个中间状态,我使用了 Socket.io 向前端实时推送 Agent 的思考过程和执行进度。这种**数据流(SSE) + 状态流(WS)**的分离,使得前端不仅能看到文字生成,还能看到如‘正在分析数据维度...’的骨架屏状态切换,体验非常流畅。”
Q2: 你们的项目有涉及到 Function Calling (工具调用) 或 Agent 编排吗?具体是怎么落地的?

💡 回答思路: “是的,Function Calling 是我们 Agent 能够操作外部系统的核心。在我的项目中,用户的需求通常不是简单的问答,而是需要‘分析这份 CSV 并生成一张柱状图’。

  1. 意图识别与工具注册:我会将‘图表生成’、‘数据清洗脚本执行’定义为具体的 Tool (Function Schema) 注册给大模型。
  2. 执行流程编排:当用户输入需求时,LLM 判断需要调用‘图表生成工具’,它会返回一个带参数的 JSON。后端拦截到这个 Tool Call,解析参数,提取出数据源,动态生成 ECharts 的配置代码。
  3. 数据校验机制:大模型偶尔会产生幻觉(比如返回的 JSON 结构不对)。我结合了 Zod 和 class-validator 在拿到大模型结果的第一时间进行校验,如果失败,会触发内部的重试机制,将错误信息喂给大模型让它自我修正 (Self-Correction),极大地提升了最终图表渲染的成功率。”
Q3: 为什么你们的全栈方案中,数据库选型使用了 PostgreSQL?对于 ORM,你对 Drizzle 有了解吗?

“选择 PostgreSQL 是因为 AI 项目通常涉及大量的非结构化或半结构化数据(如用户的 Prompt、大模型返回的复杂 JSON 结果),PG 对 JSONB 的原生支持非常强大,且未来扩展 pgvector 做向量检索(RAG)无缝衔接。 在我当前的项目中,因为后端是 NestJS 体系,我使用了生态最契合的 TypeORM 来处理复杂的关系映射。 关于 Drizzle:我非常关注 Drizzle ORM,我知道它现在在 Next.js / TypeScript 全栈圈非常火。相比 TypeORM,Drizzle 是真正的 SQL-like,没有沉重的面向对象开销,类型推导也更极致。最重要的是,Drizzle 原生支持 Edge Runtime(边缘计算),这对于部署在 Vercel 或 Cloudflare 的 Serverless 函数来说是决定性的优势,因为传统 ORM 在 Edge 上往往跑不起来。如果团队目前的技术栈是基于 Next.js 的全栈(如 T3 Stack),我完全有能力并非常乐意切换到 Drizzle。”

Q4: JD 提到“重度使用 AI 编程工具”,你能谈谈你日常是如何使用 Cursor 或类似工具开发的吗?它们对你的开发方式产生了什么改变?

💡 回答思路(展示高级使用技巧,而非只是用来写注释): “AI 编程工具对我来说不是一个‘高级搜索器’,而是我的结对编程伙伴 (Pair-programmer)。

  1. 全局上下文驱动:在使用这类工具(如 Cursor/Claude Code)时,我不会只问零碎的问题。我会利用它们读取整个 codebase 的能力(比如 @Codebase 或提供详细的结构树),让 AI 在理解了我的路由层、服务层、数据模型的基础上去生成代码,这样生成的代码不需要我大量手动改写就能直接运行。
  2. 架构设计与重构:比如在做 Next.js 前端性能优化时,我会把一个臃肿的 Server Component 交给 AI,并给出 Prompt:‘请遵循 Next.js 14 最佳实践,将重型图表组件抽离为 Client Component 并使用 next/dynamic 进行代码分割’。它能瞬间完成并处理好依赖引入。
  3. 编写测试与排错:遇到诡异的构建错误(比如 Next.js 的 hydration 错误),我会直接把终端的报错日志扔给 AI,结合它对代码库的理解,通常能在一分钟内定位到是哪个组件的 ssr: false 配置出了问题。 总的来说,AI 工具让我从‘写代码的工人’变成了‘代码的 Reviewer 和架构的指挥官’,我的开发效率至少提升了 3-5 倍。”
Q5: 你们的项目是如何处理长耗时 AI 任务的?(考察异步架构与系统解耦)

💡 回答思路: “在处理数十万行数据的分析时,普通的 HTTP 请求肯定会超时。我采用的是异步任务队列架构。 当用户上传文件并提交分析请求后,NestJS 接收请求后不会阻塞等待大模型处理,而是立即将任务打包投递到基于 Redis 的 BullMQ 任务队列中,并返回给前端一个 taskId。 后台有专门的 Worker 进程从队列中消费任务,调用大模型进行分步处理。前端拿到 taskId 后,利用 SWR 或 WebSocket 对该任务的状态进行智能轮询/监听。这种架构极大地提高了系统的吞吐量,保证了高并发下核心服务的稳定性。”

悟道 35k

1. JD 深度解析与个人匹配度

核心能力拆解与你的优势:

  1. 扎实的前端底盘与 React 深度:HTML5/CSS3/JS,精通 React (Hooks、组件设计、状态管理)、工程化 (Webpack/Vite)。
    • 匹配点:你的 ai-data-analyzer 项目前端完全基于 React 19 + Next.js App Router 构建,深度使用了最新的 React 特性(Server Components、并发渲染等),对 Hooks 和状态管理有深刻理解。
  2. AI 编程能力与 Vibe Coding 经验:熟练使用 Cursor/Claude Code 等工具,能协作开发、重构、排错。能对 AI 代码进行审查调优。
    • 匹配点:你目前的开发模式就是标准的 Vibe Coding(通过自然语言描述意图,AI 负责编码实现,你负责架构把控与代码 Review)。你完全符合“从 0 到 1 快速构建产品”的加分项。
  3. ToB 金融报告 / 在线文档编辑器经验 (加分项):熟悉 WPS WebOffice、OnlyOffice 等方案。
    • 匹配点:虽然你没有直接去开发 WPS 的内核,但你的 AI Agent 项目核心就是在生成复杂的数据分析报告和可视化看板(ECharts/3D)。这与金融报告、文档生成的业务逻辑高度一致。

Q1: JD 中提到了“Vibe Coding”和“使用 AI 工具从 0 到 1

💡 回答思路(强调架构控制与 Prompt 工程): “对我来说,Vibe Coding 并不是简单地给大模型发一句‘帮我写个页面’,而是一种高维度的架构驱动开发模式。 以我最近从 0 到 1 独立构建的 AI Data Analyzer (自动化数据分析 Agent) 为例:

  1. 全局架构规划:我首先会用 AI 助手(如 Cursor 或 Claude)确立项目的脚手架规范,设定明确的 .cursorrules,比如规定使用 Next.js App Router、TailwindCSS v4 和 Server Components。
  2. 上下文注入 (Context Feeding):在开发具体功能(如:SSE 流式对话组件)时,我会让 AI 提前读取后端的 API 路由接口定义,以及我的全局状态管理文件。这样 AI 生成的 React Hooks 就能直接无缝对接,不需要我手动去补齐类型和接口路径。
  3. 复杂逻辑攻坚:面对像大文件上传切片、或者是 Three.js 复杂渲染时,我主要充当产品经理和架构师的角色,把需求拆解成几个明确的步骤,让 AI 逐块实现。我验证通过后,再合并到主干。这让我的开发效率有了跨越式的提升。”
Q2: AI 生成的代码往往存在规范性、安全性和可维护性问题。你是如何审查和调优 AI 代码的?

💡 回答思路(展示你对代码质量的底线要求): “这是使用 AI 编程最容易踩坑的地方。AI 经常会‘为了实现功能而堆砌代码’(比如写出上百行的 useEffect 或过度使用 any 类型)。我的审查和调优原则是:

  1. 强制类型安全与边界校验:AI 返回的数据结构可能不可靠。我会使用 Zod 或 TS 严格类型对 AI 涉及的入参/出参进行强校验。如果 AI 写了 any 或者忽略了错误捕获 (try/catch),我会在 Review 时强制让它重构。
  2. 提取自定义 Hooks 与组件解耦:AI 倾向于把所有逻辑写在一个巨大的组件里。当我发现一个组件超过 200 行,我会指挥 AI:‘请将这里的数据获取和状态管理逻辑抽离成一个 useDataAnalysis Hook,保持 UI 组件的纯粹洁净 (Dumb Component)’。
  3. 消除幻觉与冗余依赖:AI 有时会引入项目中根本不存在的第三方库,或者使用已经废弃的 React 模式。我不仅依赖 ESLint 的静态检查,还会凭借我对 React 生态的熟悉,及时纠正它的‘幻觉’,确保代码符合团队现有的工程化规范。”
Q3: 结合你精通的 React 技术栈,在面对复杂 ToB 业务(如数据报告、分析看板)时,你是如何进行组件设计和状态管理的?

💡 回答思路(体现资深前端的架构 Sense): “在 ToB 数据分析场景(比如我做的 AI 数据看板),页面的状态和数据流通常极其复杂。

  1. 组件设计(Smart & Dumb 模式):我会严格区分‘容器组件’和‘展示组件’。比如一个图表报告页,外层容器负责与后端(或 AI 引擎)进行 SSE 流式通信、获取全局配置;而底层的图表组件(如 ECharts 封装)只接收 props 进行纯渲染。
  2. 状态管理选型:
    • 对于服务端的异步状态(如轮询任务状态),我抛弃了传统的 Redux,改用 SWR 或 React Query。这极大地简化了数据缓存、重试和竞态问题。
    • 对于纯客户端的 UI 交互状态(如面板的折叠、图表的深浅色模式),我偏向使用轻量级的 Zustand 或 React Context,避免了 Redux 繁琐的样板代码。
  3. 性能隔离:复杂的 ToB 看板最怕卡顿。对于包含大量计算的模块,我会利用 useMemo 缓存计算结果,并使用 next/dynamic(React.lazy)对重型图表库(如 ECharts/Three.js)进行动态拆分加载,确保首屏秒开。”
Q4: JD 的加分项提到了“在线文档/报告编辑器的开发经验(类似 WPS WebOffice)”,结合你的项目,你在富文本或复杂报表呈现上有什么思路?

💡 回答思路(跨界联想,将劣势转化为优势): “虽然我没有直接开发过 WPS 这种底层基于 Canvas 渲染的超级在线 Office,但我的 AI Agent 项目最终的交付物正是一份**‘动态生成的智能数据分析报告’**。 针对这类复杂文档或报告的开发,我的技术思路是:

  1. 基于 Schema 的渲染机制:无论是在线文档还是我的 AI 报告,底层数据绝不能是写死的 HTML 字符串,而应该是一套结构化的 JSON Schema。AI 生成数据,前端根据 Schema 动态渲染出对应的文本块、数据表格和 ECharts 图表。
  2. 模块化与拖拽(可扩展性):如果未来业务需要支持用户手动编辑报告,我会引入类似 ProseMirror 或 Yjs 的 CRDT 算法来实现协同编辑;在视图层,可以基于 Slate.js 或类似富文本框架,把图表作为一种自定义 Node 嵌入到文档流中。
  3. 性能考量:对于包含成百上千行数据的金融报表,原生的 DOM 渲染会造成严重的内存泄漏和滚动卡顿。我会使用虚拟滚动 (Virtual Scrolling) 技术,只渲染可视区域内的 DOM 节点,确保编辑器在极大数据量下依然如丝般顺滑。”

ying

2. 核心面试题与高分回答话术

Q1: JD 要求“具备设计和搭建多 Agent 架构的能力”,假设我们的系统需要多个 AI Agent 协作(比如一个负责检索数据,一个负责写代码,一个负责 Review),你会如何设计它们的调度、通信和生命周期管理?

💡 回答思路(展示后端架构与 AI 的结合能力): “在设计多 Agent 协作系统时,最忌讳的是让它们通过同步的 HTTP 请求互相死等,这会导致极差的容错率和极高的延迟。我会采用基于消息驱动的异步事件架构 (Event-Driven Architecture)。

  1. 调度与通信:我会引入类似 Redis 的 BullMQ 或 Kafka 作为中央消息总线。当总控 Agent (Router) 接收到用户请求时,它会将任务拆解,并向特定的 Topic 发布消息。检索 Agent 和编码 Agent 作为 Worker 监听对应的 Topic 进行消费。
  2. 生命周期与并发控制:每个 Agent 的执行都是一个状态机(Pending -> Processing -> Completed/Failed)。在 Node.js/NestJS 中,我会为每个 Worker 设定并发上限(Concurrency控制),防止短时间内大模型 API 并发过高被限流 (Rate Limit)。
  3. 资源隔离与容错:如果某个 Agent 陷入死循环或超时,任务队列会触发 Timeout 机制,并根据设定的策略进行重试 (Retry) 或将任务丢入死信队列 (DLQ),防止单个 Agent 的崩溃拖垮整个系统。”
Q2: 针对“大流量、高并发”的场景,如果我们上线了一个爆款的 AI 应用,瞬间涌入大量用户,你会从哪些层面进行性能调优和稳定性保障?

💡 回答思路(展现全链路的 DevOps 与后端调优经验): “应对高并发需要从接入层、应用层到数据层进行全链路防护:

  1. 接入层与前端 (CDN & 边缘计算):首先,静态资源必须全部上 CDN。对于一些无需个性化计算的接口,我会利用 Next.js 的 Edge Runtime 和 ISR(增量静态生成)在边缘节点直接拦截请求,大幅减轻源站压力。
  2. 应用层 (扩容与限流):后端采用 Docker 容器化部署在 Kubernetes (K8s) 上。我会配置 HPA (Horizontal Pod Autoscaler),根据 CPU 使用率或消息队列的积压长度自动水平扩容 Node.js/NestJS 实例。同时,在网关层 (如 Nginx 或 API Gateway) 严格配置 IP 限流和 Token 令牌桶算法,防止恶意刷接口。
  3. 数据层与异步削峰:高并发下绝不能让请求直接打到 PostgreSQL。我会引入 Redis 做热点数据缓存;对于耗时的 AI 推理请求,全面采用异步化,前端提交任务后立即返回,随后通过 WebSocket / SSE 建立长连接,等待后台 Worker 慢慢消费并推送结果,实现完美削峰。”
Q3: 你如何理解 RAG (检索增强生成) 系统?如果在项目中要落地一个 “LLM + Vector DB” 的检索功能,你会怎么做?

💡 回答思路(直击 JD 中的 AI 数据驱动要求): “RAG 系统的核心目的是解决大模型的‘幻觉’和‘私有数据缺失’问题。落地 RAG 我会分为数据处理和检索生成两步:

  1. 离线数据管道 (Data Pipeline):首先需要将企业的私有文档进行解析,然后进行合理的切块 (Chunking)。切块策略很关键,不能切断上下文语义。接着,调用 Embedding 模型(如 text-embedding-3-small)将文本块转化为高维向量,并存入向量数据库(如 pgvector 或 Milvus)。
  2. 在线检索与生成:当用户提问时,系统先将用户的问题同样转化为向量,在 Vector DB 中进行 KNN (K近邻) 或余弦相似度检索,召回最相关的 Top-K 个文本块。
  3. 混合检索优化:为了提高准确率,我不仅会用向量检索,还会结合传统的 BM25 关键词检索(混合检索 Hybrid Search),然后使用一个 Reranker 模型对召回结果进行重排,最后将最精准的上下文拼接到 Prompt 中喂给大模型,生成可靠的答案。”
Q4: 前端方面,JD 强调了 SSR/CSR、Hydration 和渲染流程。在 Next.js 的实际项目中,你是如何权衡和优化这些策略的?

💡 回答思路(展现 React/Next.js 深度): “在现代前端架构中,一刀切的 SSR 或 CSR 都是不合理的。在我的项目中,我深度实践了 Next.js 的 Server Components (RSC) 与 Client Components 混合架构。

  1. 渲染策略拆分:对于重内容的框架、SEO 敏感的页面骨架,我全部采用 Server Components(在服务端执行),这样不仅实现了零 JS 打包体积发送到客户端,还直接穿透了数据库获取数据。对于需要用户交互的图表(ECharts)、表单,我才在文件顶部标记 "use client",作为 Client Components。
  2. Hydration 优化:传统的 SSR 会在客户端执行全量的 Hydration(水合),导致 TTI(可交互时间)变长。通过合理使用 RSC,客户端只需对少量的交互组件进行 Hydration。此外,我大量使用了 next/dynamic 和 React Suspense 实现流式渲染 (Streaming),优先展现核心内容,将重型组件延迟加载和水合,极致优化了首屏性能 (LCP)。”
Q5: JD 提到了 HTTP/2、HTTP/3 以及 WebSocket 的实战。你在项目中是如何处理前后端实时通信的?

💡 回答思路(展现网络协议深度): “在 AI 交互场景中,传统的短轮询体验极差。

  1. 对于大模型的文字生成,我会采用 SSE (Server-Sent Events)。它是单向的、基于 HTTP 的流式传输,非常轻量,且天然支持 HTTP/2 的多路复用,不会像 HTTP/1.1 那样受限于浏览器的 6 个并发连接限制。
  2. 而对于需要双向交互、状态高频推送的场景(比如前端需要实时知道后端多个 Agent 的执行进度、资源状态),我会引入 WebSocket (结合 Socket.io 处理降级和心跳保活)。 这两种协议在现代 Web 架构中是互补的:SSE 负责高吞吐的流式文本,WebSocket 负责低延迟的双向信令控制。”

3. 四大核心维度:硬核知识储备与“防追问”指南

维度一:大前端深水区 (渲染、架构、工程化)
  • 重排(Reflow)与重绘(Repaint)底层原理:
    • 防追问:什么时候触发?怎么优化?
    • 答案:改变元素几何属性(宽高、位置)会触发重排(代价极大,需要重新计算布局树);仅改变外观(颜色、背景)触发重绘。优化方案:使用 CSS3 的 transform 和 opacity 实现动画,它们会触发 GPU 硬件加速,跳过主线程的 Layout 和 Paint 阶段,直接进入 Composite(合成)阶段;另外,避免在 JS 循环中频繁读取 offsetHeight 等属性,这会导致浏览器强制清空渲染队列以获取最新值(强制同步布局)。
  • Tree-shaking (摇树优化) 底层机制:
    • 防追问:为什么 CommonJS 不能摇树?
    • 答案:Tree-shaking 依赖于 ES6 Module (ESM) 的静态分析特性(import/export 只能在模块顶层,不能动态引入)。构建工具(如 Webpack/Rollup)通过 AST 分析,标记出未被使用的 export。对于带有副作用的代码,需要在 package.json 中配置 "sideEffects": false 才能彻底清除。
  • SSR vs CSR 与 Next.js App Router:
    • 防追问:SSR 的痛点是什么?Next.js 怎么解决的?
    • 答案:传统 SSR 存在“全量水合 (Hydration)”问题,导致首屏可见但不可交互 (TTI 延迟)。Next.js App Router 引入了 RSC (React Server Components)。RSC 只在服务端运行,生成的组件不会打包任何 JS 到客户端,大幅缩减 Bundle Size。配合 Suspense 实现流式渲染 (Streaming),让重要组件先水合,慢速请求组件后加载。
维度二:后端与高并发架构 (缓存、数据库、安全)
  • Redis 缓存三大经典问题 (击穿、穿透、雪崩):
    • 缓存穿透(查不到):恶意请求查询不存在的 ID,直接打到 DB。对策:缓存空对象 (短 TTL) 或引入布隆过滤器 (Bloom Filter) 拦截。
    • 缓存击穿(热点失效):某一个极高并发的热点 Key 突然过期,大量请求打穿到 DB。对策:使用互斥锁 (如 Redis 的 setnx),只允许一个线程去 DB 重建缓存,其他线程等待;或者设置“逻辑过期时间”(异步线程去更新缓存)。
    • 缓存雪崩(大面积失效):大量 Key 在同一时间过期,或 Redis 宕机。对策:给 TTL 加上随机抖动值 (Random Jitter);搭建 Redis Cluster 高可用集群。
  • PostgreSQL 索引优化与慢查询:
    • 防追问:如何排查慢 SQL?什么是最左前缀?
    • 答案:使用 EXPLAIN ANALYZE 查看执行计划(看走的是 Seq Scan 还是 Index Scan)。建立联合索引时必须遵循最左前缀法则;遇到深分页(如 OFFSET 10000 LIMIT 10)时性能会极差,应改用游标分页 (Cursor/Keyset Pagination),比如 WHERE id > last_id LIMIT 10。
  • JWT 鉴权体系的痛点:
    • 防追问:JWT 是无状态的,如果用户密码泄露或被封号,如何强制踢下线?
    • 答案:引入 Access Token (短效, 15分钟) + Refresh Token (长效, 7天) 双 Token 机制。Refresh Token 存在 Redis 中。当需要踢人时,直接在 Redis 中拉黑/删除对应的 Refresh Token。Access Token 过期后,前端拿失效的 Refresh Token 去换新时就会被拒绝,从而实现踢人。
维度三:AI 与 Multi-Agent 架构 (编排与 RAG)
  • BullMQ 与状态机编排:
    • 防追问:如何保证 Agent 任务的幂等性和不丢失?
    • 答案:BullMQ 基于 Redis 构建,利用 Redis 的事务和 Lua 脚本保证原子性。对于丢失问题,BullMQ 会将任务放在 Active 队列,如果 Worker 崩溃(未发送完成信号),任务超时后会被重新放回 Wait 队列。幂等性:每个任务必须生成全局唯一的 jobId,执行前检查状态,防止重试时造成重复扣费或重复生成。
  • RAG (检索增强生成) 的进阶优化:
    • 防追问:单纯的向量检索准确率不高怎么办?
    • 答案:采用混合检索 (Hybrid Search)。向量检索 (如 pgvector HNSW 算法) 擅长捕捉“语义相似度”,但对专有名词、料号等“精准匹配”较弱。我会结合 BM25 算法 (传统的关键词 TF-IDF 变种) 进行双路召回,然后使用 Reranker (重排模型) 根据问题和文档的相关性重新打分,取 Top 3 输入给大模型,极大降低幻觉。
维度四:DevOps 与云原生 (部署与弹性)
  • Docker 镜像优化:
    • 防追问:Node.js 的 Docker 镜像通常很大,如何优化?
    • 答案:使用 多阶段构建 (Multi-stage Builds)。第一阶段 (Builder) 安装所有 devDependencies 并执行 npm run build;第二阶段 (Runner) 使用极简的基础镜像(如 node:alpine 或 distroless),仅拷贝打包后的产物和生产依赖 (dependencies)。能将镜像从 1GB+ 压缩到 100MB 级别。
  • K8s 的 HPA (弹性伸缩) 原理:
    • 防追问:你的系统是如何自动扩容的?
    • 答案:在 Kubernetes 中配置 Horizontal Pod Autoscaler (HPA)。常规情况基于 CPU/内存利用率(比如 CPU > 70% 增加 Pod)。但在 AI 场景下,CPU 不一定高(都在等大模型 API),所以我会引入 KEDA (Kubernetes Event-driven Autoscaling),监听 Redis/BullMQ 中等待执行的任务队列长度,队列积压超过阈值就自动弹出新的 Worker Pod 来消费任务,消费完再缩容。

一、gRPC & 微服务通信(4 题)阿里/阿里云系前端(AI + 云原生方向)

1. 前端/Node 怎么调用 gRPC?和 REST 区别是什么?

答: 调用流程:

  1. 定义或引入 .proto 接口文件;
  2. 使用 @grpc/grpc-js + @grpc/proto-loader 加载并生成客户端;
  3. 直接像调用本地函数一样发起请求;
  4. 支持一元调用和客户端/服务端/双向流。

区别:

  • REST 基于 JSON + HTTP1.1,文本格式,弱类型;
  • gRPC 基于 Protobuf 二进制 + HTTP/2,更小更快,强类型约束;
  • 微服务内部通信更常用 gRPC,更适合大批量、低延迟场景。

2. 浏览器能直接调 gRPC 吗?

答: 浏览器不能原生调用普通 gRPC,需要用 grpc-web 协议, 并在后端部署 envoy 或 grpc-web 代理做协议转换。 Node.js 环境可以直接调用原生 gRPC。

3. 什么是 Protobuf?有什么好处?

答: Protobuf 是一种结构化数据序列化协议,类似 JSON 但更小更快。 好处:

  • 体积小、序列化快;
  • 强类型,前后端契约明确;
  • 自动生成代码,减少联调成本;
  • 支持字段兼容升级,适合微服务迭代。

4. 流式 gRPC 在前端有什么应用场景?

答:

  • AI 对话打字机效果(服务端流);
  • 日志实时推送、监控大屏;
  • 大文件分片上传(客户端流);
  • 视频直播、实时协作(双向流)。

二、RAG & Embedding & AI 基础(5 题)

5. 什么是 Embedding?前端为什么要了解?

答: Embedding 是把文本、代码、图像转为高维向量,用于语义相似度计算。 前端需要:

  • 调用 embedding 接口构建私有知识库检索;
  • 实现智能搜索、相似推荐、AI 问答;
  • 对接向量数据库(如 Milvus、FAISS、阿里云向量引擎)。

6. 什么是 RAG?为什么大厂都用 RAG 不用纯 LLM?

答: RAG = 检索增强生成。 流程:用户提问 → 检索私有知识库相关片段 → 拼入 Prompt → 大模型生成回答。

优势:

  • 避免大模型胡说八道;
  • 使用企业内部私有知识,不依赖模型训练数据;
  • 可追溯、可管控、更安全合规;
  • 成本更低,更新更灵活。

7. 前端在 RAG 系统里负责什么?

答:

  • 实现对话界面、历史记录;
  • 调用检索接口、embedding 接口;
  • 展示引用来源、片段溯源;
  • 做交互优化:中止、重试、重新生成;
  • 异常处理与体验降级。

8. 向量数据库是什么?常见有哪些?

答: 专门存储和查询高维向量的数据库,用于快速相似度匹配。 常见:Milvus、FAISS、Pinecone、阿里云向量检索版 Lindorm、ES 向量插件。

9. RAG 效果不好怎么优化?(前端能说的层面)

答:

  • 优化查询语句改写,让检索更准;
  • 调整 top-k 召回数量;
  • 增加相关性过滤;
  • 对文档做分段、去重、关键词增强;
  • 优化 prompt 结构,减少无关信息干扰。

三、私有云 & 强管控环境(4 题)

10. 什么是私有云/内网强管控环境?

答:

  • 内外网隔离,不能访问公网大模型;
  • 所有服务、模型部署在内网;
  • 严格权限、审计、发布流程;
  • 数据不可出域,必须本地私有化部署。

11. 在这种环境下,前端开发 AI 应用要注意什么?

答:

  • 不能调用外部 OpenAI/通义千问公网接口;
  • 统一走内部网关、SSO 单点登录、IAM 权限;
  • 不能硬编码域名、IP、密钥;
  • 部署、灰度、回滚必须走平台流程,不能随意发布;
  • 所有请求必须带鉴权 token。

12. Schema Versioning 是什么?为什么重要?

答: Schema 版本管理,指接口、数据库、向量库结构变更时的平滑兼容方案。 重要性:

  • 保证结构升级不宕机、不报错;
  • 新旧版本兼容,支持灰度;
  • 强管控环境下必须可回滚、可观测。

13. 内网环境怎么调试 AI 服务?

答:

  • 使用内网代理、VPN、跳板机;
  • 对接内部测试环境、测试账号;
  • 通过网关统一入口,不直连后端服务;
  • 利用内部日志平台、APM 监控排查问题。

四、安全 & AK 泄露 & 稳定性(4 题)

14. AI 生成代码把 AK/SK 泄露了,前端怎么兜底?

答:

  1. 前端永不持有、不展示、不存储 AK/SK,全部走后端代理;
  2. 构建流程加入敏感信息扫描,拦截密钥泄露;
  3. AI 生成代码必须人工审计 + 自动化检测;
  4. 运行时监控异常调用,及时发现盗刷;
  5. 密钥做到权限最小化、定期轮转、支持快速禁用;
  6. 一旦发生,立即下线版本、禁用密钥、回溯日志、复盘整改。

15. 前端如何避免密钥泄露?

答:

  • 不写死在代码、注释、localStorage;
  • 不提交到 Git;
  • 构建打包前做敏感词扫描;
  • 统一使用临时 token,不用长期 AK;
  • 跨域、请求头严格管控。

16. 什么是 Prompt Injection?怎么防御?

答: 提示词注入,通过构造输入劫持系统指令,窃取信息或执行危险操作。 防御:

  • 前端做长度限制、敏感词过滤;
  • 对用户输入做转义、隔离;
  • 后端做二次校验和拦截;
  • 系统提示不传到前端,避免泄露;
  • 增加日志审计和异常检测。

17. 阿里为什么强调稳定性大于创新?

答:

  • 业务量级大,线上故障影响面极广;
  • 强监管、强合规,安全事故代价极高;
  • 创新必须在可管控、可回滚、可降级的前提下进行;
  • 前端要保证:异常捕获、重试、降级、容灾、快速回滚。

五、WebGPU & 端侧 AI & 前沿(3 题)

18. WebGPU 是什么?相比 WebGL 优势?

答: WebGPU 是新一代浏览器图形与计算接口。 优势:

  • 更低 CPU 开销,多线程计算;
  • 更接近现代 GPU 架构,算力更强;
  • 支持通用计算 GPGPU,可跑端侧 AI 模型;
  • 更适合大规模可视化、3D、实时 AIGC。

19. WebGPU 如何支撑前端 AI?

答:

  • 使用 GPU 算力在浏览器内做模型推理;
  • 运行轻量级 LLM、Embedding、CV 模型;
  • 降低服务端压力,提升响应速度;
  • 保护隐私数据,不离开用户设备。

20. 未来前端核心竞争力是什么?

答:

  • 能对接云原生、微服务 gRPC;
  • 能落地 RAG/Embedding 等 AI 应用;
  • 能在强管控、高安全环境稳定交付;
  • 懂端侧异构计算(WebGPU);
  • 懂安全、稳定性、权限与合规。

下面给你整理一套专门针对「AI 全栈工程师」+ 面试官是 CEO + AI 产品经理的完整版: 会问什么、关注什么、怎么回答,全部一次性给全,你直接照着准备就能用。


二、高频问题 + 考察点 + 标准答案(直接背)

1. 自我介绍

考察:整体匹配度、表达、技术广度 建议结构:

  • 几年全栈经验,主技术栈(前端/后端/AI 工程)
  • 做过哪些 AI 相关系统:对话助手、RAG 知识库、AI 客服、Agent 等
  • 擅长:AI 接口封装、流式输出、前后端联调、部署运维
  • 表达:希望用全栈能力把 AI 产品落地

2. 你理解的 AI 全栈工程师是做什么的?

考察:认知是否清晰 回答:

  • 不只写前端或后端,而是打通 AI 产品整条链路
  • 前端:对话界面、流式打字、交互体验
  • 后端:接口、鉴权、限流、日志、监控
  • AI 层:大模型调用、Prompt、RAG、向量库、知识库管理
  • 部署与运维:Docker、云服务、成本优化、稳定性保障

3. 你做过的最完整的 AI 项目是什么?

考察:真实落地能力 按这个结构说:

  1. 产品目标:比如 AI 问答助手/智能客服
  2. 你负责:全栈 + AI 接入
  3. 技术方案:
    • 前端:流式 SSE 或 WebSocket
    • 后端:接口封装、上下文管理、限流
    • AI:RAG 检索、Prompt 优化、向量数据库
  4. 结果:响应速度、准确率提升、减少人工成本

4. 什么是 RAG?你在项目里怎么实现的?

AI PM 必问 回答:

  • RAG:检索增强生成,先查外部知识库再让模型回答
  • 实现:文档切片 → 向量化 → 存入向量库 → 用户问题检索 → 拼上下文 → 调用大模型
  • 关键点:切片策略、检索召回率、Prompt 约束、避免幻觉

5. 前端怎么实现 AI 流式打字效果?

考察真实全栈经验 回答:

  • 用 SSE(Server-Sent Events)或 WebSocket
  • 后端逐 chunk 返回,前端逐字渲染
  • 处理异常、中断、重发、加载状态

6. 产品提一个 AI 功能,你觉得实现难度大,怎么沟通?

考察协作 回答:

  1. 先确认产品真实目的
  2. 评估:技术成本、时延、成本、稳定性风险
  3. 给出替代方案,优先保证核心体验
  4. 小步迭代,先 MVP 再优化

7. AI 接口经常超时/报错/不稳定,你怎么处理?

考察工程能力 回答:

  • 超时重试、熔断降级
  • 缓存常见问题
  • 前端友好提示
  • 日志监控告警
  • 关键业务做兜底回复

8. 怎么看待大模型幻觉?工程上怎么解决?

回答:

  • 检索增强 RAG
  • 强 Prompt 约束,加引用来源
  • 关键信息加校验规则
  • 敏感场景加人工审核

9. 你怎么估算一个 AI 功能的开发时间?

CEO & PM 都爱问 回答:

  1. 拆模块:前端界面 → 接口 → AI 逻辑 → 数据库 → 测试部署
  2. 评估风险点:第三方模型、并发、数据处理
  3. 预留联调与异常处理时间
  4. 先做最小可用版本,快速验证

10. 项目进度紧张,你怎么保证 AI 效果与稳定性?

回答:

  • 优先保证核心流程可用
  • 灰度小流量上线
  • 关键路径做兜底
  • 实时监控,快速回滚

11. 你怎么和算法/产品配合?

回答:

  • 产品定目标与场景
  • 我负责落地、工程化、体验、稳定性
  • 用数据和效果说话,不主观争论

12. 未来职业规划?

CEO 必问 回答:

  • 深耕 AI 全栈工程化
  • 往 AI 系统架构、高可用、低成本方向发展
  • 希望长期稳定,和公司 AI 产品一起成长

13. 为什么想来我们公司?

回答:

  • 公司 AI 方向清晰
  • 产品落地场景明确
  • 希望用全栈能力把 AI 真正用起来

14. 你有什么问我们?

必问 2 个:

  • 团队当前 AI 产品最核心的目标是什么?
  • 这个岗位前 3 个月的重点任务是什么?

自动化测试工具的前端架构设计

这部分可以作为你面试时体现复杂系统架构能力和工程化落地能力的重点项目。

核心测试工具与框架选型 (面试必问)

在底层测试引擎的选型上,我们经过对比,最终确立了以下工具栈:

  • 核心 E2E 测试引擎:Playwright (微软开源)
    • 为什么不用 Cypress:Cypress 架构在浏览器内部运行,受限于单标签页,且对 iframe、跨域多窗口(如新标签页登录)支持很弱;而 Playwright 基于 CDP (Chrome DevTools Protocol) 在浏览器外部控制,原生支持跨域、多 Tab、多 iframe。
    • 为什么不用 Puppeteer:Puppeteer 主要针对 Chromium 且只支持 JS,而 Playwright 天生支持跨浏览器(Chromium、Firefox、WebKit)矩阵测试,且 API 更现代(自动等待机制,减少 sleep 的编写)。
  • 单元与组件测试:Vitest + Vue Test Utils / React Testing Library
    • 为什么不用 Jest:我们的工程基建是 Vite,如果用 Jest 还需要配置 Babel 转换,双套构建管线维护成本高。Vitest 与 Vite 共享同一套配置 (vite.config.ts),开箱即用,且执行速度极快。
  • 视觉回归测试 (Visual Regression):集成 Pixelmatch 进行断言截图对比,防止 UI 样式意外跑偏。
  • 测试报告与 CI/CD 集成:使用 Allure 生成多维度、可视化的测试报告,并通过 Docker 镜像无缝接入 Jenkins / GitLab CI 跑自动化流水线。

1. 核心业务模块划分

  • 用例编排与可视化编辑:支持低代码拖拽生成测试步骤,或集成代码编辑器(如 Monaco Editor)提供高级脚本(Playwright / Cypress / Puppeteer)编写能力。
  • 执行与调度中心:多环境配置切换、任务触发(立即执行/定时执行)、并发执行策略配置与浏览器矩阵选择。
  • 实时日志与报告大盘:测试执行状态实时回传、断言失败截图与视频回放展示、多维度测试通过率图表(Echarts/AntV)。
  • 资产与数据管理:测试用例库管理、公共组件(Page Object)封装、测试数据驱动(CSV / JSON 参数化导入)。

2. 技术栈与架构分层

  • 展现层 (View):React / Vue3 + 现代化 UI 组件库(Ant Design / Element Plus),满足复杂中后台交互。
  • 状态管理层 (Store):
    • 复杂交互区(如可视化编排):使用 Zustand / Redux 统一管理嵌套的步骤状态。
    • 服务端状态:结合 React Query / SWR 管理接口查询缓存,减少冗余请求,提升弱网体验。
  • 通信与传输层 (Network):
    • 基础数据通信:Axios + 统一的请求拦截、鉴权与错误处理。
    • 实时日志通信:WebSocket 或 SSE(Server-Sent Events),用于在用例执行时接收服务端推过来的实时跑测日志。
  • 工程基建层 (Infrastructure):Vite 极速构建、TypeScript 强类型接口校验、Eslint / Prettier 代码规范、Husky 提交拦截。

3. 核心难点与解决方案 (面试亮点)

难点一:海量测试日志实时渲染导致页面卡顿

  • 场景:自动化测试执行时会疯狂吐出 Console 日志,如果用传统方式直接渲染 DOM 节点,几万条日志会让页面直接卡死。
  • 解决方案:
    • 虚拟列表 (Virtual List):采用 react-window 或 vue-virtual-scroller 技术,只渲染可视区域的几十个 DOM 节点,大幅降低渲染开销。
    • 批量更新:使用 requestAnimationFrame 或防抖/节流(Throttle)控制日志数组的更新频率,将高频单条推送合并为批量渲染。

难点二:可视化用例编排的复杂状态与性能问题

  • 场景:测试步骤层级深(如包含 if 条件判断、for 循环),拖拽排序和状态更新极易引发全局组件重渲染。
  • 解决方案:
    • 数据结构扁平化:将树状深层嵌套转为扁平的 Map + ID 数组,避免深层拷贝。
    • 不可变数据与细粒度订阅:引入 Immer.js 管理不可变状态,利用 Zustand 等实现局部组件的细粒度订阅更新,配合 React.memo 阻断无效渲染。

难点三:大型代码编辑器的性能优化

  • 场景:为了支持高级脚本,引入了 Monaco Editor,但其体积庞大,导致系统首屏加载极慢。
  • 解决方案:
    • 路由懒加载与异步组件:将 Editor 核心库剥离到单独的 Chunk,只在用户点击“脚本模式”时按需加载。
    • Web Worker 卸载计算:结合 Web Worker 将语法解析、高亮提示等繁重计算放在后台线程,保证 UI 主线程的流畅。

难点四:与 DevOps 流水线的无缝集成

  • 场景:测试工具需要嵌入到公司的研发效能平台中,作为一个插件使用。
  • 解决方案:
    • 采用 无界 (Wujie) / Qiankun 微前端方案,将测试工具打包为子应用,实现能力模块的即插即用和样式隔离。

4. 架构演进与未来规划 (加分项)

  • AI 赋能 (AI-Coding):引入大模型,根据自然语言描述直接生成测试脚本(Text-to-Script),或者根据失败的执行日志让 AI 自动分析失败根因(如:“元素未找到是因为弹窗遮挡”)。
  • 录制回放扩展 (Record & Replay):提供 Chrome 浏览器扩展,捕获用户页面的点击、输入操作,前端负责解析 DOM 路径并转化为标准 AST,自动生成对应的自动化测试用例,降低非技术人员的使用门槛。

机器学习、自然语言处理 (AI 与大模型工程化)

作为大前端/全栈开发者,在当前的 AI 时代,我们面试的重点不再是手写底层深度学习算法(如 PyTorch/TensorFlow 推导),而是AI 工程化落地的能力,即如何将 LLM (大语言模型) 和 NLP 技术与现有业务场景结合。

这部分可以作为你拥抱 AI、具备全栈 AI 落地能力的高阶亮点。

1. 核心概念科普 (防盲区)

  • 机器学习 (ML) 基础:了解监督学习(有标签数据,如分类、回归)与无监督学习(无标签数据,如聚类)的区别。
  • Token 与 Embedding (向量化):
    • Token:大模型理解文本的最小单位(约等于 0.75 个英文单词或半个汉字)。LLM 按 Token 计费和限制上下文长度。
    • Embedding:将自然语言转化为高维向量(如 1536 维),让计算机能够计算词语/句子之间的“语义相似度”(如计算余弦相似度)。
  • 向量数据库 (Vector DB):如 Milvus、Pinecone、Qdrant 等,专门用于高效存储和检索高维向量,是实现 RAG 架构的基石。

2. 自然语言处理 (NLP) 核心范式演进

  • 传统 NLP:分词 (Jieba)、词性标注、命名实体识别 (NER)、情感分析。通常需要针对特定任务训练不同的小模型。
  • 大模型时代 (LLM):范式转变为 "Pre-training + Prompting"。一个基座大模型(如 GPT-4, DeepSeek)通过不同的 Prompt 即可完成翻译、总结、信息提取、代码生成等绝大部分传统 NLP 任务。

3. 大模型应用核心技术 (面试高频重点)

3.1 Prompt Engineering (提示词工程)

  • Zero-shot (零样本):直接提问,完全依赖模型原有预训练知识。
  • Few-shot (少样本):在 Prompt 中提供几个输入输出示例,让模型 "照猫画虎",能大幅提升输出格式的稳定性和业务准确率。
  • CoT (Chain of Thought, 思维链):在 Prompt 中加入类似 "请一步步思考 (Let's think step by step)" 的指令,强制引导模型输出中间推理过程,显著提升复杂逻辑推理的准确率。

3.2 RAG (Retrieval-Augmented Generation, 检索增强生成)

  • 解决的痛点:大模型的知识幻觉(胡说八道)、知识滞后(无法实时联网)、企业私有数据泄露风险(不能把机密发给公有云微调)。
  • 核心流程 (必备话术):
    1. 文档加载与切分 (Chunking):读取企业私有文档(PDF/Word),并切分为合适的文本块。
    2. 向量化与存储 (Embedding & Store):将文本块通过 Embedding 模型转化为向量,存入向量数据库。
    3. 检索 (Retrieval):用户提问时,将问题也向量化,去向量库中检索 Top-K 最相似的文本块。
    4. 生成 (Generation):将检索到的文本块作为背景上下文(Context)拼接进 Prompt,交给大模型生成最终答案。

3.3 Agent (智能体)

  • 核心思想:LLM 充当大脑(负责思考与规划),配备 Memory(记忆)、Tools(工具/API,如联网搜索、查数据库、执行代码),让大模型能够自主拆解并执行复杂任务。
  • 主流框架生态:LangChain、LlamaIndex 等。

4. 前端 AI 交互落地实战 (你的主场)

  • 流式输出 (Streaming) 优化:大模型生成速度慢(TTFT - Time To First Token),必须采用 SSE (Server-Sent Events) 实现打字机效果,大幅降低用户体感等待时间。
  • Markdown 与富文本健壮性渲染:处理 LLM 实时返回的 Markdown 格式流,解决复杂代码块的高亮、数学公式 (LaTeX) 渲染以及流式输出过程中的 HTML/Markdown 标签残缺不闭合导致的页面崩溃问题。
  • 多轮对话的上下文管理:前端如何高效维护 Context Window(会话历史),以及在超过 Token 限制时,如何利用滑动窗口或请求 LLM 生成摘要(Summary)来压缩上下文。
Last Updated:
Contributors: rain9