自我面试
结合简历内容,以 STAR 法则(背景-任务-行动-结果)组织回答
大疆用户中心重构
1、如何性能优化
回答方向:从浏览器请求链路全面分析,覆盖网络层、资源加载、渲染优化三个维度
示例回答:
用户中心服务 1000W+ 注册用户,日均登录 120W+,性能直接影响登录转化率。我从以下维度进行优化:
网络层优化:
- 开启 TLS 1.3 + 会话复用:减少握手往返(收益与网络 RTT/是否复用强相关)
- 对关键域名使用
preconnect(DNS+TCP+TLS)/dns-prefetch(仅 DNS),减少后续关键请求等待 - 开启 gzip/brotli 压缩,资源体积减少 60%+
资源加载优化:
- 关键 CSS 内联到 HTML,减少渲染阻塞
- JS 代码分割 + 动态 import(),首屏 JS 减少 40%
- 图片使用 WebP 格式 + 懒加载,带兼容性兜底方案
渲染优化:
- 骨架屏/首屏占位:提升 FCP 与“感知速度”,并通过布局一致性降低 CLS
- 合理的资源加载顺序(关键资源优先)
结果:LCP 优化 28.9%,首屏加载 < 1.5s,登录转化率提升 18%
补充要点(容易被追问):
- 指标口径:LCP/CLS 来自 RUM(Web-Vitals 上报)还是 Lighthouse?对比周期、样本量、95 分位还是均值。
- 归因方法:先用 Performance/Lighthouse/Network 确认瓶颈在“下载/主线程/渲染/三方脚本”,再做针对性手术。
- 风险控制:每个优化都要看 CLS 是否变差、错误率是否上升(例如懒加载/预加载策略)。
可扩展追问:
- 你怎么定位“LCP 慢”的根因?(资源优先级、阻塞 CSS、主线程 Long Task、图片解码/尺寸等)
- 你怎么做 A/B 或灰度验证?如何避免“实验污染”(缓存、地域、设备差异)?
- brotli 和 gzip 如何选择?CDN/网关怎么配?
2、webpack 如何配置性能优化
回答方向:构建优化 + 输出优化 + 运行时优化
示例回答:
// 说明:面试时用“关键配置片段”即可,不必贴完整 webpack.config.js
module.exports = {
output: {
filename: '[name].[contenthash:8].js',
chunkFilename: '[name].[contenthash:8].js'
},
cache: { type: 'filesystem' },
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/,
type: 'asset',
parser: { dataUrlCondition: { maxSize: 8 * 1024 } }
}
]
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 },
common: { minChunks: 2, priority: -20, reuseExistingChunk: true }
}
},
minimize: true,
minimizer: [new TerserPlugin({ parallel: true })]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
关键点:
- Tree Shaking:确保依赖是 ESM;
sideEffects不建议一刀切为false(CSS 属于副作用),常见做法:sideEffects: ["*.css", "*.scss"]。 - 长缓存:
contenthash+runtimeChunk让运行时代码稳定,减少“小改动全量失效”。 - 体积分析:
webpack-bundle-analyzer定位大包(图标/locale/重复依赖/三方库)。
可扩展追问:
- 你怎么验证 Tree Shaking 生效?(production 模式、sideEffects、观察 bundle 内是否还包含未用导出)
- splitChunks 你怎么分组?如何避免“vendor 过大/公共包抖动”?
- 构建速度怎么提?(持久化缓存、thread-loader、缩小 loader 匹配范围、babel cacheDirectory)
3、如何做响应式融合开发
回答方向:一套代码多端适配的技术方案
示例回答:
背景:用户中心需要同时支持 PC 和移动端,之前是两套代码维护成本高
技术方案:
- 媒体查询 + CSS 变量:定义断点(768px、1024px),使用 CSS 变量控制间距、字体大小
- 响应式组件设计:使用 flex/grid 布局,关键组件根据屏幕尺寸调整显示方式
- 适配逻辑封装:封装
useResponsiveHook,根据window.innerWidth返回当前设备类型 - 图片响应式:使用
<picture>标签 + srcset,按屏幕密度加载不同分辨率图片
// useResponsive Hook 示例
const useResponsive = () => {
const [device, setDevice] = useState(getDevice())
useEffect(() => {
const handler = () => setDevice(getDevice())
window.addEventListener('resize', debounce(handler, 200))
return () => window.removeEventListener('resize', handler)
}, [])
return device // 'mobile' | 'tablet' | 'desktop'
}
2
3
4
5
6
7
8
9
10
结果:一套代码多端适配,维护成本降低 50%
补充要点:
- 设计协作:明确断点与栅格体系(8/12 栅格)、字号/间距 token,避免“每个页面自己适配”。
- 性能:移动端首屏优先,图片/字体策略按设备能力分级(低端机降级动效、减少阴影/滤镜)。
可扩展追问:
- rem/vw/媒体查询你怎么选?为什么?
- 怎么处理表格类复杂页面在移动端的交互?(横向滚动、列折叠、分段展示)
- 如何做兼容性与回归?(设备矩阵、可视回归、关键页面巡检)
4、如何实现更快的加载&渲染速度
回答方向:从 URL 请求到页面可交互的全链路优化
示例回答:
网络层:
- TLS 1.3 减少握手时间
- HTTP/2 多路复用,减少连接数
- CDN 加速静态资源
资源加载:
- 关键 CSS 内联(< 14KB)
- JS 使用 defer 延迟执行,不阻塞 HTML 解析
- 预加载关键字体:
<link rel="preload" as="font" crossorigin>
渲染优化:
- 合理的加载顺序:CSS → 骨架屏 → 关键 JS → 非关键资源
- 避免布局抖动,提前占位
- 使用
will-change需谨慎:只对短时动画启用,避免长期占用合成层导致内存上涨
- 运行时:
- 避免 Long Task(> 50ms),使用
requestIdleCallback处理非紧急任务 - 事件委托 + passive 监听器
- 避免 Long Task(> 50ms),使用
补充要点:
- 资源提示要“可解释”:
preload用在“确定会用且影响首屏”的资源,prefetch用在“下一跳/低优先级”。 - 三方脚本治理:延后加载、隔离失败影响(try/catch + timeout + 降级),避免拉低 TBT/INP。
可扩展追问:
- async/defer 的差异?为什么业务脚本更倾向 defer?
- 你如何降低主线程压力?(拆分长任务、web worker、减少 hydration/重渲染)
- HTTP 缓存怎么配?(cache-control、etag、immutable、CDN 缓存层级)
5、如何实现骨架屏预渲染
回答方向:骨架屏原理 + 实现方式 + 对性能指标的影响
示例回答:
骨架屏作用:
- 快速展示页面结构,避免白屏,提升 FCP
- 减少用户感知等待时间,降低跳出率
- 保持布局稳定,减少 CLS
实现方案(HTML 内联/预渲染注入):
<!-- index.html -->
<div id="app">
<!-- 骨架屏直接内联在 HTML 中 -->
<div class="skeleton">
<div class="skeleton-header"></div>
<div class="skeleton-content"></div>
</div>
</div>
2
3
4
5
6
7
8
.skeleton {
animation: pulse 1.5s infinite;
}
.skeleton-header {
width: 100%;
height: 60px;
background: #e0e0e0;
}
@keyframes pulse {
0%,
100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
关键点:
- 骨架屏 HTML 体积 < 5KB,快速渲染
- 与真实内容布局保持一致,避免 CLS
- 真实内容加载后平滑替换(Vue:
v-if,React: 条件渲染)
结果:弱网下白屏显著减少,FCP 更早;同时通过“关键资源优先级 + 图片/字体策略”等手段推动真实 LCP(如首屏主图/首屏关键块)从 2.3s → 1.4s。
补充要点:
- 骨架屏本身不等于真实 LCP:真实内容出现时 LCP 会重新计算,所以要把“真实 LCP 元素”拉到最前(preload 首屏图/字体、避免阻塞 CSS)。
- CLS 控制:给图片/卡片/列表预留固定高度或
aspect-ratio,避免数据回来“顶开”。
可扩展追问:
- 骨架屏怎么生成/维护?(手写 vs 自动生成 vs SSR 注入,各自优缺点)
- 骨架屏的退出时机怎么设计,避免闪烁?
- 如何证明骨架屏有效?(跳出率、加载中交互、RUM 指标对比)
6、如何减小代码体积
回答方向:构建层面 + 代码层面 + 资源层面
示例回答:
构建层面:
- Tree Shaking:确保使用 ES Module,配置
sideEffects: false - 代码分割:按路由懒加载,动态 import()
- 压缩混淆:TerserPlugin 压缩 JS,CssMinimizerPlugin 压缩 CSS
代码层面:
- 精简 core-js polyfill:
useBuiltIns: 'usage'按需引入 - 替换大型库:lodash → lodash-es(支持 Tree Shaking)
- 移除未使用代码:使用 webpack-bundle-analyzer 分析
资源层面:
- 字体子集化:使用 fontmin 只保留常用汉字(5000 字)
- 图片压缩:WebP 格式,体积减少 30%+
- SVG 精灵图:合并小图标
结果:JS 包体积减少 40%,首屏加载时间显著缩短
可扩展追问:
- polyfill 怎么做到“按需”?(preset-env + targets + usage;以及与业务兼容矩阵的取舍)
- antd/icon/locale 怎么瘦身?(按需引入、替换图标方案、移除多语言包)
- “体积变小但性能没变好”怎么解释?(瓶颈可能在主线程/图片/接口,而不在下载)
大疆售后 RMS 系统重构
1、如何制定 ESLint 规范
回答方向:规范意义 + 规则选择 + 落地策略
示例回答:
背景:RMS 系统 100+ 页面,多人协作开发,代码风格不统一,Review 成本高
规范制定策略:
站在巨人肩膀上:基于 Umi/Ant Design 官方 ESLint 配置,减少从零制定成本
分层规则:
- 强制(error):可能导致 Bug 的规则(no-unused-vars、no-undef)
- 警告(warn):代码风格类(prefer-const、no-console)
- 关闭(off):与项目实际冲突的规则
渐进式推进:
- 第一阶段:只开启关键规则,存量代码不报错
- 第二阶段:新代码必须符合规范(CI 卡点)
- 第三阶段:逐步修复存量代码
自动化:
- Prettier 统一格式化(缩进、引号、分号)
- husky + lint-staged:commit 前自动检查
- CI 集成:MR 自动运行 ESLint 检查
结果:多人开发代码风格统一,交叉开发提效 30%,Bug 率下降 25%
补充要点:
- Prettier 与 ESLint 分工:Prettier 管格式,ESLint 管质量;避免规则重复导致“打架”。
- 类型规则:TypeScript 项目建议引入
@typescript-eslint,把很多运行时错误提前到编译/静态检查。
可扩展追问:
- 你们怎么处理“存量代码一上 ESLint 就炸”?(分批修、只卡新增、按目录逐步收紧)
- 规则怎么定“error/warn”?有没有你坚持关掉的规则?为什么?
2、低代码平台如何落地
回答方向:低代码核心抽象 + 搭建态/运行态 + 落地策略
示例回答:
背景:RMS 系统大量表单页面(工单、审批),重复开发效率低
低代码架构:
┌─────────────────────────────────────────┐
│ 搭建态(可视化编辑器) │
│ - 拖拽组件、配置属性、绑定数据 │
│ - 实时预览、保存 Schema │
└─────────────────────────────────────────┘
↓ Schema JSON
┌─────────────────────────────────────────┐
│ 运行态(Schema 渲染器) │
│ - 递归渲染组件树 │
│ - 表达式解析({{ formData.name }}) │
│ - 事件绑定、数据联动 │
└─────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
核心实现:
- Schema 设计:统一的 JSON 结构描述页面
{
"componentName": "Form",
"props": { "layout": "vertical" },
"children": [
{
"componentName": "Input",
"props": { "label": "工单号", "field": "orderNo" }
}
]
}
2
3
4
5
6
7
8
9
10
组件物料:基于 Ant Design 封装业务组件,提供配置面板
渲染器:递归遍历 Schema,动态加载组件
落地策略:
- 先在低频变更页面试点,验证可行性
- 逐步扩展到表单、列表、详情页
- 复杂交互仍使用 Pro-Code
结果:页面开发效率 +40%,获低代码大赛特等奖
补充要点:
- Schema 版本化:schema 结构演进要可迁移(migration),避免历史页面无法打开。
- 表达式/脚本安全:白名单 API + 沙箱执行(避免任意代码执行)。
可扩展追问:
- 搭建态与运行态如何解耦?(编辑器不进运行包,避免体积膨胀)
- 复杂联动/校验如何抽象?(规则引擎、依赖图、事件总线)
- 性能怎么保障?(虚拟滚动、按需渲染、缓存、批量更新)
3、如何实现业务组件高可用
回答方向:组件设计原则 + 错误处理 + 版本管理
示例回答:
设计原则:
- 单一职责:每个组件只做一件事
- 接口稳定:Props 设计遵循最小暴露原则
- 向后兼容:新版本不破坏旧接口
高可用保障:
// 1. 错误边界 - 组件级隔离
class ErrorBoundary extends React.Component {
state = { hasError: false }
static getDerivedStateFromError() {
return { hasError: true }
}
render() {
return this.state.hasError ? <Fallback /> : this.props.children
}
}
// 2. 默认值兜底 - 防止 undefined 报错
const UserCard = ({ user = {} }) => <div>{user.name ?? '未知用户'}</div>
// 3. 类型校验 - 开发时发现问题
interface Props {
user: { name: string, id: number };
onSelect?: (id: number) => void;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
版本管理:
- 组件库独立发包,语义化版本(SemVer)
- Breaking Change 必须大版本号递增
- 提供 CHANGELOG 和迁移指南
结果:业务组件复用率 80%+,线上故障率显著降低
可扩展追问:
- 如何做“契约”保证?(Props 类型 + 单测/快照 + Storybook 示例)
- 组件如何做可观测性?(关键交互埋点、错误上报、降级开关)
4、如何建立 Code Review 机制
回答方向:流程设计 + Review 规范 + 工具支持
示例回答:
流程设计:
- 提交规范:Commit Message 遵循 Conventional Commits(feat/fix/chore)
- MR 模板:必须填写改动说明、影响范围、测试情况
- Review 标准:
- 至少 1 人 Approve 才能合并
- 核心模块需要 2 人 Review
- CI 检查通过(ESLint、单元测试、构建)
Review 关注点:
- 正确性:逻辑是否正确,边界条件是否考虑
- 可维护性:代码是否易读、是否有注释
- 性能:是否有明显的性能问题
- 安全:是否有 XSS、敏感信息泄露风险
工具支持:
- GitLab/GitHub MR 模板
- 自动化 CI 检查(ESLint、TypeScript、单测)
- Code Review Checklist 文档
结果:团队 Bug 率下降 25%,代码质量显著提升
可扩展追问:
- Review 怎么避免“卡人/效率低”?(时间盒、OWNER 机制、拆小 MR、自动化检查前置)
- Review checklist 你会关注哪 5 类?(正确性/边界/安全/性能/可维护性)
5、如何输出技术文档
回答方向:文档类型 + 工具选择 + 维护机制
示例回答:
文档体系:
| 类型 | 内容 | 工具 |
|---|---|---|
| 项目文档 | 架构设计、开发规范 | VuePress/Notion |
| API 文档 | 接口定义、参数说明 | Swagger/TypeDoc |
| 组件文档 | 使用示例、Props 说明 | Storybook |
| 变更日志 | 版本记录、Breaking Change | CHANGELOG.md |
最佳实践:
- 代码即文档:TypeScript 类型 + JSDoc 注释自动生成
- 示例驱动:每个组件/API 必须有可运行的示例
- 持续更新:文档更新作为 MR 必检项
结果:新人上手时间缩短 50%,跨团队协作效率提升
可扩展追问:
- 文档如何保持不过期?(文档即代码、MR 必检、定期巡检)
- 什么时候写 ADR(架构决策记录)?怎么写到“可复盘”?
跨平台公告插件系统
1、如何设计跨平台公告插件系统
回答方向:架构设计 + 技术选型 + 核心实现
示例回答:
背景:公司有 5+ 业务系统需要统一的公告能力,各系统技术栈不同(React/Vue/原生)
架构设计:
┌─────────────────────────────────────────┐
│ 公告管理后台(统一配置) │
│ - 公告内容编辑、发布时间、目标系统 │
└─────────────────────────────────────────┘
↓ API
┌─────────────────────────────────────────┐
│ 公告插件 SDK(< 15KB) │
│ - 框架无关(Preact 渲染) │
│ - 多种接入方式(CDN/NPM/Web Component) │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 业务系统 A 业务系统 B 业务系统 C │
│ (React) (Vue) (原生 JS) │
└─────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
技术选型:
- Preact:仅 3KB,兼容 React API,信号机制实现响应式
- Rollup:Tree Shaking 效果好,输出多种格式(UMD/ESM)
- CSS Modules:样式隔离,避免与宿主系统冲突
核心代码:
// 插件入口
class AnnouncementPlugin {
constructor(config) {
this.container = document.createElement('div');
document.body.appendChild(this.container);
}
**补充要点**:
- 插件边界:SDK 只负责“渲染 + 拉取公告 + 基础交互”,权限/投放策略放在服务端,避免多端重复逻辑。
- 缓存与容错:公告数据可本地缓存(带版本号与 TTL),弱网/接口挂了可降级为空。
**可扩展追问**:
- SDK 包体积 < 15KB 你怎么做到的?(依赖控制、tree-shaking、压缩、locale/icon 策略)
- 如何做埋点与灰度?(appId、版本号、命中策略、上报链路)
async init() {
const data = await fetch('/api/announcements');
render(<Announcement data={data} />, this.container);
}
destroy() {
render(null, this.container);
this.container.remove();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2、如何实现跨业务系统接入
回答方向:多种接入方式 + 配置化 + 兼容性
示例回答:
三种接入方式:
- CDN 引入(最简单):
<script src="//cdn.example.com/announcement.umd.js"></script>
<script>
new AnnouncementPlugin({ appId: 'rms', position: 'top' }).init()
</script>
2
3
4
- NPM 安装(React/Vue 项目):
import { AnnouncementPlugin } from '@dji/announcement'
useEffect(() => {
const plugin = new AnnouncementPlugin({ appId: 'rms' })
plugin.init()
return () => plugin.destroy()
}, [])
2
3
4
5
6
- Web Component(框架无关):
<dji-announcement app-id="rms" position="top"></dji-announcement>
配置化设计:
interface PluginConfig {
appId: string // 业务系统标识
position: 'top' | 'modal' | 'float' // 展示位置
theme?: 'light' | 'dark' // 主题
onClose?: () => void // 关闭回调
}
2
3
4
5
6
结果:接入周期 < 0.5 人日/系统,已接入 5 个业务系统
3、如何保证插件系统的高可用性
回答方向:错误隔离 + 降级方案 + 监控告警
示例回答:
错误隔离:
// 1. try-catch 包裹,避免影响宿主系统
class AnnouncementPlugin {
async init() {
try {
const data = await this.fetchData()
this.render(data)
} catch (error) {
console.error('[Announcement] Init failed:', error)
this.reportError(error)
// 静默失败,不影响宿主系统
}
}
}
// 2. 样式隔离 - Shadow DOM(演示用:实际渲染需挂到 shadowRoot)
const host = document.createElement('div')
const shadowRoot = host.attachShadow({ mode: 'open' })
// render(<Announcement />, shadowRoot)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
降级方案:
- API 超时 3s 自动降级,不阻塞页面
- 缓存上次成功的公告数据,离线可用
- 提供
fallback配置,失败时显示静态内容
监控告警:
- 上报初始化成功/失败率
- 监控 API 响应时间
- 错误日志自动告警
结果:紧急公告触达率 100%,零影响宿主系统稳定性
补充要点:
- 错误隔离:SDK 内部错误要“吞掉并上报”,不能让宿主页面白屏/崩溃。
- 资源隔离:CSS(Shadow DOM/CSS Modules)、DOM 容器命名空间、事件监听统一回收。
可扩展追问:
- 如何安全加载第三方脚本?(SRI、CSP、域名白名单、超时与重试)
- destroy 时如何确保无泄漏?(定时器、事件、observer、请求取消、DOM 引用)
4、如何进行独立开发与交付
回答方向:独立仓库 + 版本管理 + 发布流程
示例回答:
项目结构:
announcement-plugin/
├── src/
│ ├── core/ # 核心逻辑
│ ├── components/ # Preact 组件
│ └── index.ts # 入口
├── rollup.config.js # 构建配置
├── package.json
└── CHANGELOG.md
2
3
4
5
6
7
8
构建输出:
// rollup.config.js
export default {
input: 'src/index.ts',
output: [
{
file: 'dist/announcement.umd.js',
format: 'umd',
name: 'AnnouncementPlugin'
},
{ file: 'dist/announcement.esm.js', format: 'es' }
],
plugins: [terser()] // 压缩
}
2
3
4
5
6
7
8
9
10
11
12
13
发布流程:
- 代码 Review + 合并到 main
- 打 Tag 触发 CI 自动构建
- 发布到内部 NPM + CDN
- 更新 CHANGELOG
结果:独立迭代,不依赖业务系统发布周期
大疆 DevOps 系统开发
1、workspace 如何自定义审批流程
回答方向:流程引擎设计 + 配置化 + 状态机
示例回答:
需求背景:不同项目有不同的审批流程,需要可配置
流程引擎设计:
┌─────────────────────────────────────────┐
│ 流程配置(JSON/可视化编辑) │
│ - 节点定义(审批人、条件、动作) │
│ - 流转规则(顺序、并行、条件分支) │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 流程引擎 │
│ - 状态机驱动 │
│ - 事件触发(提交、审批、驳回) │
│ - 超时处理、催办通知 │
└─────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
状态机实现:
interface WorkflowNode {
id: string
type: 'approval' | 'condition' | 'notify'
approvers: string[] // 审批人
nextNodes: { condition?: string; nodeId: string }[]
}
// 状态流转
function transition(currentNode, action) {
if (action === 'approve') {
return findNextNode(currentNode)
} else if (action === 'reject') {
return findPrevNode(currentNode)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
结果:流程审批效率提升,支持 10+ 种审批模板
可扩展追问:
- 流程模型怎么设计?(DAG/状态机/条件分支/并行汇聚)
- 如何保证幂等与可追溯?(实例 ID、操作日志、重放、审计)
2、如何进行系统集成与数据对接
回答方向:Jira 插件开发 + API 对接 + 数据同步
示例回答:
Jira 插件开发:
- 使用 Atlassian Connect 框架开发
- 实现需求与工单的双向同步
- Webhook 监听 Jira Issue 变更
数据对接方案:
┌──────────┐ Webhook ┌──────────┐
│ Jira │ ───────────────→ │ DevOps │
│ │ ←─────────────── │ │
└──────────┘ REST API └──────────┘
2
3
4
同步策略:
- 增量同步:监听变更事件,实时同步
- 全量同步:定时任务,每日对账
- 冲突处理:以源系统为准,记录冲突日志
结果:打通需求与工单流程,减少手动操作
可扩展追问:
- Webhook 怎么验签与防重放?(签名、timestamp、nonce)
- 如何做限流与失败重试?(退避、DLQ、对账任务)
3、如何保障系统的安全性
回答方向:权限控制 + 数据安全 + 审计日志
示例回答:
权限控制:
- RBAC 模型:角色(Admin/Developer/Viewer)+ 权限(Read/Write/Delete)
- 资源级权限:项目维度、模块维度细粒度控制
- 前端路由守卫 + 后端接口鉴权双重校验
数据安全:
- 敏感信息加密存储(Token、密钥)
- HTTPS 传输,防止中间人攻击
- XSS/CSRF 防护
审计日志:
- 记录关键操作(登录、配置变更、发布)
- 支持日志查询和导出
- 异常行为告警
可扩展追问:
- 前端安全你最关注哪几类?(XSS/CSRF/点击劫持/敏感信息泄露)你怎么做?
- RBAC 如何落地到“资源级/字段级”?如何做权限缓存与一致性?
4、如何进行系统的持续优化
回答方向:监控体系 + 性能优化 + 用户反馈
示例回答:
监控体系:
- 前端监控:错误上报、性能指标(FCP/LCP/CLS)
- 接口监控:响应时间、成功率
- 业务监控:核心流程转化率
持续优化:
- 定期分析监控数据,识别性能瓶颈
- 用户反馈收集,优先处理高频问题
- A/B 测试验证优化效果
结果:测试用例平台满意度显著提升
可扩展追问:
- 你们的 SLI/SLO 是什么?(成功率、95 线延迟、错误率)怎么驱动排期?
- 监控到问题后怎么闭环?(定位-修复-复盘-预防)
XDR 系统 - 魔方大屏 + 报表
1、如何设计魔方大屏系统架构
回答方向:低代码架构 + 组件设计 + 数据流
示例回答:
架构设计:
┌─────────────────────────────────────────┐
│ 可视化编辑器(搭建态) │
│ - 拖拽组件、配置数据源、调整布局 │
└─────────────────────────────────────────┘
↓ Schema
┌─────────────────────────────────────────┐
│ 渲染引擎(运行态) │
│ - Schema 解析、组件渲染、数据绑定 │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 数据服务层(NestJS) │
│ - 数据聚合、定时任务、缓存 │
└─────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
组件设计:
- 图表组件:折线图、柱状图、饼图(基于 ECharts)
- 数据组件:数字卡片、表格、进度条
- 布局组件:容器、栅格、Tab
数据流:
- 组件通过
dataSourceId绑定数据源 - 渲染引擎根据 Schema 获取数据并渲染
- 支持实时数据(WebSocket)和定时刷新
可扩展追问:
- Schema 如何做“版本 + 迁移 + 校验”?
- 如何做撤销/重做与多选拖拽?(命令模式/历史栈)
- 实时数据怎么控频?(节流、合并更新、只更新可见组件)
2、如何实现数据可视化展示
回答方向:ECharts 封装 + 响应式 + 性能优化
示例回答:
ECharts 组件封装:
const ChartComponent: React.FC<Props> = ({ type, data, options }) => {
const chartRef = useRef<HTMLDivElement>(null)
const chartInstance = useRef<echarts.ECharts>()
useEffect(() => {
chartInstance.current = echarts.init(chartRef.current)
return () => chartInstance.current?.dispose()
}, [])
useEffect(() => {
const option = generateOption(type, data, options)
chartInstance.current?.setOption(option)
}, [type, data, options])
// 响应式
useEffect(() => {
const handleResize = () => chartInstance.current?.resize()
window.addEventListener('resize', handleResize)
return () => window.removeEventListener('resize', handleResize)
}, [])
return <div ref={chartRef} style={{ width: '100%', height: '100%' }} />
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
性能优化:
- 大数据量使用
dataset+dataZoom - 开启
large模式处理万级数据点 - 使用
canvas渲染器(默认),SVG 用于导出
可扩展追问:
- 万级数据为什么还能秒开?(抽样/下采样、增量 setOption、避免频繁 resize)
- 图表组件如何避免内存泄漏?(dispose、事件解绑、observer 清理)
3、如何进行报表系统开发
回答方向:NestJS 全栈 + 定时任务 + 多格式导出
示例回答:
NestJS 后端架构:
// 报表模块
@Module({
imports: [ScheduleModule.forRoot()],
controllers: [ReportController],
providers: [ReportService, ReportScheduler]
})
export class ReportModule {}
// 定时任务
@Injectable()
export class ReportScheduler {
@Cron('0 8 * * *') // 每天 8 点
async generateDailyReport() {
const data = await this.reportService.aggregateData()
await this.reportService.generateAndSend(data)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
多格式导出:
- PDF:使用 Puppeteer 渲染 HTML 后导出
- PPT:使用 PptxGenJS 库生成
- Excel:使用 ExcelJS 生成
结果:报表自动生成,支持邮件推送
可扩展追问:
- 定时任务如何保证可靠性?(幂等、分布式锁、失败重试、任务状态持久化)
- 导出链路如何避免阻塞主服务?(队列、异步 worker、限流)
4、如何保障系统的稳定性
回答方向:错误处理 + 监控告警 + 容灾
示例回答:
错误处理:
- 前端:Error Boundary 捕获组件错误
- 后端:全局异常过滤器,统一错误响应
- 接口:超时重试、降级策略
监控告警:
- 服务健康检查(/health 端点)
- 错误日志聚合分析
- 关键指标告警(响应时间 > 3s、错误率 > 1%)
容灾设计:
- 数据库读写分离
- Redis 缓存热点数据
- 服务多实例部署
可扩展追问:
- 你怎么设计超时/重试/熔断?(避免雪崩)
- 灰度发布怎么做?如何回滚?
5、如何进行系统的性能优化
回答方向:前端性能 + 后端性能 + 数据库优化
示例回答:
前端性能:
- 大屏组件懒加载,按需渲染
- ECharts 实例复用,避免重复创建
- 虚拟滚动处理大量数据
后端性能:
- 数据预聚合,定时任务计算报表数据
- Redis 缓存高频查询结果
- 接口限流防止过载
数据库优化:
- MongoDB 索引优化
- 聚合管道优化查询
- 历史数据归档
结果:万级数据秒开,报表生成效率大幅提升
可扩展追问:
- Redis 缓存如何设计键与 TTL?如何处理缓存击穿/雪崩?
- MongoDB 索引怎么选?如何用 explain 分析慢查询?
