前端架构师
能力全景指南
从语言底层到架构设计,从工程体系到团队协作——系统梳理前端架构师应具备的核心能力、技术标配与职业素养
12
核心章节
60+
技术专题
40+
代码示例
2026
技术年份
一、语言与运行时深度
精通语言本质,而非停留在 API 调用层面
1.1 JavaScript 语言本质
前端架构师必须对 JS 语言有规范级的理解。以下从执行模型、内存管理、异步编程等多个维度展开。
执行模型与事件循环
浏览器事件循环模型
┌──────────────────────────────────────────────┐
│ Call Stack(调用栈) │
│ 同步代码在此执行,LIFO 结构 │
└──────────────────┬───────────────────────────┘
│ 栈为空时检查
▼
┌──────────────────────────────────────────────┐
│ Microtask Queue(微任务队列) │
│ Promise.then / MutationObserver │
│ / queueMicrotask │
│ ★ 每轮事件循环会清空所有微任务 │
└──────────────────┬───────────────────────────┘
│ 微任务清空后
▼
┌──────────────────────────────────────────────┐
│ Macrotask Queue(宏任务队列) │
│ setTimeout / setInterval / I/O │
│ ★ 每轮只取一个宏任务执行 │
└──────────────────────────────────────────────┘
执行顺序:Script(宏) → 全部微任务 → 下一个宏任务 → 全部微任务 → ...
★ requestAnimationFrame 在重绘前执行,不属于任何队列
// ===== 经典面试题:输出顺序 =====
console.log('1');
setTimeout(() => {
console.log('2');
Promise.resolve().then(() => console.log('3'));
}, 0);
Promise.resolve().then(() => {
console.log('4');
setTimeout(() => console.log('5'), 0);
});
console.log('6');
// 正确顺序:1 → 6 → 4 → 2 → 3 → 5
// ===== 架构师级应用:并发控制调度器 =====
class Scheduler {
#queue = []; #running = 0; #concurrency;
constructor(concurrency = 4) { this.#concurrency = concurrency; }
add(task) {
return new Promise((resolve, reject) => {
this.#queue.push({ task, resolve, reject });
this.#run();
});
}
#run() {
while (this.#running < this.#concurrency && this.#queue.length) {
const { task, resolve, reject } = this.#queue.shift();
this.#running++;
task().then(resolve).catch(reject).finally(() => {
this.#running--;
this.#run();
});
}
}
}
// 使用:控制并发请求数量
const scheduler = new Scheduler(3);
urls.forEach(url => scheduler.add(() => fetch(url)));
// ===== 异步模式全景 =====
// Promise.all — 全部并行,一个失败全部失败
const results = await Promise.all([fetchA(), fetchB(), fetchC()]);
// Promise.allSettled — 全部并行,等所有完成(无论成败)
const settled = await Promise.allSettled([fetchA(), fetchB()]);
// Promise.any — 竞速,取第一个成功的
const fastest = await Promise.any([fetchCDN1(), fetchCDN2()]);
// 带超时的请求
function withTimeout(promise, ms) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error(`Timeout ${ms}ms`)), ms));
return Promise.race([promise, timeout]);
}
// AsyncIterator 流式分页
async function* fetchPaginated(url) {
let page = 1;
while (true) {
const data = await fetch(`${url}?page=${page}`).then(r => r.json());
if (data.length === 0) return;
yield* data;
page++;
}
}
for await (const item of fetchPaginated('/api/users')) {
processItem(item);
}
// AbortController 取消机制
const ctrl = new AbortController();
useEffect(() => {
fetch('/api/data', { signal: ctrl.signal })
.then(r => r.json()).then(setData)
.catch(e => { if (e.name !== 'AbortError') throw e; });
return () => ctrl.abort();
}, []);
内存管理与 GC
V8 堆内存结构
┌──────────────────────────────────────────────────┐
│ V8 Heap │
│ ┌────────────────────┐ ┌──────────────────────┐ │
│ │ New Space (~32MB) │ │ Old Space (无上限) │ │
│ │ From/To Space │ │ │ │
│ │ Scavenge 算法 │ │ Mark-Sweep-Compact │ │
│ │ 短生命周期对象 │ │ 长生命周期对象 │ │
│ └────────────────────┘ └──────────────────────┘ │
│ Large Object Space — 超大对象直接放这里 │
│ Code Space — JIT 编译后的机器码 │
│ Map Space — Hidden Class 对象 │
└──────────────────────────────────────────────────┘
对象晋升:经历 2 次 Scavenge 仍存活 → 移入 Old Space
// 1. 未清理的事件监听
class Chart {
#handler;
mount(el) { this.#handler = this.#onResize.bind(this); window.addEventListener('resize', this.#handler); }
unmount() { window.removeEventListener('resize', this.#handler); /* 必须移除 */ }
}
// 2. 闭包意外持有大对象
function processData() {
const hugeDataset = fetchHugeDataset(); // 100MB
// 错误:闭包引用整个 hugeDataset
// return () => hugeDataset.metadata.version;
// 修复:只提取需要的值
const version = hugeDataset.metadata.version;
return () => version; // hugeDataset 可被 GC
}
// 3. 被遗忘的定时器
function startPolling(cb, interval) {
const id = setInterval(cb, interval);
return () => clearInterval(id); // 必须返回清理函数
}
// 4. 分离的 DOM 引用
const el = document.getElementById('chart');
el.parentNode.removeChild(el); // DOM 已移除
// 但 el 仍被引用 → 整个子树无法 GC → 修复:el = null
// 5. 实验性内存测量 API
if (performance.measureUserAgentSpecificMemory) {
const result = await performance.measureUserAgentSpecificMemory();
console.log(`Total: ${result.bytes / 1024 / 1024} MB`);
}
元编程能力
// ===== 实现响应式系统核心(Vue 3 简化版) =====
const targetMap = new WeakMap();
let activeEffect = null;
function reactive(target) {
return new Proxy(target, {
get(obj, key, receiver) {
track(obj, key);
const result = Reflect.get(obj, key, receiver);
if (typeof result === 'object' && result !== null) return reactive(result);
return result;
},
set(obj, key, value, receiver) {
const oldValue = obj[key];
const result = Reflect.set(obj, key, value, receiver);
if (oldValue !== value) trigger(obj, key);
return result;
},
deleteProperty(obj, key) {
const hadKey = key in obj;
const result = Reflect.deleteProperty(obj, key);
if (hadKey) trigger(obj, key);
return result;
},
});
}
function track(target, key) {
if (!activeEffect) return;
let depsMap = targetMap.get(target);
if (!depsMap) targetMap.set(target, (depsMap = new Map()));
let deps = depsMap.get(key);
if (!deps) depsMap.set(key, (deps = new Set()));
deps.add(activeEffect);
}
function trigger(target, key) {
const depsMap = targetMap.get(target);
if (!depsMap) return;
depsMap.get(key)?.forEach(effect => effect());
}
// ===== 不可变数据代理 =====
function deepFreeze(obj) {
return new Proxy(obj, {
get(target, key) {
const val = target[key];
return typeof val === 'object' && val !== null ? deepFreeze(val) : val;
},
set() { throw new Error('Immutable'); },
deleteProperty() { throw new Error('Immutable'); },
});
}
// ===== Proxy 实现 API 自动重试 + 缓存 =====
function createSmartClient(baseURL, { retries = 3, cacheTTL = 60000 } = {}) {
const cache = new Map();
return new Proxy({}, {
get(_, apiName) {
return async (...args) => {
const key = `${apiName}:${JSON.stringify(args)}`;
const cached = cache.get(key);
if (cached && Date.now() - cached.time < cacheTTL) return cached.data;
for (let i = 0; i <= retries; i++) {
try {
const res = await fetch(`${baseURL}/${apiName}`, {
method: 'POST', body: JSON.stringify(args),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
cache.set(key, { data, time: Date.now() });
return data;
} catch (e) {
if (i === retries) throw e;
await new Promise(r => setTimeout(r, 1000 * 2 ** i));
}
}
};
},
});
}
const api = createSmartClient('/api');
const users = await api.getUsers({ page: 1 }); // 自动缓存 + 重试
核心知识点全景表
| 领域 | 具体要求 | 深度标准 |
|---|---|---|
| 执行模型 | 事件循环、宏/微任务、rAF/rIC | 能解释任意异步代码的输出顺序 |
| 内存管理 | V8 堆结构、GC 算法、WeakRef | 能用 DevTools 定位并修复内存泄漏 |
| 原型与继承 | [[Prototype]] 链、new/class 底层 | 能手写 new/class 的 polyfill |
| 闭包与作用域 | 词法作用域、Hooks 闭包陷阱 | 能解释 React Hooks 的闭包问题 |
| 异步编程 | Promise A+、async/await 编译、AsyncIterator | 能设计并发控制、流式处理方案 |
| 模块化 | ESM vs CJS、Tree-shaking 前提 | 能解释为什么某些导出无法 tree-shake |
| 元编程 | Proxy 全陷阱、Symbol 协议 | 能基于 Proxy 实现响应式/不可变 |
| 新特性 | Temporal、Records & Tuples、Decorators | 能评估新特性的 polyfill 成本 |
1.2 TypeScript 类型工程
TypeScript 已是前端标配。架构师需掌握从基础泛型到高级类型体操的全链路能力。
类型能力分级
| 层级 | 能力要求 | 示例 |
|---|---|---|
| L1 基础 | 泛型、联合/交叉类型、类型守卫 | function isString(x: unknown): x is string |
| L2 进阶 | 条件类型、映射类型、infer、模板字面量 | type Unwrap<T> = T extends Promise<infer U> ? U : T |
| L3 高级 | 递归类型、分布式条件类型、协变/逆变 | DeepPartial、路径类型推导 |
| L4 工程 | 声明文件、模块增强、tsconfig 深度配置 | 为无类型库写 .d.ts |
| L5 架构 | 类型驱动开发、Schema-to-Type | Zod Schema → 运行时校验 + 类型推导 |
// 1. 深层 Partial
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object
? T[K] extends Function ? T[K] : DeepPartial<T[K]>
: T[K];
};
// 2. 路径类型(嵌套对象点访问)
type Path<T, K extends keyof T = keyof T> = K extends string
? T[K] extends Record<string, any>
? `${K}` | `${K}.${Path<T[K]>}`
: `${K}`
: never;
type UserPath = Path<{ name: string; address: { city: string; zip: string } }>;
// "name" | "address" | "address.city" | "address.zip"
// 3. 类型安全事件系统
type EventMap = {
'user:login': { userId: string; timestamp: number };
'order:create': { orderId: string; amount: number };
};
interface TypedEventBus<T extends Record<string, any>> {
on<K extends keyof T>(event: K, handler: (payload: T[K]) => void): () => void;
emit<K extends keyof T>(event: K, payload: T[K]): void;
}
// 4. 模板字面量类型:CSS 类型安全
type CSSUnit = 'px' | 'rem' | 'em' | '%' | 'vh' | 'vw';
type CSSValue = `${number}${CSSUnit}` | 'auto' | '0';
function setPadding(value: CSSValue) { /* ... */ }
setPadding('16px'); // OK
setPadding('1.5rem'); // OK
setPadding('large'); // Error!
// 5. 路由参数提取
type ExtractRouteParams<T extends string> =
T extends `${string}:${infer Param}/${infer Rest}`
? Param | ExtractRouteParams<Rest>
: T extends `${string}:${infer Param}` ? Param : never;
type P = ExtractRouteParams<'/users/:userId/posts/:postId'>;
// "userId" | "postId"
// 6. 类型测试
import { expectTypeOf } from 'vitest';
test('DeepPartial', () => {
type Result = DeepPartial<{ a: { b: { c: string } } }>;
expectTypeOf<Result>().toEqualTypeOf<{ a?: { b?: { c?: string } } }>();
});
工程实践
tsconfig.json 必须开启 strict 全家桶:strictNullChecks、noImplicitAny、strictFunctionTypes、exactOptionalPropertyTypes、noUncheckedIndexedAccess。1.3 Node.js 与服务端能力
| 领域 | 具体内容 | 架构师标准 |
|---|---|---|
| 事件循环 | libuv、6 阶段模型、process.nextTick | 能解释 Node 与浏览器事件循环的差异 |
| Stream | Readable/Writable/Duplex/Transform、背压 | 能处理大文件流式传输、SSE |
| 并发 | Cluster / Worker Threads / Child Process | 能根据 CPU/IO 密集选择正确方案 |
| 框架 | Express / Fastify / Hono / Koa | 精通至少一个,理解洋葱模型 |
| BFF | API 聚合、数据裁剪、GraphQL Gateway | 能设计 BFF 层减少前后端耦合 |
| 部署 | PM2 / Docker / K8s / 优雅关闭 | 能独立完成容器化部署 |
| 新运行时 | Bun(Zig)、Deno(Rust) | 了解优劣势,能评估迁移可行性 |
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { jwt } from 'hono/jwt';
import { z } from 'zod';
import { zValidator } from '@hono/zod-validator';
const app = new Hono();
app.use('*', cors({ origin: ['https://myapp.com'] }));
app.use('/api/*', jwt({ secret: process.env.JWT_SECRET! }));
// BFF 聚合:一次请求聚合多个微服务
app.get('/api/dashboard', async (c) => {
const userId = c.get('userId');
const [user, orders, notifications] = await Promise.all([
fetch(`${SERVICES.user}/users/${userId}`).then(r => r.json()),
fetch(`${SERVICES.order}/orders?userId=${userId}&limit=5`).then(r => r.json()),
fetch(`${SERVICES.notify}/notifications?unread=true`).then(r => r.json()),
]);
// 数据裁剪:只返回前端需要的字段
return c.json({
user: { id: user.id, name: user.name, avatar: user.avatarUrl },
recentOrders: orders.data.map(o => ({ id: o.id, total: o.totalAmount, status: o.status })),
unreadCount: notifications.total,
});
});
// 带校验的 POST
const CreateUserSchema = z.object({
name: z.string().min(2).max(50),
email: z.string().email(),
role: z.enum(['admin', 'user', 'viewer']),
});
app.post('/api/users', zValidator('json', CreateUserSchema), async (c) => {
const data = c.req.valid('json');
const res = await fetch(`${SERVICES.user}/users`, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
return c.json(await res.json(), res.status as any);
});
export default app;
1.4 WebAssembly 与 Rust
| 应用场景 | 代表产品 | 性能提升 | 技术细节 |
|---|---|---|---|
| 图像/视频处理 | Figma、Photoshop Web | 10-50x | C++/Rust 编译为 Wasm |
| 数据库 | SQLite Wasm | 接近原生 | 浏览器端本地 SQL |
| 加密/编解码 | libsodium-wasm | 5-20x | 密码学算法原生实现 |
| 3D/游戏 | Unity WebGL | 2-5x | 物理引擎原生编译 |
| CAD/设计 | AutoCAD Web | 10-30x | 几何计算引擎 |
// Rust 端:图片灰度处理
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn grayscale(pixels: &mut [u8]) {
for i in (0..pixels.len()).step_by(4) {
let gray = (0.299 * pixels[i] as f32
+ 0.587 * pixels[i+1] as f32
+ 0.114 * pixels[i+2] as f32) as u8;
pixels[i] = gray;
pixels[i+1] = gray;
pixels[i+2] = gray;
}
}
// JS 端调用:
// import init, { grayscale } from './pkg/image_processor';
// await init();
// const imageData = ctx.getImageData(0, 0, w, h);
// grayscale(imageData.data);
// ctx.putImageData(imageData, 0, 0);
何时考虑 Wasm
当 JS 计算密集任务成为性能瓶颈,且逻辑可用 Rust/C++ 表达时。普通 DOM 操作、API 调用不需要 Wasm。注意 Wasm↔JS 互操作有开销。二、浏览器与网络原理
理解从 URL 输入到像素上屏的全链路
2.1 浏览器渲染管线
完整渲染管线(Critical Rendering Path)
URL 输入 → DNS → TCP → TLS → HTTP 请求 → 接收响应
│
├──▶ HTML 解析 → DOM 树
├──▶ CSS 解析 → CSSOM 树
├──▶ JS 执行(阻塞解析!)
│
└──▶ DOM + CSSOM → Render Tree
│
▼
Layout(布局)— 计算每个节点的几何信息
│
▼
Paint(绘制)— 生成绘制指令
│
▼
Composite(合成)— 分层 → 光栅化 → GPU 合成
│
▼
像素上屏 🎨
各阶段优化策略
| 阶段 | 瓶颈 | 优化手段 |
|---|---|---|
| 网络 | DNS/TCP/TLS 延迟 | preconnect、HTTP/2、Brotli、CDN |
| 解析 | 渲染阻塞资源 | 关键 CSS 内联、defer/async、流式 SSR |
| 样式 | 复杂选择器 | 避免深层嵌套、CSS Containment |
| 布局 | 强制同步布局 | transform 代替 top/left、content-visibility: auto |
| 绘制 | 重绘区域过大 | 减少 box-shadow 滥用、will-change(谨慎) |
| 合成 | 过多合成层 | 只对动画元素提升图层 |
// 反面:布局抖动(交替读写 DOM 几何属性)
function badResize() {
for (const box of document.querySelectorAll('.box')) {
box.style.width = '200px'; // 写:布局失效
console.log(box.offsetHeight); // 读:强制同步布局!
}
}
// 正确:批量读写分离
function goodResize() {
const boxes = document.querySelectorAll('.box');
const heights = Array.from(boxes, b => b.offsetHeight); // 批量读
requestAnimationFrame(() => { // 批量写
boxes.forEach(b => { b.style.width = '200px'; });
});
}
// ResizeObserver 替代轮询
const observer = new ResizeObserver(entries => {
for (const entry of entries) {
updateLayout(entry.target, entry.contentRect.width);
}
});
observer.observe(document.querySelector('.container'));
2.2 V8 引擎原理
V8 编译管线
JS 源码 → Parser → AST → Ignition → Bytecode
│
函数被频繁调用(热点)
│
▼
Maglev(中层优化)
│
极热点函数
│
▼
TurboFan(深度优化 → 机器码)
│
假设失败 → Deoptimization
Hidden Class (Map):
每个对象关联一个 Map,记录属性偏移
相同初始化顺序的对象共享 Map → 快速属性访问
属性增删 → 创建新 Map → Transition Tree
// 1. Hidden Class:保持属性初始化顺序一致
function createUser(name, age, email) {
return { name, age, email }; // 所有用户共享同一个 Hidden Class
}
// 2. Inline Cache:单态(Monomorphic)最快
function getX(obj) { return obj.x; }
getX({ x: 1 }); // 一种形状 → 单态缓存 → 最快
getX({ x: 1, y: 2 }); // 两种形状 → 多态 → 较慢
// 避免:函数接收过多不同形状的对象 → 超态 → 最慢
// 3. 数组优化
const fast = [1, 2, 3]; // PACKED_SMI → 最快
const slow1 = [1, , 3]; // HOLEY → 有空洞 → 最慢
const slow2 = [1, 'two', 3]; // 混合类型 → 无法数值优化
// 4. 避免 Deoptimization
function add(a, b) { return a + b; }
add(1, 2); // TurboFan 优化为整数加法
add('a', 'b'); // Deopt! 类型变了,回退到字节码
2.3 网络协议栈
HTTP 版本演进
| 特性 | HTTP/1.1 | HTTP/2 | HTTP/3 (QUIC) |
|---|---|---|---|
| 传输层 | TCP | TCP | UDP (QUIC) |
| 连接复用 | 管线化(队头阻塞) | 多路复用(流级) | 多路复用(无队头阻塞) |
| 头部压缩 | 无 | HPACK | QPACK |
| 握手延迟 | 1-3 RTT | 1 RTT | 0-1 RTT |
| 队头阻塞 | 有(请求级) | 有(TCP 级) | 无 |
| 连接迁移 | 不支持 | 不支持 | 支持 |
HTTP 缓存全景
HTTP 缓存决策树
请求发出 → Cache-Control 检查
├── max-age 未过期 → 强缓存命中(200 from cache)
├── no-cache → 跳过强缓存,进入协商缓存
├── no-store → 完全不缓存
└── 强缓存未命中 → 协商缓存
├── ETag / If-None-Match → 304 或 200
└── Last-Modified / If-Modified-Since → 同上
最佳实践:
HTML → no-cache(每次都协商)
JS/CSS → max-age=31536000, immutable(文件名带 hash)
图片/字体 → max-age=2592000(30天)
API 响应 → 根据业务设置短缓存或 no-store
2.4 浏览器安全模型
| 安全机制 | 原理 | 配置方式 | 注意事项 |
|---|---|---|---|
| 同源策略 (SOP) | 协议+域名+端口相同 | 浏览器内置 | iframe 跨域需 postMessage |
| CORS | 服务端声明允许的来源 | Access-Control-Allow-Origin | 带凭证不能用 * |
| CSP | 限制资源加载和脚本执行 | HTTP Header | 用 nonce 而非 unsafe-inline |
| COOP/COEP | 进程隔离 | Cross-Origin-Opener-Policy | 影响第三方嵌入 |
| Trusted Types | 防 DOM XSS | CSP require-trusted-types-for | 需为 innerHTML 创建 policy |
| SRI | 子资源完整性校验 | integrity="sha384-..." | CDN 防篡改 |
三、框架生态与源码理解
不止会用 API,更要理解底层原理
3.1 React 核心原理
React 19 Fiber 架构
┌───────────────────────────────────────────────────┐
│ Scheduler(调度器) │
│ 优先级 lanes:Sync → InputContinuous → Default │
│ → Transition → Idle │
│ 实现:MessageChannel 时间切片(5ms/切片) │
└──────────────────────┬────────────────────────────┘
▼
┌───────────────────────────────────────────────────┐
│ Reconciler(协调器)— Fiber 树 │
│ Fiber 节点:{ type, key, props, stateNode, │
│ child, sibling, return, // 链表结构 │
│ lanes, flags, alternate } // 双缓冲 │
│ │
│ Render 阶段(可中断):beginWork → completeWork │
│ Commit 阶段(不可中断):BeforeMutation │
│ → Mutation → Layout → Passive │
└──────────────────────┬────────────────────────────┘
▼
┌───────────────────────────────────────────────────┐
│ Renderer:ReactDOM / React Native / Test │
└───────────────────────────────────────────────────┘
React Compiler(React 19):
自动分析组件 → 插入记忆化 → 消除手动 useMemo/useCallback
// useState 简化实现
function mountState(initial) {
const hook = { memoizedState: initial, queue: { pending: null } };
if (!fiber.memoizedState) fiber.memoizedState = hook;
else currentHook.next = hook;
currentHook = hook;
const dispatch = (action) => {
hook.queue.pending = { action, next: null };
scheduleUpdateOnFiber(fiber);
};
return [hook.memoizedState, dispatch];
}
// useEffect 执行时机:
// Render 阶段:收集 effect(不执行)
// Commit 阶段:
// BeforeMutation → useLayoutEffect destroy
// Mutation → DOM 更新
// Layout → useLayoutEffect create
// Passive(异步)→ useEffect create
// ★ useEffect 在浏览器绘制后异步执行
// ★ useLayoutEffect 在 DOM 更新后、绘制前同步执行
// 闭包陷阱与修复
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
// 错误:count 永远是 0(闭包捕获首次渲染值)
// setCount(count + 1);
// 修复 1:函数式更新
setCount(prev => prev + 1);
}, 1000);
return () => clearInterval(timer);
}, []); // 空依赖 → effect 只执行一次 → 闭包永远 count=0
}
React 生态标配(2025-2026)
| 领域 | 首选 | 备选 |
|---|---|---|
| 路由 | TanStack Router | React Router v7 |
| 数据请求 | TanStack Query v5 | SWR / Apollo |
| 全局状态 | Zustand | Jotai / Valtio |
| 表单 | React Hook Form + Zod | Formik |
| 样式 | Tailwind CSS v4 | CSS Modules / Panda CSS |
| 动画 | Motion (Framer Motion) | AutoAnimate |
| 组件基础 | Radix UI / React Aria | Headless UI |
| SSR | Next.js 15+ | Remix |
| 测试 | Vitest + Testing Library | Jest |
| E2E | Playwright | Cypress |
3.2 Vue 核心原理
Vue 3 响应式系统
reactive() — Proxy 代理
get → track(target, key) → 依赖收集
set → trigger(target, key) → 触发更新
依赖收集数据结构:
targetMap: WeakMap<target, Map<key, Set<Effect>>>
副作用类型:
effect() — 直接执行,同步响应
computed() — 惰性求值 + 缓存
watch() — 异步队列调度 + 回调
编译器优化(vs Vue 2):
├── 静态提升:不变节点只创建一次
├── 补丁标记(Patch Flags):TEXT=1, CLASS=2, STYLE=4...
├── 树摇优化:只 diff 变化的部分
└── Block Tree:跳过静态子树
| 领域 | 选型 | 说明 |
|---|---|---|
| 框架 | Vue 3.5+ (Vapor Mode) | 无虚拟 DOM,编译为直接 DOM 操作 |
| 元框架 | Nuxt 4 | 文件路由 + Server Components + 混合渲染 |
| 状态管理 | Pinia | 官方推荐,TS 友好,支持 SSR |
| 路由 | Vue Router 4 | Composition API 集成 |
| 组件库 | Naive UI / Element Plus | TS 优先 / 企业级 |
| 工具链 | Vite 6+ / unplugin 生态 | auto-import, vue-components |
| 组合函数 | VueUse(200+) | useIntersectionObserver, useDark... |
3.3 框架选型方法论
选型决策树
项目需求分析
│
├── SSR/SSG 优先?
│ ├── React 经验 → Next.js
│ ├── Vue 经验 → Nuxt
│ └── 内容站点 → Astro
│
├── SPA 为主?
│ ├── 大型复杂应用 → React + TanStack Router / Vue + Pinia
│ ├── 中小型快速开发 → Vue + Vite
│ └── 极致性能 → SolidJS / Svelte 5
│
├── 跨端需求?
│ ├── 移动端 → React Native / Expo
│ ├── 桌面端 → Tauri / Electron
│ └── 小程序 → Taro / uni-app
│
└── 团队因素(最重要的非技术因素)
├── 现有技能栈 → 优先复用
├── 招聘市场 → React 人才池更大
└── 学习曲线 → Vue 对新手更友好
选型原则
技术选型不是选"最好的",而是选"最适合当前团队和业务阶段的"。框架迁移成本极高,决策应基于:团队能力 × 业务需求 × 生态成熟度 × 长期维护成本。四、工程化体系
从构建到部署的全链路工程能力
4.1 构建工具链
| 工具 | 语言 | 定位 | 开发体验 | 适用场景 |
|---|---|---|---|---|
| Webpack 5 | JS | 全能打包器 | 慢(冷启动 30s+) | 大型遗留项目 |
| Vite 6+ | JS+Rust | DX 优先 | 极快(esbuild 预构建) | 新项目首选 |
| Rspack | Rust | Webpack 兼容 | 快 5-10x | Webpack 项目性能升级 |
| Turbopack | Rust | Next.js 专属 | 增量编译极快 | Next.js 项目 |
| Rolldown | Rust | Rollup 替代品 | 快 10-20x | Vite 底层引擎 |
| esbuild | Go | 极速转译 | 极快 | 预处理、TS→JS |
| SWC | Rust | Babel 替代品 | 快 20-70x | 转译、lint、压缩 |
| tsdown | Rust | TS 库构建 | 零配置 | TypeScript 库开发 |
构建优化清单
- Tree-shaking:
sideEffects: false,ESM 导出 - Code Splitting:路由级 + 供应商分包 + 大组件动态导入
- 依赖预构建:Vite deps optimizer / Webpack 持久化缓存
- 压缩:esbuild minify(默认)/ terser(高级)/ SWC
- 图片优化:AVIF/WebP 自动转换
- 资源内联:小图片 base64(assetsInlineLimit)
- Source Map:开发
eval-source-map,生产hidden-source-map
4.2 Monorepo 管理
适合 Monorepo
✓ 多应用共享组件库/工具库
✓ Design System 与应用同步迭代
✓ 统一构建/测试/发布流程
✓ 原子级变更(跨包修改在一个 PR)
✓ 团队 > 10 人
✓ Design System 与应用同步迭代
✓ 统一构建/测试/发布流程
✓ 原子级变更(跨包修改在一个 PR)
✓ 团队 > 10 人
不适合
✗ 项目完全独立,无共享代码
✗ 团队 < 5 人
✗ 各团队技术栈差异极大
✗ 发布节奏完全不同
✗ CI 无法支持增量构建
✗ 团队 < 5 人
✗ 各团队技术栈差异极大
✗ 发布节奏完全不同
✗ CI 无法支持增量构建
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
"inputs": ["src/**", "package.json", "tsconfig.json"]
},
"test": { "dependsOn": ["^build"], "outputs": ["coverage/**"] },
"lint": { "outputs": [] },
"type-check": { "outputs": [] },
"dev": { "cache": false, "persistent": true, "dependsOn": ["^build"] },
"deploy": { "dependsOn": ["build", "test", "lint"] }
}
}
4.3 代码质量与规范
代码质量金字塔
┌──────────┐
│ 人工评审 │ ← Code Review(PR 级别,最终防线)
├──────────┤
│ 类型检查 │ ← TypeScript strict(编译时保障)
├──────────┤
│ 静态分析 │ ← ESLint + Oxlint(代码模式检测)
├──────────┤
│ 格式化 │ ← Prettier / Biome(风格统一)
├──────────┤
│ Git 规范 │ ← commitlint + husky + lint-staged
└──────────┘
执行时机:
保存文件 → Prettier(编辑器)
git add → lint-staged(暂存文件 lint + type-check)
git commit → commitlint(校验 message 格式)
CI → ESLint + tsc + test + build(全量)
// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import reactCompiler from 'eslint-plugin-react-compiler';
export default tseslint.config(
js.configs.recommended,
...tseslint.configs.strictTypeChecked,
{
files: ['**/*.{ts,tsx}'],
plugins: { react, 'react-hooks': reactHooks, 'react-compiler': reactCompiler },
languageOptions: {
parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname },
},
rules: {
'react-hooks/exhaustive-deps': 'warn',
'react-compiler/react-compiler': 'warn',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'@typescript-eslint/consistent-type-imports': ['error', { prefer: 'type-imports' }],
},
},
{ ignores: ['dist/', '.next/', 'node_modules/'] }
);
4.4 CI/CD 流水线
前端 CI/CD 全景
Push / PR
│
▼
┌────────────────────────────────────────────────────┐
│ Stage 1: 质量门禁(并行 ~3-5 分钟) │
│ lint + type-check + test + build + security-audit │
└─────────────────────┬──────────────────────────────┘
▼
┌────────────────────────────────────────────────────┐
│ Stage 2: 预览部署(仅 PR) │
│ Preview URL + 视觉回归 + E2E + Bundle 分析 │
└─────────────────────┬──────────────────────────────┘
▼
┌────────────────────────────────────────────────────┐
│ Stage 3: 生产发布 │
│ Changeset 版本号 → 构建 → Source Map 上传 │
│ → CDN 部署 → 健康检查 → 通知 │
└─────────────────────┬──────────────────────────────┘
▼
┌────────────────────────────────────────────────────┐
│ Stage 4: 灰度发布(可选) │
│ 1% → 5% → 20% → 50% → 100% │
│ 监控错误率 + 性能指标 + 异常自动回滚 │
└────────────────────────────────────────────────────┘
4.5 包管理与版本发布
开发者完成功能
→
pnpm changeset
→
选择受影响包
→
选择版本类型
→
写变更说明
→
提交 .changeset/*.md
→
CI 创建版本 PR
→
合并后自动发版
{
"name": "@my-org/ui",
"version": "1.2.0",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./styles": "./dist/styles.css"
},
"sideEffects": ["*.css"],
"files": ["dist", "README.md"],
"publishConfig": { "access": "public", "provenance": true },
"peerDependencies": { "react": "^18.0.0 || ^19.0.0" }
}
五、架构设计能力
从代码组织到系统架构的全局把控
5.1 应用架构模式
| 模式 | 核心思想 | 优点 | 缺点 | 适用 |
|---|---|---|---|---|
| MVC | 三层分离 | 简单直观 | Controller 臃肿 | 简单 CRUD |
| MVVM | 数据双向绑定 | 声明式 | 调试困难 | Vue 应用 |
| Flux/Redux | 单向数据流 | 可预测 | 样板代码多 | 复杂状态 |
| Feature-Sliced | 按业务特性组织 | 高内聚低耦合 | 学习成本 | 中大型应用 |
| 原子设计 | 原子→分子→组织→模板→页面 | 复用性强 | 层级模糊 | Design System |
Feature-Sliced Design 目录结构
src/
├── app/ # 应用初始化:providers, router, styles
├── pages/ # 页面层(路由一一对应)
├── widgets/ # 业务模块层(独立功能块:sidebar, header)
├── features/ # 功能特性层(跨模块复用:auth, add-to-cart)
├── entities/ # 业务实体层(user, product, order)
└── shared/ # 共享基础层(ui, api, lib, config, types)
依赖方向:pages → widgets → features → entities → shared
同层之间不能互相引用
5.2 微前端架构
| 方案 | 原理 | 隔离方式 | 优点 | 缺点 |
|---|---|---|---|---|
| Module Federation 2 | 原生模块共享 | 无沙箱(共享作用域) | 真正的运行时共享、类型安全 | 构建配置复杂 |
| qiankun | single-spa + 沙箱 | Proxy 沙箱 + Shadow DOM | 成熟稳定、接入成本低 | 沙箱性能开销 |
| Wujie | iframe + Web Component | iframe 天然隔离 | 完美隔离、无改造成本 | 弹窗限制、SEO 不友好 |
| Micro App | 自定义元素 + 沙箱 | JS 沙箱 | 接入简单 | 社区较小 |
// 宿主应用 (host) — Vite 配置
import { federation } from '@module-federation/vite';
export default defineConfig({
plugins: [
federation({
name: 'host',
remotes: {
remoteApp: {
type: 'module',
name: 'remoteApp',
entry: 'https://cdn.example.com/remoteEntry.js',
},
},
shared: {
react: { singleton: true, requiredVersion: '^19.0.0' },
'react-dom': { singleton: true },
},
}),
],
});
// 远程应用 (remote)
export default defineConfig({
plugins: [
federation({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Dashboard': './src/Dashboard.tsx',
'./utils': './src/utils/index.ts',
},
}),
],
});
5.3 状态管理架构
状态分类与选型
┌──────────────────────────────────────────────────────┐
│ 服务端状态(Server State) │
│ → TanStack Query / SWR │
│ → 特征:异步、可缓存、需同步 │
├──────────────────────────────────────────────────────┤
│ 客户端状态(Client State) │
│ ├── 全局 UI 状态(主题、侧边栏)→ Zustand / Pinia │
│ ├── 表单状态 → React Hook Form + Zod │
│ ├── URL 状态 → TanStack Router searchParams │
│ └── 组件本地状态 → useState / ref │
├──────────────────────────────────────────────────────┤
│ 持久化状态 → localStorage / IndexedDB / Cookie │
└──────────────────────────────────────────────────────┘
import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
interface AuthState {
user: User | null;
token: string | null;
isAuthenticated: boolean;
login: (credentials: Credentials) => Promise<void>;
logout: () => void;
}
export const useAuthStore = create<AuthState>()(
devtools(
persist(
immer((set) => ({
user: null, token: null, isAuthenticated: false,
login: async (credentials) => {
const { user, token } = await authApi.login(credentials);
set((state) => {
state.user = user;
state.token = token;
state.isAuthenticated = true;
});
},
logout: () => set((state) => {
state.user = null;
state.token = null;
state.isAuthenticated = false;
}),
})),
{ name: 'auth-storage' }
)
)
);
5.4 路由架构设计
| 方案 | 类型安全 | 文件路由 | 数据加载 | 适用 |
|---|---|---|---|---|
| TanStack Router | 完全类型安全 | 可选 | 内置 loader | 类型安全优先 |
| React Router v7 | 一般 | 否 | 手动 | 通用 SPA |
| Next.js App Router | 部分 | 是 | Server Components | SSR/SSG |
| Nuxt 4 | 部分 | 是 | useAsyncData | Vue SSR |
import { createFileRoute } from '@tanstack/react-router';
import { z } from 'zod';
const searchSchema = z.object({
tab: z.enum(['content', 'comments']).default('content'),
page: z.number().int().positive().default(1),
});
export const Route = createFileRoute('/posts/$postId')({
validateSearch: searchSchema.parse,
loader: async ({ params: { postId }, search }) => {
const post = await fetchPost(postId);
const comments = search.tab === 'comments'
? await fetchComments(postId, search.page) : [];
return { post, comments };
},
component: PostPage,
});
function PostPage() {
const { post, comments } = Route.useLoaderData();
const { tab } = Route.useSearch(); // 完全类型安全
const { postId } = Route.useParams(); // string 类型
}
5.5 Design System 与组件体系
Design System 分层
┌──────────────────────────────────────────────────┐
│ Patterns(模式层)— 登录表单、数据表格等业务模式 │
├──────────────────────────────────────────────────┤
│ Compositions(组合层)— 卡片、导航栏等复合组件 │
├──────────────────────────────────────────────────┤
│ Components(组件层)— Button、Input、Modal 等 │
├──────────────────────────────────────────────────┤
│ Primitives(原语层)— Headless UI: Dialog, Popover │
│ (Radix UI / Reka UI / React Aria) │
├──────────────────────────────────────────────────┤
│ Tokens(设计令牌层)— 颜色、间距、字体、阴影 │
│ (Style Dictionary / CSS Custom Properties) │
└──────────────────────────────────────────────────┘
好的设计:组合式 API
<Select.Root value={v} onValueChange={setV}>
<Select.Trigger><Select.Value /></Select.Trigger>
<Select.Content>
<Select.Item value="a">A</Select.Item>
</Select.Content>
</Select.Root>不好的设计:配置式
<Select
value={v}
onChange={setV}
options={[...]}
placeholder="..."
triggerClassName="..."
/>5.6 数据层架构
// 统一 API 客户端
class ApiClient {
private baseURL: string;
async request<T>(config: RequestConfig): Promise<T> {
const response = await fetch(this.baseURL + config.url, this.buildOptions(config));
if (!response.ok) throw await this.handleError(response);
return response.json();
}
}
const api = {
users: {
list: (params: UserListParams) => client.get<User[]>('/users', { params }),
getById: (id: string) => client.get<User>(`/users/${id}`),
create: (data: CreateUserInput) => client.post<User>('/users', { body: JSON.stringify(data) }),
update: (id: string, data: UpdateUserInput) => client.patch<User>(`/users/${id}`, { body: JSON.stringify(data) }),
delete: (id: string) => client.delete(`/users/${id}`),
},
};
// 配合 TanStack Query
function useUsers(params: UserListParams) {
return useQuery({
queryKey: ['users', params],
queryFn: () => api.users.list(params),
staleTime: 30_000,
});
}
六、性能工程
从指标到优化到监控的完整体系
6.1 性能指标体系
| 指标 | 含义 | 良好阈值 | 优化方向 |
|---|---|---|---|
| LCP | 最大内容绘制时间 | ≤ 2.5s | 资源加载、服务端响应 |
| INP | 交互到下一次绘制 | ≤ 200ms | 主线程阻塞、事件处理 |
| CLS | 累积布局偏移 | ≤ 0.1 | 图片尺寸、字体加载、动态内容 |
| TTFB | 首字节时间 | ≤ 800ms | 服务器响应、CDN |
| FCP | 首次内容绘制 | ≤ 1.8s | 关键资源加载 |
6.2 加载性能优化
<!-- 预连接关键域名 -->
<link rel="preconnect" href="https://api.example.com" />
<link rel="dns-prefetch" href="https://analytics.example.com" />
<!-- 预加载关键资源 -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/critical.css" as="style" />
<link rel="preload" href="/hero.avif" as="image" type="image/avif" />
<!-- 预获取下一页 -->
<link rel="prefetch" href="/next-page.js" as="script" />
<!-- 预渲染(Chrome 121+) -->
<link rel="prerender" href="/next-page" />
图片优化决策
| 类型 | 格式选择 | 加载策略 |
|---|---|---|
| 照片 | AVIF(首选)→ WebP → JPEG | 首屏 eager,非首屏 loading="lazy" |
| 图形/图标 | SVG(首选)→ PNG | 内联小 SVG,大图标 sprite |
| 动画 | Lottie / 视频(H.265) | 视口内才加载 |
代码分割策略
// 路由级分割
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));
// 组件级分割(条件加载的大组件)
const HeavyChart = lazy(() => import('./components/HeavyChart'));
// Vite 供应商分包
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
'vendor-react': ['react', 'react-dom'],
'vendor-query': ['@tanstack/react-query'],
'vendor-ui': ['@radix-ui/react-dialog', '@radix-ui/react-popover'],
},
},
},
},
});
6.3 运行时性能优化
// 1. 虚拟列表(长列表必备)
import { useVirtualizer } from '@tanstack/react-virtual';
function VirtualList({ items }) {
const parentRef = useRef(null);
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50,
overscan: 5,
});
return (
<div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>
<div style={{ height: `${virtualizer.getTotalSize()}px`, position: 'relative' }}>
{virtualizer.getVirtualItems().map(row => (
<div key={row.index}
style={{ position: 'absolute', top: 0, transform: `translateY(${row.start}px)` }}>
{items[row.index].name}
</div>
))}
</div>
</div>
);
}
// 2. Web Worker 处理计算密集任务
const worker = new Worker('./worker.ts', { type: 'module' });
worker.postMessage(largeDataset);
worker.onmessage = (e) => setResult(e.data);
// 3. 避免不必要的重渲染
// 错误:每次渲染创建新对象
function Parent({ items }) {
return <Child style={{ color: 'red' }} items={items} />;
// style={{ color: 'red' }} 每次都是新引用
}
// 正确:提取常量
const defaultStyle = { color: 'red' };
function Parent({ items }) {
return <Child style={defaultStyle} items={items} />;
}
6.4 性能监控与回归防护
import { onLCP, onINP, onCLS, onTTFB } from 'web-vitals';
function sendToAnalytics(metric: Metric) {
navigator.sendBeacon('/analytics', JSON.stringify({
name: metric.name,
value: metric.value,
rating: metric.rating, // 'good' | 'needs-improvement' | 'poor'
delta: metric.delta,
id: metric.id,
url: location.href,
timestamp: Date.now(),
}));
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
onTTFB(sendToAnalytics);
性能预算
{
"maxBundleSize": "250KB",
"maxInitialJS": "150KB",
"maxImageSize": "100KB",
"maxLCP": 2500,
"maxINP": 200,
"maxCLS": 0.1,
"maxThirdPartyBytes": "50KB"
}
七、可观测性与质量保障
监控、测试、错误治理的完整体系
7.1 前端监控体系
监控架构
┌──────────────────────────────────────────────────────┐
│ 监控平台 │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ 错误监控 │ │ 性能监控 │ │ 行为/业务监控 │ │
│ │ (Sentry) │ │ (RUM) │ │ (GrowingIO等) │ │
│ └──────────┘ └──────────┘ └──────────────────┘ │
├──────────────────────────────────────────────────────┤
│ 数据采集层 │
│ 全局错误监听 / PerformanceObserver / 用户行为埋点 │
├──────────────────────────────────────────────────────┤
│ 客户端 SDK │
│ window.onerror / unhandledrejection / Resource Error │
└──────────────────────────────────────────────────────┘
// 1. JS 运行时错误
window.addEventListener('error', (event) => {
reportError({ type: 'js_error', message: event.message,
filename: event.filename, lineno: event.lineno, stack: event.error?.stack });
});
// 2. Promise 未捕获异常
window.addEventListener('unhandledrejection', (event) => {
reportError({ type: 'promise_rejection', message: String(event.reason) });
});
// 3. 资源加载错误(捕获阶段,资源错误不冒泡)
window.addEventListener('error', (event) => {
const target = event.target;
if (target.tagName) {
reportError({ type: 'resource_error', tagName: target.tagName, src: target.src });
}
}, true);
// 4. API 请求错误(fetch 拦截)
const originalFetch = window.fetch;
window.fetch = async (...args) => {
const start = performance.now();
try {
const response = await originalFetch(...args);
const duration = performance.now() - start;
if (!response.ok) reportError({ type: 'api_error', url: args[0], status: response.status, duration });
return response;
} catch (error) {
reportError({ type: 'api_error', url: args[0], message: String(error) });
throw error;
}
};
// 5. React Error Boundary
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
componentDidCatch(error, info) {
reportError({ type: 'react_error', message: error.message,
stack: error.stack, componentStack: info.componentStack });
}
render() { return this.state.hasError ? this.props.fallback : this.props.children; }
}
7.2 测试策略
测试金字塔
┌─────────┐
│ E2E │ ← Playwright(关键用户流程)
│ (少量) │
├─────────┤
│ 集成测试 │ ← Testing Library(组件交互)
│ (中量) │
├─────────┤
│ 单元测试 │ ← Vitest(函数、Hook、工具)
│ (大量) │
└─────────┘
// 单元测试:Hook
import { renderHook, act } from '@testing-library/react';
import { useCounter } from './useCounter';
test('increments correctly', () => {
const { result } = renderHook(() => useCounter(0));
act(() => { result.current.increment(); });
expect(result.current.count).toBe(1);
});
// 集成测试:组件
import { render, screen, userEvent } from '@testing-library/react';
test('submits form with valid credentials', async () => {
const onSubmit = vi.fn();
render(<LoginForm onSubmit={onSubmit} />);
await userEvent.type(screen.getByLabelText('Email'), 'user@example.com');
await userEvent.type(screen.getByLabelText('Password'), 'password123');
await userEvent.click(screen.getByRole('button', { name: 'Login' }));
expect(onSubmit).toHaveBeenCalledWith({ email: 'user@example.com', password: 'password123' });
});
// E2E 测试:Playwright
import { test, expect } from '@playwright/test';
test('checkout flow', async ({ page }) => {
await page.goto('/products');
await page.getByRole('link', { name: 'Widget Pro' }).click();
await page.getByRole('button', { name: 'Add to Cart' }).click();
await page.getByRole('link', { name: 'Checkout' }).click();
await page.getByLabel('Email').fill('test@example.com');
await page.getByRole('button', { name: 'Pay Now' }).click();
await expect(page.getByText('Order Confirmed')).toBeVisible();
});
7.3 错误治理
// 构建时生成 hidden source map
// vite.config.ts
export default defineConfig({
build: { sourcemap: 'hidden' }, // 生成 .map 但不引用
});
// 发布后上传到 Sentry
// npx sentry-cli sourcemaps inject ./dist
// npx sentry-cli sourcemaps upload --release v1.2.0 ./dist
错误分级与告警
| 级别 | 告警渠道 | 阈值 | 响应时间 |
|---|---|---|---|
| Fatal | 电话 + Slack | 1 次即告警 | 5 分钟内 |
| Error | Slack | 10 次/5分钟 | 30 分钟内 |
| Warning | 日志 | 不告警 | 下一迭代 |
八、安全工程
XSS、CSRF、CSP、依赖安全的全方位防御
8.1 XSS 防御
| 类型 | 攻击方式 | 防御手段 |
|---|---|---|
| 存储型 XSS | 恶意脚本存入数据库 | 输入过滤 + 输出编码 + CSP |
| 反射型 XSS | URL 参数直接渲染 | URL 参数不直接渲染、转义 |
| DOM XSS | JS 直接操作 DOM | 避免 innerHTML、使用 Trusted Types |
// React 默认转义 JSX,但 dangerouslySetInnerHTML 是陷阱
// 危险:
<div dangerouslySetInnerHTML={{ __html: userInput }} />
// 安全:使用 DOMPurify 清洗
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />
// 最安全:避免 HTML 注入
<div>{userInput}</div> // React 自动转义
8.2 CSRF 防御
SameSite Cookie(首选)
Set-Cookie: session=abc; SameSite=Strict; Secure; HttpOnlyCSRF Token
服务端生成 token → 前端放在 header
X-CSRF-Token 中回传Double Submit Cookie
Cookie 和 Header 中放相同 token,服务端比较
8.3 CSP 配置
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{random}';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://api.example.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
upgrade-insecure-requests;
8.4 依赖安全
# 定期扫描
pnpm audit # 内置审计
npx snyk test # Snyk 扫描
npx trivy fs . # Trivy 全面扫描
# CI 集成
pnpm audit --audit-level=high
九、跨端能力
移动端、桌面端、小程序的全端覆盖
9.1 移动端方案
| 方案 | 技术栈 | 适用场景 |
|---|---|---|
| React Native / Expo | React | 跨平台移动应用 |
| Flutter | Dart | 高一致性 UI |
| Capacitor | Web 技术 | Web 应用包装为原生 |
| PWA | Web 技术 | 轻量跨端、离线能力 |
| Taro / uni-app | Vue/React 语法 | 国内小程序生态 |
9.2 桌面端方案
| 方案 | 技术栈 | 包大小 | 性能 |
|---|---|---|---|
| Electron | Chromium + Node.js | ~150MB | 一般 |
| Tauri | 系统 WebView + Rust | ~10MB | 优秀 |
| Wails | 系统 WebView + Go | ~10MB | 优秀 |
9.3 跨端代码共享
跨端架构
┌──────────────────────────────────────────────────────┐
│ 共享层(packages/shared) │
│ 业务逻辑 / API 客户端 / 类型定义 / 工具函数 │
├──────────────────────────────────────────────────────┤
│ 平台适配层 │
│ platform-web → DOM API │
│ platform-native → React Native API │
│ platform-mini → 小程序 API │
├──────────────────────────────────────────────────────┤
│ UI 层(各端独立) │
│ apps/web → React + Tailwind │
│ apps/mobile → React Native │
│ apps/mini → Taro │
└──────────────────────────────────────────────────────┘
十、技术软实力
技术判断、团队赋能、业务翻译
10.1 技术判断与决策
# ADR-001: 选择 Zustand 作为全局状态管理
## 状态:已接受
## 背景
应用需要管理全局 UI 状态,当前使用 Context + useReducer,
在频繁更新时出现性能问题。
## 决策
采用 Zustand 替代 Context + useReducer。
## 理由
1. 性能:基于发布-订阅,只有订阅 slice 的组件会重渲染
2. 简洁:API 极简,无需 Provider 包裹
3. 体积:~1KB gzipped
4. 生态:支持 devtools、persist、immer 中间件
## 被否决的方案
- Redux Toolkit:过于重量
- Jotai:原子化模型对本项目收益不大
- MobX:隐式依赖追踪,调试困难
## 后果
- 正面:减少 30% 不必要重渲染,代码量减少 40%
- 负面:团队需要学习新模式
10.2 团队赋能
| 输出类型 | 频率 | 目的 |
|---|---|---|
| 技术 RFC | 按需 | 重大技术决策的讨论与记录 |
| ADR 文档 | 按需 | 架构决策的可追溯记录 |
| Code Review | 每日 | 代码质量把控、知识传递 |
| 技术分享 | 双周/月 | 团队技术视野拓展 |
| 规范文档 | 季度更新 | 编码规范、最佳实践沉淀 |
| 1:1 辅导 | 每周 | 团队成员成长 |
10.3 业务翻译能力
业务需求 → 技术方案
业务需求:"用户需要能快速找到想要的商品"
│
├── 拆解:搜索体验优化
│ ├── 搜索建议/自动补全
│ ├── 搜索结果高亮
│ ├── 搜索历史
│ └── 筛选/排序
│
├── 技术方案:
│ ├── 前端:防抖搜索 + 虚拟列表 + 骨架屏
│ ├── 后端:Elasticsearch 接入
│ ├── 缓存:搜索建议 Redis 缓存
│ └── 监控:搜索成功率、无结果率
│
└── 排期:
├── P0:基础搜索 + 结果展示(1 周)
├── P1:自动补全 + 搜索历史(1 周)
└── P2:AI 推荐 + 语音搜索(2 周)
附录 A:2025-2026 技术标配清单
必会 / 应会 / 了解 三级分类
必会(日常使用)
| 领域 | 技术 |
|---|---|
| 语言 | TypeScript 5.x(strict 模式) |
| 框架 | React 19+ 或 Vue 3.5+ |
| 元框架 | Next.js 15+ / Nuxt 4 |
| 样式 | Tailwind CSS v4 |
| 状态 | Zustand / Pinia |
| 数据请求 | TanStack Query v5 |
| 路由 | TanStack Router / React Router v7 |
| 表单 | React Hook Form + Zod |
| 构建 | Vite 6+ |
| 测试 | Vitest + Testing Library + Playwright |
| 代码质量 | ESLint v9 (flat config) + Prettier |
| 包管理 | pnpm |
| 组件 | shadcn/ui / Radix UI / Reka UI |
| 类型校验 | Zod / Valibot |
应会(架构能力)
| 领域 | 技术 |
|---|---|
| 微前端 | Module Federation 2 / Wujie |
| Monorepo | Turborepo + pnpm workspace |
| SSR/SSG | Next.js App Router / Nuxt |
| 性能 | Lighthouse CI + web-vitals + DevTools |
| 监控 | Sentry / 自建 RUM |
| CI/CD | GitHub Actions / GitLab CI |
| 容器化 | Docker + Docker Compose |
| 部署 | Vercel / Cloudflare Workers / AWS |
了解(技术视野)
| 领域 | 技术 |
|---|---|
| AI 集成 | Vercel AI SDK / LangChain.js / OpenAI API |
| 边缘计算 | Cloudflare Workers / Deno Deploy |
| 图形 | Three.js / WebGL2 / WebGPU |
| 跨端 | React Native / Expo / Tauri |
| Wasm | Rust + wasm-pack |
| 新运行时 | Bun / Deno |
| 可视化 | D3.js / ECharts / Observable Plot |
附录 B:成长路径与学习资源
从初级到架构师的进阶之路
成长路径
| 阶段 | 年限 | 核心能力 | 重点方向 |
|---|---|---|---|
| 初级 | 0-2 年 | 独立完成功能模块 | JS/TS 基础、框架 API、CSS 布局 |
| 中级 | 2-4 年 | 设计组件和状态管理方案 | 性能优化、工程化、测试 |
| 高级 | 4-6 年 | 设计模块级架构,推动技术改进 | 架构设计、构建工具、微前端、监控 |
| 架构师 | 6+ 年 | 设计系统级架构,影响技术方向 | 技术判断力、团队赋能、业务翻译 |
推荐学习资源
patterns.dev
前端设计模式与最佳实践
web.dev
Google 出品的 Web 性能与最佳实践
react.dev
React 官方文档(交互式教程)
State of JS
前端生态年度调查报告
Frontend Masters
高质量前端视频课程
mrale.ph
V8 引擎深度解析
开源项目学习路线
| 项目 | 学习点 |
|---|---|
| React | Fiber 架构、调度器、Hooks 实现 |
| Vue 3 | 响应式系统、编译器优化 |
| Vite | 构建工具、插件系统 |
| TanStack Query | 缓存策略、状态同步 |
| shadcn/ui | 组件设计、所有权模式 |
| Zustand | 状态管理极简实现 |
附录 C:能力自检清单
前端架构师能力全面自检
基础能力(必须全部达标)
- 能手写 Promise、debounce、throttle、deepClone
- 理解事件循环,能解释微任务/宏任务执行顺序
- 精通 TypeScript,能写复杂泛型和条件类型
- 理解浏览器渲染管线,能定位性能瓶颈
- 精通至少一个框架的原理(非仅 API)
- 能独立搭建完整工程化体系(构建+规范+CI/CD)
- 理解 HTTP 协议、缓存策略、安全机制
架构能力(至少达标 80%)
- 能设计大型应用的目录结构和模块边界
- 有微前端落地经验或深入理解至少一种方案
- 能设计 Design System 并推动落地
- 能制定性能预算并建立监控体系
- 能编写 ADR 文档,有理有据地做技术决策
- 有 Monorepo 管理经验
- 能设计前端监控体系(错误+性能+行为)
- 理解跨端方案的取舍
软实力(至少达标 70%)
- 能向非技术人员解释技术方案
- 能带 3+ 人团队交付项目
- 定期输出技术文档/分享
- 能评估新技术的价值并做引入决策
- 能将业务需求翻译为技术方案
前端架构师能力全景指南 v2.0 · 2026-08-29
核心不是"会的技术多",而是在正确的场景做正确的取舍