前言
大家好,我是木斯佳。
相信很多人都感受到了,在AI浪潮的席卷之下,前端领域的门槛在变高,纯粹的"增删改查"岗位正在肉眼可见地减少。曾经热闹非凡的面经分享,如今也沉寂了许多。但我们都知道,市场的潮水退去,留下的才是真正在踏实准备、努力沉淀的人。学习的需求,从未消失,只是变得更加务实和深入。
这个专栏的初衷很简单:拒绝过时的、流水线式的PDF引流贴,专注于收集和整理当下最新、最真实的前端面试资料。我会在每一份面经和八股文的基础上,尝试从面试官的角度去拆解问题背后的逻辑,而不仅仅是提供一份静态的背诵答案。无论你是校招还是社招,目标是中大厂还是新兴团队,只要是真实发生、有价值的面试经历,我都会在这个专栏里为你沉淀下来。专栏快速链接

温馨提示:市面上的面经鱼龙混杂,甄别真伪、把握时效,是我们对抗内卷最有效的武器。
面经原文内容
📍面试公司:影刀
🕐面试时间:近期
💻面试岗位:AI前端一面
📝面试背景:4年前端,有AI行业工作经历
❓面试问题:
- 为什么会有给AI用的sandbox,它的出现是为了解决什么问题?有没有用过sandbox?
- llm playground深挖
- sse和socket的区别,为什么用sse做流式而不是socket
- 假设你现在在用这个playground和AI进行对话,发送按钮点击了,此时模型在不断的一个字一个字的蹦出来,在这个流式输出的过程中,我刷新了页面或者切了一下对话再切回来,这个时候作为用户我肯定希望对话是继续的,这种场景你是怎么处理的?后续面试官补充:sse不是socket,在断掉之后,是没有重连这个概念的,你是怎么保证断了之后还能继续的?
- 模型在输出的时候,用户可以随时点击停止按钮让模型停下来,你是怎么设计中止这部分的功能的?前端会不会把fetch取消掉?如果只是前端取消掉,后端不是还在sse吗?怎么处理的?
- 给llm的tool是前端实现的吗?你们是怎样去调用web search的?
- 上面聊了这么多,你有参与过agent的开发吗?你对llm本身的运行过程了解吗?
- 用户的输出VS模型的输入,多模态模型的消息和普通的纯文本的消息有什么区别吗?
- 为什么你需要用到swr?为什么会有请求缓存?
- 你项目里写了国际化,你是怎么做国际化的?
- 接上一条,假设有一个论坛,是全球可用的,你发了一条帖子,是中文的,这个时候我在海外,我希望能看到英文,如果是你,你会怎么设计?
- 后端翻译的时机是什么时候?
- 如果有同样的文本,后端难道每一次都要翻译吗?怎么优化?因为论坛的实时性,如果你缓存了,但我还是得调接口才能拿到新的,那缓存还有必要么?
来源:牛客网 秋盈丶
💡 木木有话说(刷前先看)
这是一份"含金量"极高的面经,不是因为题难,而是因为每道题都切中AI前端生产的核心痛点。用户自述"惨不忍睹",但能聊四五十分钟,说明面试官很感兴趣。问题覆盖:沙箱安全、SSE断线恢复、中止生成、多模态、国际化缓存......全是真实场景。如果你也在做AI前端,这份面经是绝佳的"实战演练",建议一道一道跟着思考。
📝 影刀AI前端一面·深度解析
🎯 面试整体画像
| 维度 | 特征 |
|---|---|
| 面试风格 | 场景驱动型 + 深挖细节型 + 系统设计型 |
| 难度评级 | ⭐⭐⭐⭐⭐(五星,实战难题,考察系统设计) |
| 考察重心 | AI沙箱安全、SSE断线恢复、中止生成、多模态、国际化缓存 |
| 特殊之处 | 每道题都是AI应用的真实痛点,考察"能不能落地" |
🔍 逐题深度解析
一、AI沙箱(Sandbox)的作用与使用
回答思路:沙箱是AI应用中的关键安全组件。LLM可以生成代码并执行,沙箱提供一个隔离环境,防止恶意代码影响主程序或访问系统资源。
为什么需要沙箱:
- 安全隔离:防止AI生成的代码执行危险操作(删除文件、网络攻击)
- 资源限制:限制CPU、内存、网络访问,防止无限循环耗尽资源
- 环境可控:提供一致的执行环境,避免依赖冲突
使用场景:
- AI执行代码(Python/JavaScript代码运行)
- AI调用工具(浏览器、计算器、数据库查询)
- AI操作外部系统(发送邮件、操作文件)
实现方式:
- Web Worker:隔离JS执行环境,不能访问DOM
- iframe沙箱 :
<iframe sandbox>属性,限制表单、脚本、弹窗 - 服务端容器:Docker、gVisor,进程级隔离
javascript
// Web Worker作为轻量沙箱
const worker = new Worker('sandbox.js')
worker.postMessage({ code: userCode })
worker.onmessage = (e) => console.log(e.data)
worker.onerror = (e) => console.error('沙箱错误', e)
二、LLM Playground深挖
回答思路:这里没有具体问题,但面试官会围绕你做的Playground项目展开,考察技术选型、交互设计、性能优化。建议准备:
- 技术栈:Monaco Editor(代码编辑器)、SSE(流式输出)、Markdown渲染
- 核心功能:参数调节(temperature、top_p)、多模型切换、对话历史管理
- 难点:大模型输出慢、长文本渲染、历史记录持久化
三、SSE和WebSocket的区别,为什么用SSE做流式
回答思路:参考之前多次解析的SSE vs WebSocket对比。
核心区别:
- 通信方向:SSE单向(服务端→客户端),WebSocket双向
- 协议:SSE基于HTTP,WebSocket独立协议(ws/wss)
- 自动重连:SSE内置,WebSocket需手动实现
为什么AI流式选SSE:
- 方向匹配:AI生成是服务端到客户端的单向流,不需要双向
- 实现简单:SSE基于HTTP,无需协议升级,兼容性好
- 自动重连:网络波动时自动恢复(虽然面试官说"SSE没有重连概念",但标准SSE确实有自动重连机制)
- 资源开销小:比WebSocket轻量
javascript
// SSE客户端
const eventSource = new EventSource('/api/stream')
eventSource.onmessage = (e) => console.log(e.data)
四、SSE断线后如何恢复对话
回答思路:这是AI对话的真实痛点。用户刷新页面或切换对话后,希望之前的回复还在,且能继续。
解决方案 :消息持久化 + 断点续传
前端设计:
- 存储消息:每收到一个chunk,存入localStorage/IndexedDB,或通过API同步到服务端
- 会话恢复:页面加载时,从存储中恢复消息列表,并记录"最后一条未完成的消息"
- 续传请求 :携带
lastMessageId参数,请求服务端从断点继续发送
javascript
// 消息结构
{
id: 'msg_123',
content: '已收到的部分内容',
status: 'streaming', // 'complete' | 'streaming' | 'error'
chunks: ['Hello', ' world']
}
// 恢复连接
function resumeConversation(conversationId, lastMessageId) {
const eventSource = new EventSource(`/api/stream?resume=true&lastId=${lastMessageId}`)
eventSource.onmessage = (e) => {
// 追加新chunk到已有消息
appendToMessage(lastMessageId, e.data)
}
}
服务端支持:
- 缓存每个会话的生成状态(generation state)
- 支持
?resume参数,从断点继续推送
五、中止生成的设计
回答思路:用户点击停止按钮,需要同时取消前端请求和后端生成。
前端实现:
javascript
let abortController = new AbortController()
async function generate() {
try {
const response = await fetch('/api/stream', {
signal: abortController.signal
})
// 处理流式数据
} catch (err) {
if (err.name === 'AbortError') {
console.log('用户主动停止')
}
}
}
function stop() {
abortController.abort()
abortController = new AbortController() // 重置
}
后端处理:
- 前端取消fetch,只是浏览器不再接收响应,后端的SSE生成不会自动停止
- 需要前端发送一个"停止信号"给后端(如单独的HTTP请求
POST /api/stop,带上会话ID) - 后端收到信号后,中断LLM生成,关闭SSE连接
javascript
// 停止生成
async function stopGeneration(sessionId) {
await fetch('/api/stop', {
method: 'POST',
body: JSON.stringify({ sessionId })
})
abortController.abort()
}
六、Tool Calling是前端实现的吗?Web Search怎么调用
回答思路:Tool Calling(函数调用)是模型决定调用工具的能力,前后端配合完成。
流程:
- 用户提问:"今天天气怎么样?"
- 模型返回函数调用:
{ name: 'get_weather', args: { city: '北京' } } - 前端解析函数调用,调用真实API(天气接口)
- 前端将结果返回给模型
- 模型生成最终回答
Web Search调用:
- 可以是前端直接调用搜索API(如Bing Search API),也可以是后端代理
- 前端调用时需注意API Key安全(应走后端代理)
javascript
// 前端处理函数调用
if (response.function_call) {
const { name, args } = response.function_call
if (name === 'web_search') {
const results = await fetch(`/api/search?q=${args.query}`)
// 将结果返回给模型
continueConversation(results)
}
}
七、Agent开发和LLM运行过程
回答思路:Agent是能自主规划、调用工具、完成复杂任务的AI。
LLM运行过程:
- 输入处理:Tokenization(分词),将文本转成Token ID
- 模型推理:Token ID → Embedding → Transformer层 → 概率分布
- 采样:根据温度(temperature)、Top-K、Top-P选择下一个Token
- 迭代:重复直到生成结束或达到最大长度
Agent开发要点:
- 规划:将复杂任务拆解成步骤
- 记忆:短期记忆(对话历史)+ 长期记忆(向量数据库)
- 工具使用:模型选择工具,前端/后端执行
- 反思:根据执行结果调整计划
八、多模态消息 vs 纯文本消息的区别
回答思路:多模态模型可以处理文本、图像、音频等多种输入。
消息结构差异:
javascript
// 纯文本消息
{ role: 'user', content: '描述这张图片' }
// 多模态消息(OpenAI格式)
{
role: 'user',
content: [
{ type: 'text', text: '描述这张图片' },
{ type: 'image_url', image_url: { url: 'https://...' } }
]
}
前端处理差异:
- 上传图片 → 转Base64或URL
- 构造多模态content数组
- 渲染时需支持图片、视频等富媒体
九、为什么用SWR,为什么需要请求缓存
回答思路:SWR(stale-while-revalidate)是数据请求库,核心是缓存和重新验证。
为什么需要缓存:
- 减少请求:相同数据不重复请求
- 提升体验:先展示缓存,后台更新
- 节省带宽:减少数据传输
SWR在AI场景的应用:
- 缓存模型列表、历史对话摘要、配置参数
- 用户快速切换对话时,先展示缓存,再请求最新
javascript
const { data } = useSWR('/api/conversations', fetcher, {
revalidateOnFocus: false, // 不自动刷新
dedupingInterval: 60000 // 60秒内去重
})
十、国际化(i18n)的实现
回答思路:参考之前面经的i18n解析。
基础实现:
javascript
import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
i18n.use(initReactI18next).init({
resources: {
en: { translation: { 'welcome': 'Welcome' } },
zh: { translation: { 'welcome': '欢迎' } }
},
lng: 'zh'
})
进阶:动态加载语言包、命名空间、变量插值、日期格式化。
十一、论坛帖子的国际化设计(中文→英文)
回答思路:用户发中文帖,海外用户希望看英文。核心是"何时翻译、如何缓存"。
设计方案:
- 用户发帖时:存储原文(中文),同时调用翻译API生成英文版本,一并存储
- 用户阅读时:根据用户语言偏好返回对应版本(已翻译好的)
- 前端显示:直接显示服务端返回的内容
优点 :实时性好,阅读时无翻译延迟
缺点:存储成本翻倍,发帖时略慢
十二、后端翻译的时机
回答思路:翻译时机影响实时性和成本。
三种时机:
- 写入时翻译(推荐):用户发帖后立即翻译并存储,阅读时直接返回。适合帖子内容不频繁修改的场景。
- 读取时翻译:阅读时实时翻译,适合内容实时变化(如聊天室)
- 异步翻译:写入后放入队列,异步翻译后更新,适合大量内容
论坛推荐:写入时翻译 + 缓存翻译结果。
十三、翻译缓存的必要性与优化
回答思路:相同文本重复翻译浪费资源,缓存很有必要。但论坛内容实时更新,需平衡。
缓存策略:
- 内容哈希作为Key:相同文本直接复用翻译
- 设置合理TTL:如24小时,超时后重新翻译(应对内容审核规则变化)
- 主动失效:帖子编辑后,删除对应缓存
- 分级缓存:热门内容优先缓存,冷门内容实时翻译
为什么缓存仍然必要:
- 相同文本(如"你好"、"谢谢")可能出现无数次
- 即使帖子是新的,其中的常用短语可以复用缓存
- 大幅降低翻译API调用成本
javascript
// 缓存结构
translationCache = {
'你好': { en: 'Hello', ttl: Date.now() + 86400000 },
'谢谢': { en: 'Thanks', ttl: Date.now() + 86400000 }
}
📚 知识点速查表
| 知识点 | 核心要点 |
|---|---|
| AI沙箱 | 安全隔离、资源限制,Web Worker/iframe/Docker实现 |
| SSE vs WebSocket | 单向/双向、协议、自动重连、AI场景选SSE原因 |
| SSE断线恢复 | 消息持久化 + 断点续传,服务端缓存生成状态 |
| 中止生成 | AbortController + 后端停止信号,前后端协同 |
| Tool Calling | 模型返回函数名+参数,前端/后端执行真实调用 |
| Agent | 规划+记忆+工具+反思,自主完成复杂任务 |
| 多模态消息 | content数组支持text/image_url,结构不同于纯文本 |
| SWR/缓存 | 减少请求、提升体验、AI场景缓存模型列表/配置 |
| 国际化 | i18n配置、动态加载、变量插值 |
| 论坛翻译 | 写入时翻译、内容哈希缓存、TTL失效 |
| 翻译优化 | 相同文本复用、分级缓存、热门优先 |
📌 最后一句:
影刀这场AI一面,是我见过的最贴近AI生产实际 的面经之一。从沙箱安全到SSE断线恢复,从中止生成到多模态消息,每一道题都是真实业务中会遇到的挑战。用户自述"惨不忍睹",但能聊四五十分钟,恰恰说明面试官对这些问题的兴趣。AI前端开发,不再是调个API渲染一下那么简单了------你需要懂安全、懂网络、懂缓存、懂系统设计。