前端架构设计
前端面试题 - 前端架构设计篇
本章节收录前端架构设计相关面试题,涵盖微前端、组件库设计、低代码平台、性能监控、工程化架构等高级话题。适合前端架构师和高级工程师面试准备。
📊 数据统计
| 统计项 | 数值 |
|---|---|
| 总题数 | 50道 |
| 基础题 | 10道 (20%) |
| 中级题 | 22道 (44%) |
| 高级题 | 18道 (36%) |
📚 目录
一、微前端架构
1. 什么是微前端?解决了什么问题?
难度:⭐⭐(中级)
标签:#微前端 #架构
参考答案要点:
定义:微前端是一种架构风格,将前端应用拆分为多个独立部署的小型应用,再由主应用集成。
解决的问题:
| 问题 | 说明 |
|---|---|
| 技术栈无关 | 不同团队可使用不同技术栈(React/Vue/Angular) |
| 独立部署 | 各微应用可独立开发、测试、部署 |
| 团队自治 | 减少团队间依赖,提升开发效率 |
| 渐进升级 | 可逐步重构老系统,而非一次性重写 |
| 代码复用 | 共享组件和工具函数 |
实现方案:
- iframe
- Web Components
- Module Federation
- qiankun/single-spa
2. 微前端的实现方案有哪些?各自的优缺点?
难度:⭐⭐⭐(高级)
标签:#微前端 #方案对比
参考答案要点:
| 方案 | 优点 | 缺点 | 代表 |
|---|---|---|---|
| iframe | 简单、隔离性好 | 体验差、通信困难、SEO 不友好 | 传统方案 |
| Web Components | 标准化、隔离性好 | 兼容性、生态不成熟 | LitElement |
| Module Federation | 共享依赖、体验好 | 技术栈需统一(Webpack) | Webpack 5 |
| qiankun | 成熟、易用、技术栈无关 | 沙箱有性能损耗 | 蚂蚁开源 |
| single-spa | 灵活、生态丰富 | 配置复杂 | 社区方案 |
| 无界 | 原生隔离、性能好 | 较新、生态待完善 | 腾讯开源 |
选型建议:
- 简单场景:iframe
- Webpack 项目:Module Federation
- 多技术栈:qiankun
- 追求性能:无界
3. qiankun 的实现原理是什么?
难度:⭐⭐⭐⭐(专家)
标签:#qiankun #微前端
参考答案要点:
核心原理:
主应用(基座)
↓
├─ 路由拦截(判断加载哪个微应用)
├─ 加载微应用 HTML/JS/CSS
├─ JS 沙箱(Proxy 代理 window)
├─ CSS 沙箱(Shadow DOM / 样式隔离)
└─ 生命周期管理(bootstrap/mount/unmount)JS 沙箱实现:
// 简化版沙箱
class ProxySandbox {
constructor() {
this.fakeWindow = {}
this.proxy = new Proxy(window, {
get(target, key) {
return this.fakeWindow[key] || target[key]
},
set(target, key, value) {
this.fakeWindow[key] = value
return true
},
})
}
active() {
// 激活沙箱
}
inactive() {
// 失活沙箱,清理副作用
}
}CSS 隔离方案:
- Shadow DOM:真正的隔离
- CSS Module:类名哈希
- Dynamic Stylesheet:动态添加/移除样式
4. Module Federation 的实现原理是什么?
难度:⭐⭐⭐⭐(专家)
标签:#ModuleFederation #Webpack
参考答案要点:
核心概念:
Host(宿主应用)
↓
加载 Remote(远程应用)暴露的模块
↓
共享依赖(Shared Dependencies)配置示例:
// 远程应用(Remote)
// webpack.config.js
const { ModuleFederationPlugin } = require("webpack").container
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "app2",
filename: "remoteEntry.js",
exposes: {
"./Button": "./src/Button",
"./utils": "./src/utils",
},
shared: ["react", "react-dom"],
}),
],
}
// 宿主应用(Host)
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: "app1",
remotes: {
app2: "app2@http://localhost:3002/remoteEntry.js",
},
shared: ["react", "react-dom"],
}),
],
}
// 使用
const Button = React.lazy(() => import("app2/Button"))原理:
- 远程应用打包时暴露模块
- 宿主应用运行时加载远程应用的
remoteEntry.js - 通过全局变量获取远程模块
- 共享依赖避免重复加载
5. 微前端如何共享状态?
难度:⭐⭐⭐(高级)
标签:#微前端 #状态管理
参考答案要点:
方案对比:
| 方案 | 适用场景 | 实现方式 |
|---|---|---|
| URL 参数 | 简单数据 | ?userId=123 |
| CustomEvent | 事件通信 | window.dispatchEvent |
| 全局状态 | 复杂应用 | Redux/Vuex + 持久化 |
| Props 传递 | 父子关系 | 主应用传递 |
| 发布订阅 | 解耦通信 | EventBus |
推荐方案:
// 全局状态管理(推荐)
// 主应用创建 Store
import { createStore } from 'redux'
const globalStore = createStore(reducer)
// 通过 props 传递给微应用
<MicroApp store={globalStore} />
// 微应用接收并使用
function MicroApp({ store }) {
store.subscribe(() => {
console.log(store.getState())
})
}二、组件库设计
6. 如何设计一个组件库?
难度:⭐⭐⭐(高级)
标签:#组件库 #设计
参考答案要点:
设计原则:
- 单一职责:每个组件只做一件事
- 可复用性:props 配置,支持多种场景
- 可扩展性:支持自定义样式和行为
- 一致性:API 设计统一
- 可访问性:支持键盘导航、屏幕阅读器
目录结构:
my-ui/
├── src/
│ ├── components/ # 组件
│ │ ├── Button/
│ │ │ ├── Button.tsx
│ │ │ ├── Button.vue
│ │ │ ├── style.css
│ │ │ └── index.ts
│ │ └── Input/
│ ├── styles/ # 公共样式
│ ├── utils/ # 工具函数
│ └── index.ts # 入口
├── docs/ # 文档
├── tests/ # 测试
├── package.json
└── vite.config.ts技术选型:
- 框架:Vue 3 / React 18
- 构建:Vite / Rollup
- 样式:CSS Variable / SCSS
- 文档:Storybook / VitePress
- 测试:Vitest / Jest
7. 组件库如何实现主题定制?
难度:⭐⭐⭐(高级)
标签:#组件库 #主题
参考答案要点:
方案一:CSS 变量(推荐)
:root {
--primary-color: #1890ff;
--border-radius: 4px;
--font-size-base: 14px;
}
.btn {
background: var(--primary-color);
border-radius: var(--border-radius);
}方案二:SCSS 变量
// _variables.scss
$primary-color: #1890ff !default;
$border-radius: 4px !default;
// 用户覆盖
@import "~my-ui/styles/variables";
$primary-color: #ff4d4f;
@import "~my-ui/styles/index";方案三:CSS-in-JS
const theme = {
primaryColor: "#1890ff",
borderRadius: "4px",
}
const Button = styled.button`
background: ${(props) => props.theme.primaryColor};
`8. 组件库如何实现按需加载?
难度:⭐⭐⭐(高级)
标签:#组件库 #按需加载
参考答案要点:
方案一:ES Module(推荐)
// 用户按需引入
import { Button, Input } from "my-ui"
// 构建工具自动 Tree-shaking方案二:Babel 插件
// .babelrc
{
"plugins": [
["import", {
"libraryName": "my-ui",
"libraryDirectory": "es",
"style": true // 自动引入样式
}]
]
}
// 源码
import { Button } from 'my-ui'
// 编译后
import Button from 'my-ui/es/button'
import 'my-ui/es/button/style'方案三:手动按需引入
import Button from "my-ui/lib/button"
import "my-ui/lib/button/style.css"三、低代码平台
9. 低代码平台的核心设计思路是什么?
难度:⭐⭐⭐(高级)
标签:#低代码 #架构
参考答案要点:
核心概念:
- 可视化设计:拖拽组件生成页面
- 数据驱动:JSON Schema 定义页面结构
- 代码生成:可视化配置生成代码
- 扩展能力:支持自定义组件和逻辑
架构分层:
┌─────────────────────────────────────┐
│ 设计器(Designer) │
│ ┌─────────┐ ┌─────────┐ ┌────────┐ │
│ │ 组件面板 │ │ 画布区 │ │ 属性面板│ │
│ └─────────┘ └─────────┘ └────────┘ │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 渲染器(Renderer) │
│ 解析 JSON Schema 渲染页面 │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ 运行时(Runtime) │
│ 状态管理、事件处理、API 调用 │
└─────────────────────────────────────┘核心模块:
- 物料系统:组件注册、分类、版本管理
- Schema 协议:页面配置标准格式
- 设计器引擎:拖拽、选中、撤销重做
- 代码生成器:可视化配置转代码
- 扩展系统:自定义组件、插件
10. 低代码平台的 Schema 如何设计?
难度:⭐⭐⭐⭐(专家)
标签:#低代码 #Schema
参考答案要点:
Schema 结构:
{
"type": "page",
"title": "用户管理",
"body": [
{
"type": "form",
"api": "/api/users",
"body": [
{
"type": "input-text",
"name": "username",
"label": "用户名",
"required": true
},
{
"type": "input-number",
"name": "age",
"label": "年龄"
}
]
},
{
"type": "table",
"source": "${users}",
"columns": [
{ "name": "id", "label": "ID" },
{ "name": "username", "label": "用户名" }
]
}
]
}设计原则:
- 声明式:描述做什么,而非怎么做
- 可扩展:支持自定义组件类型
- 可校验:JSON Schema 校验
- 可转换:支持导入/导出代码
11. 低代码平台如何支持自定义逻辑?
难度:⭐⭐⭐⭐(专家)
标签:#低代码 #扩展
参考答案要点:
方案对比:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 可视化逻辑编排 | 易用 | 复杂逻辑受限 |
| 代码编辑器 | 灵活 | 需要编程能力 |
| JS 表达式 | 平衡 | 安全性问题 |
推荐方案:
// JS 表达式(推荐)
{
"type": "button",
"label": "提交",
"onClick": "${submitForm()}",
"visible": "${form.status === 'draft'}"
}
// 安全沙箱执行
function safeEval(expression, context) {
const sandbox = new Proxy(context, {
has() { return true },
get(target, key) {
if (key === 'window' || key === 'document') {
throw new Error('禁止访问全局对象')
}
return target[key]
}
})
return new Function('context', `with(context) { return ${expression} }`)(sandbox)
}四、性能监控与埋点
12. 如何设计前端性能监控系统?
难度:⭐⭐⭐⭐(专家)
标签:#性能监控 #架构
参考答案要点:
系统架构:
┌─────────────────────────────────────────┐
│ 数据采集层(SDK) │
│ ┌─────────┐ ┌─────────┐ ┌────────────┐ │
│ │ Web Vitals │ │ 资源加载 │ │ 错误监控 │ │
│ └─────────┘ └─────────┘ └────────────┘ │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 数据传输层 │
│ Beacon / Fetch / WebSocket │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 数据处理层 │
│ 数据清洗 → 聚合计算 → 存储(ES/ClickHouse)│
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 数据展示层 │
│ 可视化平台 / 告警系统 │
└─────────────────────────────────────────┘核心指标:
| 指标 | 说明 | 目标值 |
|---|---|---|
| FP | First Paint | < 1.8s |
| FCP | First Contentful Paint | < 1.8s |
| LCP | Largest Contentful Paint | < 2.5s |
| FID | First Input Delay | < 100ms |
| CLS | Cumulative Layout Shift | < 0.1 |
| TTFB | Time to First Byte | < 600ms |
13. 如何实现前端错误监控?
难度:⭐⭐⭐(高级)
标签:#错误监控
参考答案要点:
错误类型:
// 1. JavaScript 错误
window.addEventListener("error", (event) => {
reportError({
type: "js",
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
stack: event.error?.stack,
})
})
// 2. Promise 未捕获错误
window.addEventListener("unhandledrejection", (event) => {
reportError({
type: "promise",
message: event.reason?.message || "Promise rejected",
stack: event.reason?.stack,
})
})
// 3. 资源加载错误
window.addEventListener(
"error",
(event) => {
if (event.target !== window) {
reportError({
type: "resource",
url: event.target.src || event.target.href,
tagName: event.target.tagName,
})
}
},
true
)
// 4. Vue/React 错误(框架捕获)
// Vue
app.config.errorHandler = (err, vm, info) => {
reportError({ type: "vue", error: err, info })
}
// React
class ErrorBoundary extends React.Component {
componentDidCatch(error, errorInfo) {
reportError({ type: "react", error, errorInfo })
}
}14. 如何实现用户行为埋点?
难度:⭐⭐⭐(高级)
标签:#埋点 #监控
参考答案要点:
埋点类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| PV/UV | 页面访问 | 页面浏览量 |
| 点击埋点 | 用户点击 | 按钮点击、链接点击 |
| 曝光埋点 | 元素可见 | 广告曝光、商品曝光 |
| 性能埋点 | 性能指标 | 加载时间、接口耗时 |
| 错误埋点 | 异常监控 | JS 错误、接口错误 |
实现方案:
// 自动埋点(推荐)
// 通过事件委托自动采集
class AutoTracker {
constructor() {
this.initClickTracking()
this.initExposureTracking()
}
initClickTracking() {
document.addEventListener("click", (e) => {
const target = e.target.closest("[data-track]")
if (target) {
this.track({
type: "click",
element: target.dataset.track,
text: target.textContent,
path: location.pathname,
})
}
})
}
initExposureTracking() {
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
this.track({
type: "exposure",
element: entry.target.dataset.exposure,
})
}
})
})
document.querySelectorAll("[data-exposure]").forEach((el) => {
observer.observe(el)
})
}
track(data) {
// 上报数据
navigator.sendBeacon("/api/track", JSON.stringify(data))
}
}五、前端工程化架构
15. 如何设计前端工程化体系?
难度:⭐⭐⭐(高级)
标签:#工程化 #架构
参考答案要点:
工程化体系:
┌─────────────────────────────────────────┐
│ 开发阶段 │
│ ┌─────────┐ ┌─────────┐ ┌────────────┐ │
│ │ 代码规范 │ │ 脚手架 │ │ 本地Mock │ │
│ │ (ESLint)│ │ │ │ │ │
│ └─────────┘ └─────────┘ └────────────┘ │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 构建阶段 │
│ ┌─────────┐ ┌─────────┐ ┌────────────┐ │
│ │ 代码转换 │ │ 资源处理 │ │ 代码优化 │ │
│ │(Babel) │ │(Webpack)│ │ (压缩/分割)│ │
│ └─────────┘ └─────────┘ └────────────┘ │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 部署阶段 │
│ ┌─────────┐ ┌─────────┐ ┌────────────┐ │
│ │ CI/CD │ │ 自动化测试│ │ 灰度发布 │ │
│ │(GitHub │ │ │ │ │ │
│ │ Actions)│ │ │ │ │ │
│ └─────────┘ └─────────┘ └────────────┘ │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 监控阶段 │
│ ┌─────────┐ ┌─────────┐ ┌────────────┐ │
│ │ 性能监控 │ │ 错误监控 │ │ 用户反馈 │ │
│ └─────────┘ └─────────┘ └────────────┘ │
└─────────────────────────────────────────┘核心能力:
- 标准化:代码规范、提交规范、目录结构
- 自动化:构建、测试、部署
- 可视化:构建分析、性能报告
- 可度量:代码质量、性能指标
16. 如何设计 Monorepo 架构?
难度:⭐⭐⭐(高级)
标签:#Monorepo #架构
参考答案要点:
Monorepo vs Polyrepo:
| 特性 | Monorepo | Polyrepo |
|---|---|---|
| 代码共享 | 容易 | 困难(需发布 npm) |
| 版本管理 | 统一 | 分散 |
| 构建优化 | 支持增量构建 | 独立构建 |
| 团队协作 | 代码可见 | 隔离 |
| 适用场景 | 大型项目、多包项目 | 独立项目 |
工具选择:
| 工具 | 特点 | 适用 |
|---|---|---|
| pnpm workspace | 轻量、高效 | 中小型项目 |
| Turborepo | 增量构建、缓存 | 大型项目 |
| Nx | 功能丰富、插件多 | 企业级项目 |
| Rush | 微软出品、规范 | 超大型项目 |
目录结构:
my-monorepo/
├── apps/ # 应用
│ ├── web/ # Web 应用
│ ├── admin/ # 管理后台
│ └── mobile/ # 移动端
├── packages/ # 共享包
│ ├── ui/ # UI 组件库
│ ├── utils/ # 工具函数
│ └── hooks/ # 共享 Hooks
├── package.json # 根配置
├── pnpm-workspace.yaml # pnpm 工作区
└── turbo.json # Turborepo 配置17. 如何实现前端自动化部署?
难度:⭐⭐⭐(高级)
标签:#CI/CD #部署
参考答案要点:
CI/CD 流程:
代码提交 → 触发构建 → 运行测试 → 构建产物 → 部署 → 通知GitHub Actions 配置:
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
- name: Install pnpm
uses: pnpm/action-setup@v2
- name: Install dependencies
run: pnpm install
- name: Run tests
run: pnpm test
- name: Build
run: pnpm build
- name: Deploy to CDN
uses: appleboy/scp-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
source: "dist/*"
target: "/var/www/html"部署策略:
| 策略 | 说明 | 适用 |
|---|---|---|
| 全量部署 | 替换所有文件 | 小型项目 |
| 增量部署 | 只更新变更文件 | 大型项目 |
| 蓝绿部署 | 两套环境切换 | 高可用要求 |
| 金丝雀发布 | 灰度放量 | 风险控制 |
六、安全架构
18. 前端安全架构如何设计?
难度:⭐⭐⭐(高级)
标签:#安全 #架构
参考答案要点:
安全体系:
┌─────────────────────────────────────────┐
│ 应用层安全 │
│ ┌─────────┐ ┌─────────┐ ┌────────────┐ │
│ │ XSS 防护 │ │ CSRF 防护│ │ 点击劫持 │ │
│ └─────────┘ └─────────┘ └────────────┘ │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 传输层安全 │
│ ┌─────────┐ ┌─────────┐ ┌────────────┐ │
│ │ HTTPS │ │ HSTS │ │ 证书固定 │ │
│ └─────────┘ └─────────┘ └────────────┘ │
└─────────────────────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 数据层安全 │
│ ┌─────────┐ ┌─────────┐ ┌────────────┐ │
│ │ 输入校验 │ │ 输出编码 │ │ 敏感数据 │ │
│ └─────────┘ └─────────┘ └────────────┘ │
└─────────────────────────────────────────┘防护措施:
| 威胁 | 防护措施 |
|---|---|
| XSS | CSP、输入过滤、输出编码、HttpOnly Cookie |
| CSRF | Token、SameSite Cookie、Referer 检查 |
| 点击劫持 | X-Frame-Options、CSP frame-ancestors |
| 中间人攻击 | HTTPS、HSTS、证书固定 |
19. 如何实现前端代码安全?
难度:⭐⭐⭐(高级)
标签:#安全 #代码保护
参考答案要点:
代码保护方案:
| 方案 | 说明 | 效果 |
|---|---|---|
| 代码混淆 | 变量名压缩、控制流扁平化 | 增加阅读难度 |
| Source Map 保护 | 不部署到生产环境 | 防止源码泄露 |
| WebAssembly | 核心逻辑用 C++/Rust 编写 | 提高逆向难度 |
| 域名绑定 | 代码校验域名 | 防止盗用 |
| 动态加载 | 核心代码动态获取 | 减少静态分析 |
配置示例:
// vite.config.js
export default {
build: {
sourcemap: false, // 不生成 source map
minify: "terser",
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
mangle: {
properties: true, // 混淆属性名
},
},
},
}七、复习建议
重点题目清单
必会题目(⭐⭐⭐ 高频)
- 微前端实现方案和选型
- qiankun/Module Federation 原理
- 组件库设计(主题定制、按需加载)
- 性能监控系统设计
- 前端工程化体系
重点掌握(⭐⭐ 常考)
- 低代码平台设计
- 错误监控和埋点
- Monorepo 架构
- CI/CD 流程
- 前端安全架构
加分项(⭐ 了解)
- 代码保护方案
- 灰度发布策略
- 多租户架构
面试技巧
- 结合实际项目:描述你在项目中如何应用这些架构
- 画图说明:架构图、流程图能更好表达思路
- 权衡利弊:每种方案都有优缺点,要会分析
- 关注前沿:了解最新的架构趋势(如 Rspack、Turbopack)