目标:主导大型 React 项目架构设计,搭建工程化体系,解决大规模应用的性能、安全、扩展性问题,赋能团队

视角:基于字节/阿里/腾讯等大厂 React 架构实战 + 开源项目源码分析 + React 官方设计哲学

维度:架构合理性 | 工程质量 | 性能 | 可扩展性 | 安全性 | 团队协作

前置要求:完成基础层 + 进阶层学习,具备 3 年以上 React 实战经验


目录


一、架构设计能力

1.1 项目分层架构

1.1.1 四层解耦架构(核心设计模式)

【架构核心】视图层 → 业务层 → 数据层 → 工具层,每层职责单一、独立可测试

┌──────────────────────────────────────────────────────────────┐
│                                                              │
│  视图层(View Layer)                                         │
│  ├── Pages:页面组件,组合业务组件                              │
│  ├── Components:UI 组件(通用 + 业务)                         │
│  └── Layouts:布局组件                                         │
│                                                              │
│  业务层(Business Layer)                                     │
│  ├── Hooks:业务逻辑封装(useAuth / useCart / useOrder)       │
│  ├── Services:业务流程编排                                     │
│  └── Validators:业务校验规则                                   │
│                                                              │
│  数据层(Data Layer)                                          │
│  ├── API:请求封装(axios / fetch)                             │
│  ├── Store:状态管理(Zustand / Redux)                         │
│  ├── Cache:缓存策略(React Query / SWR)                       │
│  └── DTO:数据传输对象                                          │
│                                                              │
│  工具层(Utils Layer)                                         │
│  ├── helpers:纯函数工具                                        │
│  ├── constants:常量定义                                        │
│  ├── types:类型定义                                            │
│  └── config:环境配置                                           │
│                                                              │
└──────────────────────────────────────────────────────────────┘
📊 字节跳动分层架构实战案例

【案例背景】字节跳动电商中台项目,20+ 人团队,日活 500 万

项目初期架构问题:
├── 业务代码与 UI 组件严重耦合
├── API 调用散落在各个组件中,接口变更难以追踪
├── 状态管理混乱,组件间数据同步靠 props drilling
└── 单元测试覆盖率 < 20%,改动即崩溃

重构后的分层架构收益:
├── 模块职责清晰,新人上手时间从 2 周 → 3 天
├── 单元测试覆盖率提升至 75%+
├── 接口变更影响范围可控,平均修复时间缩短 60%
└── 组件复用率提升 3 倍
📁 目录结构(分层落地)
src/
├── views/                    # 视图层
│   ├── Home/
│   │   ├── index.tsx          # 页面入口
│   │   ├── HomePage.tsx       # 页面组件
│   │   ├── components/        # 页面私有组件
│   │   └── styles.module.css
│   └── Dashboard/
├── components/               # 视图层 - 共享组件
│   ├── ui/                    # 通用 UI 组件(原子/分子)
│   │   ├── Button/
│   │   ├── Input/
│   │   ├── Modal/
│   │   └── Table/
│   └── business/              # 业务组件(有机体)
│       ├── UserSelector/
│       ├── OrderForm/
│       └── ProductCard/
├── hooks/                    # 业务层
│   ├── useAuth.ts
│   ├── useOrder.ts
│   └── useProduct.ts
├── services/                 # 业务层 - 流程编排
│   ├── order.service.ts
│   └── payment.service.ts
├── api/                      # 数据层
│   ├── client.ts              # 请求实例
│   ├── modules/               # 按模块组织
│   │   ├── user.api.ts
│   │   ├── product.api.ts
│   │   └── order.api.ts
│   └── interceptors.ts        # 拦截器
├── store/                    # 数据层 - 状态管理
│   ├── slices/
│   │   ├── user.slice.ts
│   │   └── cart.slice.ts
│   └── index.ts
├── dto/                      # 数据层 - 数据传输对象
│   ├── user.dto.ts
│   └── product.dto.ts
├── utils/                    # 工具层
│   ├── helpers/
│   ├── constants/
│   │   ├── app.ts
│   │   └── api.ts
│   ├── validators/
│   └── formatters/
├── types/                    # 工具层 - 全局类型
│   ├── api.types.ts
│   ├── component.types.ts
│   └── global.d.ts
└── config/                   # 工具层 - 配置
    ├── env.ts
    └── routes.ts
🏭 阿里前端团队分层架构规范(内部规范摘要)
// 阿里企业级前端分层规范(简化版)
// 来源:Alibaba D2 前端规范论坛 2024 年度最佳实践

/**
 * 【强制】视图层禁止直接调用 API
 * ❌ 错误示例:
 * const data = await fetch('/api/user');
 *
 * ✅ 正确示例:
 * const data = await userService.getUserInfo();
 */

// 视图层(View)- 只负责渲染
// ✅ 允许:组合组件、调用 Hooks
// ❌ 禁止:直接调用 API、书写业务逻辑

// 业务层(Service)- 编排业务流程
// ✅ 允许:调用多个 API、组合多个 Hooks
// ❌ 禁止:直接操作 DOM、渲染 JSX

// 数据层(API)- 原子化接口
// ✅ 允许:单一接口调用、数据转换
// ❌ 禁止:业务逻辑组合、状态管理
1.1.2 依赖规则(层级隔离)

【解耦关键】每一层只依赖下层,严禁反向依赖

依赖方向(从上到下):
视图层 ──→ 业务层 ──→ 数据层 ──→ 工具层
  │          │          │          │
  │    ✅ 可以引用下层       │          │
  │    ❌ 不能引用上层       │          │
  │    ❌ 不能跨层引用       │          │
// ✅ 正确示例:页面组件依赖业务层和数据层
import { useOrder } from '@/hooks/useOrder';           // 业务层 ✅
import { OrderForm } from '@/components/business';     // 视图层 ✅
import type { OrderDTO } from '@/dto/order.dto';        // 数据层 ✅

// ❌ 反例:工具层不能依赖业务层
import { useAuth } from '@/hooks/useAuth'; // ❌ 工具层不能引用业务层

// ❌ 反例:数据层不能引用视图层
import { Button } from '@/components/ui'; // ❌ 数据层不能引用视图层
🎯 腾讯微信支付团队依赖注入实践
// 依赖注入容器(微信支付团队实践)
// 来源:微信前端技术分享 2024

class DIContainer {
  private services = new Map<string, any>();

  register<T>(token: string, factory: () => T) {
    this.services.set(token, factory);
  }

  resolve<T>(token: string): T {
    const factory = this.services.get(token);
    if (!factory) {
      throw new Error(`Service ${token} not registered`);
    }
    return factory();
  }
}

// 服务定位器模式
const container = new DIContainer();

// 业务层注册
container.register('UserService', () => new UserService(
  container.resolve<UserApi>('UserApi'),
  container.resolve<AuthService>('AuthService')
));

// 数据层注册(不依赖业务层)
container.register('UserApi', () => new UserApi(
  container.resolve<ApiClient>('ApiClient')
));

container.register('ApiClient', () => new ApiClient({
  baseURL: ENV.API_BASE_URL,
}));

// 组件中使用(通过 Hook 获取服务)
function useService<T>(token: string): T {
  const serviceRef = useRef<T | null>(null);
  if (!serviceRef.current) {
    serviceRef.current = container.resolve<T>(token);
  }
  return serviceRef.current;
}

// 优点:
// 1. 层级依赖清晰,数据层不知道业务层的存在
// 2. 方便 Mock 测试
// 3. 服务实例化管理,避免重复创建
1.1.3 Monorepo 架构实现

【大型项目标配】pnpm workspace + turborepo 统一管理多应用

monorepo/
├── apps/                     # 应用层
│   ├── web/                   # 主站 C 端(字节抖音 web)
│   ├── admin/                 # 管理后台
│   └── h5/                    # 移动端 H5(抖音小程序)
├── packages/                 # 共享包
│   ├── ui/                    # 通用 UI 组件库(字节 ARES UI)
│   ├── hooks/                 # 共享 Hooks
│   ├── utils/                 # 工具函数
│   ├── types/                 # 类型定义
│   ├── api/                   # 接口 SDK
│   └── config/                # 共享配置(ESLint / TS / Vite)
├── package.json
├── pnpm-workspace.yaml
├── turbo.json                # Turborepo 任务编排
└── tsconfig.base.json
📊 字节跳动 Monorepo 实战数据
【字节 TikTok Web Monorepo 案例】

项目规模:
├── 代码总量:500 万行
├── 应用数量:20+ 个(主站、创作者后台、广告后台等)
├── 团队规模:200+ 前端工程师
├── 包数量:150+ 个

构建性能对比(改造前 vs 改造后):
├── 本地启动:180s → 15s(增量编译)
├── 全量构建:45min → 8min(并行 + 缓存)
├── CI 构建:30min → 5min(turbo cache)
└── 代码检出:10min → 30s(pnpnm + 软链接)

依赖管理优化:
├── 重复依赖:从 120+ 个副本 → 0
├── 安装时间:5min → 45s
└── 磁盘占用:节省 60%
# pnpm-workspace.yaml
packages:
  - 'apps/*'
  - 'packages/*'
// turbo.json - 字节内部优化版本
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"],
      "inputs": ["src/**", "package.json"],
      "env": ["NODE_ENV"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": ["coverage/**"],
      "inputs": ["src/**", "test/**", "*.config.*"]
    },
    "lint": {
      "outputs": [],
      "inputs": ["src/**", "*.config.*", ".eslintrc*"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    },
    // 字节自研增量构建
    "build:incremental": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    }
  },
  // 远程缓存配置(字节内部)
  "remoteCache": {
    "enabled": true,
    "team": "tiktok-web",
    "url": "https://turbo.bytedance.net"
  }
}

1.2 组件架构设计

1.2.1 原子设计理论(Atomic Design)

【组件分层标准】原子 → 分子 → 有机体 → 模板 → 页面

原子(Atoms):最小不可分割 UI 单元
├── Button, Input, Icon, Avatar, Badge, Tag, Spinner

分子(Molecules):原子组合的功能单元
├── SearchBar (Input + Button + Icon)
├── FormField (Label + Input + ErrorMessage)
├── Card (Image + Title + Description + Button)

有机体(Organisms):分子组合的功能模块
├── Header (Logo + Navigation + UserMenu + SearchBar)
├── ProductList (SearchBar + FilterBar + Card[])
├── DataTable (Toolbar + Table + Pagination)

模板(Templates):有机体组合的占位布局
├── DashboardTemplate (Sidebar + Header + Content + Footer)

页面(Pages):填入真实数据的模板实例
├── DashboardPage → DashboardTemplate + Real Data
🎯 阿里 Ant Design 组件分层实践
// 【阿里 Ant Design Pro 组件分层规范】

/**
 * 原子组件(Atoms)- 纯展示,无业务逻辑
 * 位置:@company/ui/atoms/
 *
 * 示例:
 * - <Avatar size="md" src={src} />
 * - <Badge count={5} />
 * - <Icon name="search" />
 */

// 分子组件(Molecules)- 简单组合,原子级业务
// 位置:@company/ui/molecules/
/**
 * 示例:
 * - <SearchInput placeholder="搜索" onSearch={fn} />
 * - <FormField label="用户名" error={errors.name}>
 *     <Input value={value} onChange={onChange} />
 *   </FormField>
 */

// 有机体组件(Organisms)- 完整功能模块
// 位置:@company/ui/organisms/
/**
 * 示例:
 * - <ProductCard product={p} onAddCart={fn} onBuy={fn} />
 * - <UserProfile user={u} onFollow={fn} />
 * - <CommentList comments={c} onReply={fn} />
 */

// 业务组件(Business Components)- 包含特定业务逻辑
// 位置:@company/biz/
/**
 * 示例:
 * - <OrderForm order={o} onSubmit={fn} onCancel={fn} />
 * - <UserSelector orgId={id} value={v} onChange={fn} />
 * - <ProductGrid categoryId={id} />
 */

// 页面组件(Pages)- 组合所有组件
// 位置:apps/admin/src/pages/
/**
 * 示例:
 * - <OrderListPage /> - 订单列表页
 * - <OrderDetailPage id={id} /> - 订单详情页
 */
1.2.2 双库体系:通用组件库 + 业务组件库
┌─────────────────────────────────────────────────────────────┐
│  通用组件库(@company/ui)                                    │
│  ├── 不包含业务逻辑                                            │
│  ├── 跨项目复用、独立发版、完整类型定义                          │
│  └── SemVer 版本管理                                           │
│                                                             │
│  业务组件库(@company/biz)                                    │
│  ├── 包含特定业务逻辑(如 UserSelector、OrderForm)             │
│  ├── 项目内或团队内共享,快速迭代                                │
│  └── 依赖通用组件库                                            │
└─────────────────────────────────────────────────────────────┘
📊 腾讯滨海大厦组件库治理案例
【腾讯微信小程序组件库治理案例】

背景:
├── 微信小程序团队 50+ 前端
├── 10+ 个业务线各自维护组件
├── 组件重复率 > 40%
├── API 不统一,新人学习成本高

解决方案:
├── 统一组件库 @tencent/mp-ui
├── 分为基础组件(60+)和业务组件(120+)
├── 统一 Design Token(颜色、字体、间距)
└── Storybook 文档覆盖率 100%

治理效果:
├── 组件重复率:40% → 5%
├── 新人上手时间:2 周 → 3 天
├── 需求交付效率提升 40%
└── UI 一致性投诉:每月 20+ → 0
// 通用组件示例
// packages/ui/src/Button/types.ts
export interface ButtonProps {
  children: React.ReactNode;
  variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
  size?: 'sm' | 'md' | 'lg';
  loading?: boolean;
  disabled?: boolean;
  block?: boolean;
  leftIcon?: React.ReactNode;
  rightIcon?: React.ReactNode;
  onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
}

// 业务组件示例
// packages/biz/src/UserSelector/types.ts
export interface UserSelectorProps {
  value?: string[];
  onChange?: (userIds: string[]) => void;
  multiple?: boolean;
  maxCount?: number;
  organizationId?: string;  // 业务参数
  excludeUserIds?: string[];
}
1.2.3 组件拆分决策树
是否需要拆分?

├── 组件超过 200 行? → ✅ 拆分
├── 组件有 3+ 种不同业务逻辑? → ✅ 拆分为子组件 + 容器
├── Props 超过 10 个? → ✅ 可能职责太多,考虑聚合
├── 组件嵌套超过 3 层? → ✅ 提取中间层组件
├── 有重复的 UI 模式? → ✅ 提取为通用组件

何时停止拆分?
├── 拆出来的组件 props 只有 0-2 个 → 过度拆分
├── 拆出来的组件完全没有复用价值 → 不要拆分
├── 拆出来的组件代码不到 10 行 → 可能是过度设计
🎯 美团组件拆分实战案例
// 【美团外卖 C 端项目组件拆分案例】

/**
 * 场景:商家详情页,包含商家信息、菜单、评价、优惠券
 *
 * 初始版本(反面教材):
 * 全部代码 2000+ 行,单个组件
 * 问题:
 * - 200+ props
 * - 30+ useEffect
 * - 测试覆盖率 < 10%
 * - 任何改动都可能影响全局
 */

// 重构后的拆分方案:

// 容器组件(Orchestrator)
// 职责:数据获取、状态聚合、事件分发
const MerchantDetailPage = ({ merchantId }) => {
  // 数据获取
  const { data: merchant } = useMerchant(merchantId);
  const { data: menu } = useMenu(merchantId);
  const { data: reviews } = useReviews(merchantId);
  const { data: coupons } = useCoupons(merchantId);

  // 状态
  const [activeTab, setActiveTab] = useState('menu');
  const [selectedSpec, setSelectedSpec] = useState(null);

  // 事件处理
  const handleAddCart = useCallback((item) => {
    cartStore.addItem(item);
    toast.success('已加入购物车');
  }, []);

  const handleBuyNow = useCallback((item) => {
    if (!authStore.isLoggedIn) {
      navigate('/login', { from: `/merchant/${merchantId}` });
      return;
    }
    orderStore.createOrder([item]);
    navigate('/checkout');
  }, [merchantId]);

  // 渲染
  return (
    <div className="merchant-detail">
      <MerchantHeader merchant={merchant} />
      <CouponBanner coupons={coupons} />
      <TabSwitcher
        active={activeTab}
        onChange={setActiveTab}
        tabs={['menu', 'reviews', 'info']}
      />
      {activeTab === 'menu' && (
        <MenuSection
          menu={menu}
          selectedSpec={selectedSpec}
          onSpecChange={setSelectedSpec}
          onAddCart={handleAddCart}
          onBuyNow={handleBuyNow}
        />
      )}
      {activeTab === 'reviews' && (
        <ReviewsSection reviews={reviews} />
      )}
      {activeTab === 'info' && (
        <MerchantInfo merchant={merchant} />
      )}
    </div>
  );
};

// 子组件各自独立,职责单一
const MenuSection = ({
  menu,
  selectedSpec,
  onSpecChange,
  onAddCart,
  onBuyNow,
}) => {
  // 单一职责:只负责菜单展示和交互
  return (
    <div className="menu-section">
      {menu.categories.map(category => (
        <MenuCategory
          key={category.id}
          category={category}
          selectedSpec={selectedSpec}
          onSpecChange={onSpecChange}
          onAddCart={onAddCart}
          onBuyNow={onBuyNow}
        />
      ))}
    </div>
  );
};

const MenuCategory = ({ category, ...props }) => {
  // 单一职责:只负责一个分类的展示
  return (
    <div className="menu-category">
      <h3>{category.name}</h3>
      {category.items.map(item => (
        <MenuItem key={item.id} item={item} {...props} />
      ))}
    </div>
  );
};

const MenuItem = ({ item, onAddCart, onBuyNow }) => {
  // 原子级:只负责单个菜品展示
  return (
    <div className="menu-item">
      <img src={item.image} alt={item.name} />
      <div className="info">
        <h4>{item.name}</h4>
        <p>{item.description}</p>
        <span className="price">¥{item.price}</span>
      </div>
      <div className="actions">
        <Button size="sm" onClick={() => onAddCart(item)}>
          加购
        </Button>
        <Button size="sm" type="primary" onClick={() => onBuyNow(item)}>
          立即购买
        </Button>
      </div>
    </div>
  );
};

// 拆分后的效果:
// ├── 组件平均行数:2000+ → 150(平均)
// ├── 组件最大 props:200+ → 8
// ├── 测试覆盖率:< 10% → 75%+
// └── 需求迭代速度:提升 3 倍

1.3 路由架构设计

1.3.1 权限路由体系(三层权限架构)

【安全第一】菜单权限 → 路由权限 → 接口权限 三层防护

// 路由权限配置
type RouteConfig = {
  path: string;
  element: React.LazyComponent;
  permissions?: string[];   // 路由级权限
  children?: RouteConfig[];
  meta?: {
    title: string;
    icon?: string;
    hidden?: boolean;
    keepAlive?: boolean;
  };
};

const routeConfig: RouteConfig[] = [
  {
    path: '/system',
    element: SystemLayout,
    permissions: ['system:access'],
    meta: { title: '系统管理' },
    children: [
      {
        path: 'users',
        element: UserManagement,
        permissions: ['system:users:view'],
        meta: { title: '用户管理' },
      },
      {
        path: 'roles',
        element: RoleManagement,
        permissions: ['system:roles:view'],
        meta: { title: '角色管理' },
      },
    ],
  },
];

// 前端路由守卫(UX 优化,真正安全在后端)
function ProtectedRoute({ requiredPermissions = [] }: { requiredPermissions: string[] }) {
  const permissions = useUserPermissions();
  const location = useLocation();

  const hasAccess = requiredPermissions.every(p => permissions.includes(p));
  if (!hasAccess) return <Navigate to="/403" state={{ from: location }} replace />;

  return <Outlet />;
}

// 后端接口守卫(真正的安全防线)
// 每个 API 请求都携带 token,后端验证权限
🎯 京东到家权限路由实战案例
/**
 * 【京东到家到家业务权限系统】
 *
 * 背景:
 * - 10+ 角色(商家、配送员、客服、运营、管理员等)
 * - 200+ 页面路由
 * - 权限粒度:页面级 + 按钮级 + 数据级
 *
 * 挑战:
 * - 权限配置频繁变更
 * - 需要实时生效(不能靠前端发版)
 * - 兼容历史系统(多套权限体系并存)
 */

interface Permission {
  code: string;           // 'order:view'
  name: string;           // '查看订单'
  type: 'menu' | 'button' | 'api';  // 权限类型
  children?: Permission[]; // 子权限
}

// 权限树结构
const permissionTree: Permission[] = [
  {
    code: 'order',
    name: '订单管理',
    type: 'menu',
    children: [
      { code: 'order:view', name: '查看订单', type: 'button' },
      { code: 'order:edit', name: '编辑订单', type: 'button' },
      { code: 'order:export', name: '导出订单', type: 'button' },
      { code: 'order:api', name: '订单接口', type: 'api' },
    ],
  },
];

// 权限 Hook(带缓存和防抖)
function usePermissions() {
  const { data: permissions, isLoading } = useQuery({
    queryKey: ['user-permissions'],
    queryFn: () => api.getPermissions(),
    staleTime: 5 * 60 * 1000, // 5 分钟缓存
    refetchInterval: 10 * 60 * 1000, // 10 分钟轮询(权限变更实时生效)
  });

  const hasPermission = useCallback((code: string) => {
    if (!permissions) return false;
    return flatPermissions(permissions).some(p => p.code === code);
  }, [permissions]);

  return { permissions, hasPermission, isLoading };
}

// 路由守卫(带加载状态)
function ProtectedRoute({ permission, children }) {
  const { hasPermission, isLoading } = usePermissions();
  const location = useLocation();

  if (isLoading) {
    return <PageSkeleton />;
  }

  if (!hasPermission(permission)) {
    return <Navigate to="/no-permission" state={{ from: location }} replace />;
  }

  return children;
}

// 按钮级权限控制
function AuthorizedButton({ permission, ...props }) {
  const { hasPermission } = usePermissions();

  if (!hasPermission(permission)) {
    return null;
  }

  return <Button {...props} />;
}

// 使用示例
const OrderListPage = () => {
  return (
    <div>
      <h1>订单列表</h1>

      {/* 工具栏:根据权限显示按钮 */}
      <div className="toolbar">
        <AuthorizedButton
          permission="order:export"
          icon="export"
          onClick={handleExport}
        >
          导出
        </AuthorizedButton>
        <AuthorizedButton
          permission="order:create"
          type="primary"
          onClick={handleCreate}
        >
          新建订单
        </AuthorizedButton>
      </div>

      {/* 表格:根据权限显示操作列 */}
      <Table
        columns={[
          { dataIndex: 'id', title: '订单号' },
          { dataIndex: 'status', title: '状态' },
          {
            title: '操作',
            render: (_, record) => (
              <>
                <AuthorizedButton
                  permission="order:view"
                  link
                  onClick={() => navigate(`/orders/${record.id}`)}
                >
                  查看
                </AuthorizedButton>
                <AuthorizedButton
                  permission="order:edit"
                  link
                  onClick={() => handleEdit(record.id)}
                >
                  编辑
                </AuthorizedButton>
              </>
            ),
          },
        ]}
      />
    </div>
  );
};

// 权限变更实时生效(WebSocket 推送)
useEffect(() => {
  const ws = new WebSocket(`wss://api.example.com/permissions?token=${token}`);

  ws.onmessage = (event) => {
    const { type, data } = JSON.parse(event.data);

    if (type === 'permission_changed') {
      // 权限变更:刷新缓存
      queryClient.invalidateQueries(['user-permissions']);

      // 如果当前用户失去了访问当前页面的权限
      if (!hasCurrentPagePermission(data.permissions)) {
        toast.warning('您的权限已变更,部分页面将无法访问');
      }
    }
  };

  return () => ws.close();
}, []);
1.3.2 分层层级懒加载
// 页面级懒加载(路由按需)
const Dashboard = lazy(() => import('@/views/Dashboard'));
const UserList = lazy(() => import('@/views/User/List'));

// 组件级懒加载(大组件按需)
const RichEditor = lazy(() => import('@/components/Editor/RichText'));

// Tab 切换时懒加载(避免挂载时全部加载)
function TabContainer({ tabs }) {
  const [loadedTabs, setLoadedTabs] = useState(new Set([tabs[0].key]));

  const handleTabChange = (key: string) => {
    setLoadedTabs(set => new Set([...set, key]));
  };

  return (
    <Tabs onChange={handleTabChange}>
      {tabs.map(tab => (
        <TabPane key={tab.key} tab={tab.title}>
          {loadedTabs.has(tab.key) ? <tab.Component /> : <Skeleton />}
        </TabPane>
      ))}
    </Tabs>
  );
}
🎯 拼多多首页懒加载实战
/**
 * 【拼多多首页性能优化案例】
 *
 * 背景:
 * - 首页 100+ 个组件
 * - 首屏加载时间 4.5s(用户流失率高)
 * - 目标:首屏加载 < 1.5s
 *
 * 优化策略:分层次懒加载
 */

// 第一层:核心骨架(立即加载)
// 包含:Header、搜索栏、首屏商品
const HomePage = () => {
  return (
    <div className="home-page">
      {/* 同步加载:Header + 搜索 + 底部导航 */}
      <Header />
      <SearchBar />
      <Suspense fallback={<HomeSkeleton />}>
        <HeroBanner />  {/* 首屏轮播图 */}
      </Suspense>

      {/* 第二层:Suspense 流式加载 */}
      <Suspense fallback={<FlashSaleSkeleton />}>
        <FlashSaleSection />  {/* 限时秒杀 */}
      </Suspense>

      <Suspense fallback={<RecommendSkeleton />}>
        <RecommendSection />  {/* 推荐商品 */}
      </Suspense>

      {/* 第三层:用户视口触发加载 */}
      <LazySection
        placeholder={<CategorySkeleton />}
        component={CategorySection}
      />

      <Suspense fallback={<TopicSkeleton />}>
        <TopicSection />  {/* 话题区 */}
      </Suspense>

      <BottomNav />
    </div>
  );
};

// 视口触发加载 Hook
function LazySection({ component: Component, placeholder }) {
  const [isVisible, setIsVisible] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setIsVisible(true);
          observer.disconnect();
        }
      },
      { rootMargin: '200px' } // 提前 200px 开始加载
    );

    if (ref.current) {
      observer.observe(ref.current);
    }

    return () => observer.disconnect();
  }, []);

  return (
    <div ref={ref}>
      {isVisible ? (
        <Suspense fallback={placeholder}>
          <Component />
        </Suspense>
      ) : placeholder}
    </div>
  );
}

// 优化效果:
// - 首屏加载:4.5s → 1.2s
// - 可交互时间:3.8s → 0.8s
// - 用户流失率:下降 35%

1.4 状态架构设计

1.4.1 四层状态架构

**【分层原则】**不同类型的状态,不同的管理方案

┌─────────────────────────────────────────────────────────────┐
│  第零层:URL 状态(路由参数、查询参数)                         │
│  ├── 可分享 / 可收藏                                           │
│  ├── 管理:React Router / URL                                 │
│  └── 示例:搜索词、页面 ID、筛选条件                             │
│                                                             │
│  第一层:服务器状态(API 数据)                                  │
│  ├── 来源:服务端,需要缓存和同步                                 │
│  ├── 管理:React Query / SWR                                  │
│  └── 示例:用户列表、订单详情                                    │
│                                                             │
│  第二层:全局状态(跨模块/页面共享)                              │
│  ├── 管理:Zustand / Redux Toolkit                            │
│  └── 示例:用户信息、通知数量、主题/语言                          │
│                                                             │
│  第三层:局部状态(组件内部)                                     │
│  ├── 管理:useState / useReducer                              │
│  └── 示例:表单输入、弹窗状态、展开/折叠                          │
└─────────────────────────────────────────────────────────────┘
🎯 网易云音乐状态架构实战
/**
 * 【网易云音乐播放器状态架构】
 *
 * 场景:播放器需要在页面任何角落都能控制
 * 状态类型:
 * - 全局状态:当前播放歌曲、播放列表、播放模式
 * - 服务器状态:歌曲信息、歌词、评论
 * - URL 状态:当前歌曲 ID(可分享)
 * - 局部状态:播放器展开/收起、歌词滚动位置
 */

interface PlayerState {
  // 全局播放器状态(Zustand)
  currentSong: Song | null;
  playlist: Song[];
  playMode: 'sequence' | 'repeat' | 'random';
  volume: number;
  isPlaying: boolean;
  currentTime: number;
  duration: number;
}

interface PlayerStore extends PlayerState {
  // Actions
  play: (song: Song) => void;
  pause: () => void;
  togglePlay: () => void;
  setPlaylist: (songs: Song[]) => void;
  addToPlaylist: (song: Song) => void;
  removeFromPlaylist: (songId: string) => void;
  setPlayMode: (mode: PlayMode) => void;
  setVolume: (volume: number) => void;
  seek: (time: number) => void;
  playNext: () => void;
  playPrev: () => void;
}

const usePlayerStore = create<PlayerStore>((set, get) => ({
  currentSong: null,
  playlist: [],
  playMode: 'sequence',
  volume: 0.8,
  isPlaying: false,
  currentTime: 0,
  duration: 0,

  play: (song) => set({ currentSong: song, isPlaying: true }),
  pause: () => set({ isPlaying: false }),
  togglePlay: () => set((state) => ({ isPlaying: !state.isPlaying })),

  playNext: () => {
    const { playlist, currentSong, playMode } = get();
    const currentIndex = playlist.findIndex(s => s.id === currentSong?.id);

    let nextIndex;
    if (playMode === 'random') {
      nextIndex = Math.floor(Math.random() * playlist.length);
    } else {
      nextIndex = (currentIndex + 1) % playlist.length;
    }

    if (playlist[nextIndex]) {
      set({ currentSong: playlist[nextIndex], isPlaying: true });
    }
  },
}));

/**
 * 播放器全局状态使用 Hook
 * 在任何组件中都能访问和操作播放器
 */
function usePlayer() {
  const store = usePlayerStore();

  // 带本地状态的状态(不触发重渲染的辅助状态)
  const actionsRef = useRef({
    play: store.play,
    pause: store.pause,
    // ...
  });

  return store;
}

/**
 * 歌曲详情页 - 混合状态架构
 */
const SongDetailPage = ({ songId }) => {
  // URL 状态:当前歌曲 ID
  const { songId } = useParams();

  // 服务器状态:歌曲详情、歌词、评论(React Query)
  const { data: songDetail } = useQuery({
    queryKey: ['song-detail', songId],
    queryFn: () => api.getSongDetail(songId),
  });

  const { data: lyrics } = useQuery({
    queryKey: ['song-lyrics', songId],
    queryFn: () => api.getLyrics(songId),
  });

  // 全局播放器状态
  const player = usePlayer();

  // 局部状态:评论展开/收起
  const [showAllComments, setShowAllComments] = useState(false);

  // 播放歌曲(更新全局状态)
  const handlePlay = () => {
    player.play(songDetail);
  };

  return (
    <div>
      <SongInfo song={songDetail} />
      <Lyrics lyrics={lyrics} currentTime={player.currentTime} />
      <Comments
        songId={songId}
        expanded={showAllComments}
        onToggle={() => setShowAllComments(!showAllComments)}
      />
      <PlayButton onClick={handlePlay} />
    </div>
  );
};
1.4.2 跨 Tab/跨窗口 状态同步
// BroadcastChannel API(同源页面间通信)
function useCrossTabState<T>(key: string, initialValue: T) {
  const [value, setValue] = useState<T>(initialValue);
  const channelRef = useRef<BroadcastChannel>();

  useEffect(() => {
    const channel = new BroadcastChannel('app-state');
    channelRef.current = channel;

    channel.onmessage = (e) => {
      if (e.data.key === key) {
        setValue(e.data.value);
      }
    };

    return () => channel.close();
  }, [key]);

  const setCrossTabValue = (newValue: T) => {
    setValue(newValue);
    channelRef.current?.postMessage({ key, value: newValue });
  };

  return [value, setCrossTabValue] as const;
}
🎯 蚂蚁金服跨 Tab 状态同步案例
/**
 * 【蚂蚁金服 OceanBase 控制台跨 Tab 案例】
 *
 * 场景:
 * - 用户在 Tab A 修改了某条配置
 * - Tab B 需要实时感知变更
 * - 不刷新页面,保持状态同步
 *
 * 解决方案:BroadcastChannel + 后端推送
 */

interface SyncState {
  type: 'create' | 'update' | 'delete';
  entity: 'config' | 'user' | 'permission';
  entityId: string;
  data: any;
  timestamp: number;
  operator: string;
}

// 跨 Tab 同步 Hook
function useCrossTabSync(entityType: string) {
  const [syncQueue, setSyncQueue] = useState<SyncState[]>([]);
  const channelRef = useRef<BroadcastChannel>();
  const queryClient = useQueryClient();

  useEffect(() => {
    // 1. 建立 Tab 间通信
    const channel = new BroadcastChannel(`oceanbase:${entityType}`);
    channelRef.current = channel;

    channel.onmessage = (event: MessageEvent<SyncState>) => {
      const syncState = event.data;

      // 2. 更新本地缓存
      queryClient.setQueryData(
        [`${entityType}-list`],
        (oldData: any[]) => {
          if (!oldData) return oldData;

          switch (syncState.type) {
            case 'create':
              return [...oldData, syncState.data];
            case 'update':
              return oldData.map(item =>
                item.id === syncState.entityId ? syncState.data : item
              );
            case 'delete':
              return oldData.filter(item => item.id !== syncState.entityId);
            default:
              return oldData;
          }
        }
      );

      // 3. 显示同步提示
      toast.info(
        `${syncState.operator} ${syncState.type === 'create' ? '创建' : syncState.type === 'update' ? '更新' : '删除'}了一条配置`
      );

      // 4. 更新同步队列(用于审计)
      setSyncQueue(prev => [...prev.slice(-50), syncState]);
    };

    return () => channel.close();
  }, [entityType, queryClient]);

  // 广播变更到其他 Tab
  const broadcastChange = (syncState: SyncState) => {
    channelRef.current?.postMessage(syncState);
  };

  return { syncQueue, broadcastChange };
}

/**
 * 配置列表页
 */
const ConfigListPage = () => {
  const { data: configs, refetch } = useQuery({
    queryKey: ['config-list'],
    queryFn: () => api.getConfigs(),
  });

  const { broadcastChange } = useCrossTabSync('config');

  const handleUpdate = async (config: Config) => {
    const updated = await api.updateConfig(config);

    // 1. 更新本地
    queryClient.setQueryData(['config-list'], (old: Config[]) =>
      old.map(c => c.id === updated.id ? updated : c)
    );

    // 2. 广播到其他 Tab
    broadcastChange({
      type: 'update',
      entity: 'config',
      entityId: updated.id,
      data: updated,
      timestamp: Date.now(),
      operator: getCurrentUser().name,
    });
  };

  return <ConfigTable data={configs} onUpdate={handleUpdate} />;
};

1.5 可扩展性设计

1.5.1 插件化架构(生命周期钩子)
// 表单插件引擎
interface FormPlugin {
  name: string;
  priority: number;
  beforeSubmit?: (data: any) => Promise<any>;
  afterSubmit?: (result: any) => void;
  onChange?: (field: string, value: any, formData: any) => void;
}

class FormPluginEngine {
  private plugins: FormPlugin[] = [];

  register(plugin: FormPlugin) {
    this.plugins = [...this.plugins, plugin].sort(
      (a, b) => b.priority - a.priority
    );
  }

  async executeLifecycle(phase: keyof FormPlugin, data: any) {
    for (const plugin of this.plugins) {
      const hook = plugin[phase];
      if (hook) data = await hook(data);
    }
    return data;
  }
}

// 使用:各业务模块注册自己的插件
const analyticsPlugin: FormPlugin = {
  name: 'analytics',
  priority: 1,
  afterSubmit: (result) => track('form_submit', result),
};

const validationPlugin: FormPlugin = {
  name: 'validation',
  priority: 10,
  beforeSubmit: async (data) => {
    // 统一校验
    return data;
  },
};
🎯 有赞微商城表单插件化实践
/**
 * 【有赞微商城表单配置化实践】
 *
 * 场景:
 * - 商家后台有 50+ 种表单(订单信息、商品编辑、客户管理等)
 * - 每个表单有不同的校验规则、业务逻辑
 * - 表单引擎需要支持插件扩展
 *
 * 解决方案:表单插件化架构
 */

// 插件接口定义
interface FormPlugin<FormData = any, PluginContext = any> {
  name: string;
  version: string;

  // 生命周期钩子
  beforeInit?: (ctx: PluginContext) => void;
  afterInit?: (form: FormInstance<FormData>, ctx: PluginContext) => void;

  beforeSubmit?: (
    data: FormData,
    ctx: PluginContext
  ) => Promise<FormData | { valid: false; errors: Record<string, string> }>;
  afterSubmit?: (
    result: any,
    ctx: PluginContext
  ) => void;

  onFieldChange?: (
    field: string,
    value: any,
    form: FormInstance<FormData>,
    ctx: PluginContext
  ) => void;

  beforeReset?: (ctx: PluginContext) => void;
}

// 表单引擎核心
class FormEngine<FormData = any> {
  private plugins: FormPlugin<FormData>[] = [];
  private formInstance: FormInstance<FormData> | null = null;

  use(plugin: FormPlugin<FormData>) {
    this.plugins.push(plugin);
    return this;
  }

  async init(initialData: FormData) {
    // 初始化上下文
    const ctx = { timestamp: Date.now(), requestId: generateId() };

    // beforeInit
    for (const plugin of this.plugins) {
      await plugin.beforeInit?.(ctx);
    }

    // 创建表单实例
    this.formInstance = createFormInstance(initialData);

    // 注入插件能力
    this.formInstance.use({
      onValuesChange: (changedValues, allValues) => {
        for (const plugin of this.plugins) {
          Object.entries(changedValues).forEach(([field, value]) => {
            plugin.onFieldChange?.(field, value, this.formInstance!, ctx);
          });
        }
      },
    });

    // afterInit
    for (const plugin of this.plugins) {
      await plugin.afterInit?.(this.formInstance, ctx);
    }

    return this.formInstance;
  }

  async submit() {
    const ctx = { timestamp: Date.now() };
    let data = this.formInstance!.getFieldsValue();

    // beforeSubmit 链式调用
    for (const plugin of this.plugins) {
      const result = await plugin.beforeSubmit?.(data, ctx);

      if (result && 'valid' in result && !result.valid) {
        return { success: false, errors: result.errors };
      }

      data = result as FormData;
    }

    // 实际提交
    const response = await api.submit(data);

    // afterSubmit
    for (const plugin of this.plugins) {
      await plugin.afterSubmit?.(response, ctx);
    }

    return { success: true, data: response };
  }
}

// 业务插件示例
const orderFormPlugins: FormPlugin<OrderFormData>[] = [
  // 1. 订单号自动生成插件
  {
    name: 'order-number-generator',
    version: '1.0.0',
    afterInit: (form) => {
      const orderNo = generateOrderNo();
      form.setFieldsValue({ orderNo });
      form.setFieldDisabled('orderNo', true);
    },
  },

  // 2. 库存校验插件
  {
    name: 'inventory-validator',
    version: '1.0.0',
    async beforeSubmit(data) {
      const inventoryCheck = await api.checkInventory(data.items);
      if (!inventoryCheck.sufficient) {
        return {
          valid: false,
          errors: {
            items: `商品 ${inventoryCheck.insufficientItems.join(', ')} 库存不足`,
          },
        };
      }
      return data;
    },
  },

  // 3. 价格计算插件
  {
    name: 'price-calculator',
    version: '1.0.0',
    onFieldChange: (field, value, form) => {
      if (field === 'items' || field === 'discount') {
        const items = form.getFieldValue('items');
        const discount = form.getFieldValue('discount') || 0;
        const subtotal = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
        const total = subtotal - discount;
        form.setFieldsValue({ subtotal, total });
      }
    },
  },

  // 4. 数据分析插件
  {
    name: 'analytics',
    version: '1.0.0',
    afterSubmit: (result) => {
      analytics.track('order_created', {
        orderId: result.id,
        amount: result.total,
        itemCount: result.items.length,
      });
    },
  },

  // 5. 操作日志插件
  {
    name: 'audit-log',
    version: '1.0.0',
    async afterSubmit(result, ctx) {
      await api.logOperation({
        action: 'create_order',
        entityId: result.id,
        operator: getCurrentUser().id,
        timestamp: ctx.timestamp,
        data: result,
      });
    },
  },
];

// 使用
const OrderForm = () => {
  const formRef = useRef<FormInstance>();

  useEffect(() => {
    const engine = new FormEngine<OrderFormData>();

    // 链式注册插件
    orderFormPlugins.forEach(plugin => engine.use(plugin));

    engine.init({}).then(form => {
      formRef.current = form;
    });
  }, []);

  const handleSubmit = async () => {
    const engine = new FormEngine<OrderFormData>();
    orderFormPlugins.forEach(plugin => engine.use(plugin));

    const result = await engine.submit();
    if (result.success) {
      toast.success('订单创建成功');
      navigate('/orders');
    }
  };

  return <Form ref={formRef} onSubmit={handleSubmit} />;
};

// 插件市场(未来扩展)
const pluginRegistry = {
  register: (plugin: FormPlugin) => { /* ... */ },
  get: (name: string) => { /* ... */ },
  list: () => { /* ... */ },
};
1.5.2 适配器模式(多版本 API 兼容)
// ✅ V1 / V2 / V3 API 不同数据结构统一处理
interface UserV1 { userName: string; userAge: number; }
interface UserV2 { name: string; age: number; }

interface User { name: string; age: number; }

const apiAdapters = {
  v1: { toUser: (d: UserV1): User => ({ name: d.userName, age: d.userAge }) },
  v2: { toUser: (d: UserV2): User => ({ name: d.name, age: d.age }) },
};

function normalizeUser(apiVersion: string, rawData: any): User {
  const adapter = apiAdapters[apiVersion];
  if (!adapter) throw new Error(`Unknown API version: ${apiVersion}`);
  return adapter.toUser(rawData);
}
🎯 滴滴出行多版本 API 适配案例
/**
 * 【滴滴出行乘客端 API 版本适配案例】
 *
 * 背景:
 * - 滴滴 API 经历多次重构(v1 → v2 → v3 → v4)
 * - iOS/Android/Web 多端共用一套适配层
 * - 历史版本 APP 仍需兼容
 *
 * 解决方案:适配器模式 + 版本协商
 */

// 原始 API 响应类型
interface RawOrderV1 {
  order_no: string;
  driver_name: string;
  car_no: string;
  status: 0 | 1 | 2 | 3;
  create_time: number;
}

interface RawOrderV2 {
  orderId: string;
  driverName: string;
  carNumber: string;
  status: 'pending' | 'confirmed' | 'arrived' | 'completed';
  createdAt: string;
}

interface RawOrderV3 {
  id: string;
  driver: {
    name: string;
    avatar: string;
  };
  vehicle: {
    plateNumber: string;
    model: string;
  };
  status: string;
  createdAt: string;
}

// 统一内部数据类型
interface Order {
  id: string;
  driverName: string;
  driverAvatar?: string;
  vehiclePlate: string;
  vehicleModel?: string;
  status: 'pending' | 'confirmed' | 'arrived' | 'completed';
  createdAt: Date;
}

// 适配器映射
const orderAdapters: Record<string, (raw: any) => Order> = {
  v1: (raw: RawOrderV1): Order => ({
    id: raw.order_no,
    driverName: raw.driver_name,
    vehiclePlate: raw.car_no,
    status: ['', 'pending', 'confirmed', 'arrived', 'completed'][raw.status],
    createdAt: new Date(raw.create_time * 1000),
  }),

  v2: (raw: RawOrderV2): Order => ({
    id: raw.orderId,
    driverName: raw.driverName,
    vehiclePlate: raw.carNumber,
    status: raw.status,
    createdAt: new Date(raw.createdAt),
  }),

  v3: (raw: RawOrderV3): Order => ({
    id: raw.id,
    driverName: raw.driver.name,
    driverAvatar: raw.driver.avatar,
    vehiclePlate: raw.vehicle.plateNumber,
    vehicleModel: raw.vehicle.model,
    status: raw.status as Order['status'],
    createdAt: new Date(raw.createdAt),
  }),
};

// API 客户端(带版本协商)
class OrderApiClient {
  private baseURL: string;
  private version: string;

  constructor(baseURL: string) {
    this.baseURL = baseURL;
    this.version = 'v4'; // 默认最新版本
  }

  // 版本协商:与服务端协商使用最优版本
  async negotiateVersion(): Promise<string> {
    try {
      const response = await fetch(`${this.baseURL}/api/version`);
      const { optimalVersion } = await response.json();
      this.version = optimalVersion;
      return this.version;
    } catch {
      return this.version; // 降级到默认版本
    }
  }

  async getOrder(orderId: string): Promise<Order> {
    const response = await fetch(`${this.baseURL}/api/orders/${orderId}`, {
      headers: {
        'X-Api-Version': this.version,
      },
    });

    if (response.status === 406) {
      // 服务端不支持当前版本,尝试协商
      await this.negotiateVersion();
      return this.getOrder(orderId); // 递归重试
    }

    const raw = await response.json();
    const adapter = orderAdapters[this.version];

    if (!adapter) {
      throw new Error(`Unsupported API version: ${this.version}`);
    }

    return adapter(raw);
  }

  async getOrders(): Promise<Order[]> {
    const response = await fetch(`${this.baseURL}/api/orders`, {
      headers: {
        'X-Api-Version': this.version,
      },
    });

    const raws: any[] = await response.json();
    const adapter = orderAdapters[this.version];

    return raws.map(raw => adapter(raw));
  }
}

// 使用
const apiClient = new OrderApiClient('https://api.diditaxi.com');

function OrderList() {
  const [orders, setOrders] = useState<Order[]>([]);

  useEffect(() => {
    apiClient.getOrders().then(setOrders);
  }, []);

  return (
    <div>
      {orders.map(order => (
        <OrderCard key={order.id} order={order} />
      ))}
    </div>
  );
}

// 效果:
// - 多版本兼容:从 v1 到 v4 全部兼容
// - 无感知升级:用户始终使用最优版本
// - 故障恢复:版本协商失败时自动降级

二、大型应用解决方案

2.1 微前端架构

2.1.1 方案对比与选型
维度 qiankun Module Federation wujie
CSS 隔离 Shadow DOM 实验性 需手动处理 iframe 天然隔离
JS 隔离 Proxy 沙箱 共享全局 iframe 天然隔离
通信 全局状态 + 事件 共享模块 postMessage
子应用独立 ✅ 独立开发部署 ⚠️ 部分耦合 ✅ 独立开发部署
性能 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐
应用场景 历史系统改造 新项目 跨技术栈
2.1.2 qiankun 主应用注册
import { registerMicroApps, start, initGlobalState } from 'qiankun';

// 全局状态(主/子应用共享)
const actions = initGlobalState({ user: null, theme: 'light' });

registerMicroApps([
  {
    name: 'app-dashboard',
    entry: `//localhost:3001`,
    container: '#subapp-dashboard',
    activeRule: '/dashboard',
    props: {
      mainApp: {
        navigate: (path: string) => router.push(path),
        getToken: () => localStorage.getItem('token'),
      },
    },
  },
]);

start({ prefetch: true });
2.1.3 跨应用通信方式矩阵
// 方式 1:qiankun 全局状态(推荐)
actions.setGlobalState({ ...actions.getGlobalState(), theme: 'dark' });

// 方式 2:自定义事件总线
const MicroEventBus = {
  events: new Map<string, Function[]>(),
  on(event: string, handler: Function) {
    if (!this.events.has(event)) this.events.set(event, []);
    this.events.get(event)!.push(handler);
  },
  emit(event: string, data?: any) {
    this.events.get(event)?.forEach(h => h(data));
  },
};

// 方式 3:URL 参数变量(最简单,适合轻量通信)
// 主应用:router.push('/dashboard?tab=analytics')
// 子应用:useSearchParams() 读取
🎯 阿里云主机控制台微前端实战案例
/**
 * 【阿里云控制台微前端架构实战】
 *
 * 背景:
 * - 阿里云控制台 50+ 产品,每个产品独立团队维护
 * - 技术栈不统一:React 15/16/18、Vue 2/3、Angular
 * - 需要统一导航、权限、体验
 * - 日活 100 万+,稳定性要求极高
 *
 * 挑战:
 * - 子应用独立部署,独立技术栈
 * - 主应用需要协调子应用生命周期
 * - 跨应用状态共享(用户信息、权限、主题)
 * - 样式冲突隔离
 */

import { registerMicroApps, start, setDefaultMountApp, initGlobalState } from 'qiankun';
import { loading } from '@apollo/loading';

// 1. 主应用状态管理(qiankun 全局状态)
const initialState = {
  user: null,
  region: 'cn-hangzhou',
  theme: 'light',
  locale: 'zh-CN',
};

const actions = initGlobalState(initialState);

// 状态变更监听
actions.onGlobalStateChange((state, prev) => {
  console.log('[主应用] 状态变更:', state, '上一个状态:', prev);
  
  // 同步到 localStorage(跨 Tab 共享)
  localStorage.setItem('main-state', JSON.stringify(state));
});

// 2. 子应用注册配置
const microApps = [
  {
    name: 'ecs',  // 云服务器控制台
    entry: '//ecs.aliyun.com',
    container: '#subapp-container',
    activeRule: '/ecs',
    props: {
      mainState: initialState,
      onStateChange: (state) => actions.setGlobalState(state),
    },
  },
  {
    name: 'rds',  // 云数据库控制台
    entry: '//rds.aliyun.com',
    container: '#subapp-container',
    activeRule: '/rds',
  },
  {
    name: 'slb',  // 负载均衡
    entry: '//slb.aliyun.com',
    container: '#subapp-container',
    activeRule: '/slb',
  },
];

// 3. 子应用生命周期管理
registerMicroApps(microApps, {
  beforeLoad: [
    async (app) => {
      console.log(`[主应用] 准备加载: ${app.name}`);
      
      // 显示 loading
      loading.show(app.name);
      
      // 预检查:验证用户权限
      const hasPermission = await checkSubappPermission(app.name);
      if (!hasPermission) {
        throw new Error(`无权限访问 ${app.name}`);
      }
    },
  ],
  beforeMount: [
    async (app) => {
      console.log(`[主应用] 准备挂载: ${app.name}`);
      
      // 同步主题到子应用
      const theme = localStorage.getItem('theme') || 'light';
      window.__POWERED_BY_QIANKUN__ && (document.documentElement.dataset.theme = theme);
    },
  ],
  afterMount: [
    async (app) => {
      console.log(`[主应用] 挂载完成: ${app.name}`);
      loading.hide(app.name);
      
      // 发送欢迎消息
      app.container.contentWindow.postMessage({
        type: 'MAIN_APP_READY',
        payload: { timestamp: Date.now() }
      }, '*');
    },
  ],
  afterUnmount: [
    async (app) => {
      console.log(`[主应用] 卸载完成: ${app.name}`);
      loading.hide(app.name);
    },
  ],
});

// 4. 启动配置
start({
  prefetch: ['ecs', 'rds'],  // 预加载常用子应用
  jsSandbox: true,           // 启用 JS 沙箱隔离
  singular: false,            // 多实例模式(部分子应用需要)
});

// 5. 降级策略:当微前端失效时,降级到 iframe
const fallbackContainer = document.getElementById('subapp-container');

function renderWithFallback(name, entry) {
  start(); // 先尝试微前端
  
  // 5 秒后未挂载,启用 iframe 降级
  setTimeout(() => {
    if (!fallbackContainer.innerHTML) {
      console.warn(`[主应用] ${name} 加载超时,启用 iframe 降级`);
      fallbackContainer.innerHTML = `
        <iframe 
          src="${entry}" 
          style="width:100%;height:100%;border:none;"
          sandbox="allow-scripts allow-same-origin allow-forms"
        ></iframe>
      `;
    }
  }, 5000);
}

// 6. 跨应用通信:主应用向子应用发消息
function notifySubapp(subappName: string, event: string, data: any) {
  const microApp = Array.from(document.querySelectorAll('[data-name]'))
    .find(el => el.getAttribute('data-name') === subappName);
  
  if (microApp) {
    microApp.contentWindow.postMessage({ event, payload: data }, '*');
  }
}

// 7. 跨应用通信:子应用向主应用发消息
window.addEventListener('message', (event) => {
  if (event.data.type === 'SUBAPP_READY') {
    console.log(`[主应用] 收到子应用 ${event.source} 就绪`);
  }
  
  if (event.data.type === 'NAVIGATE') {
    // 子应用请求主应用跳转
    router.push(event.data.payload.path);
  }
});

// 8. 全局错误处理
window.addEventListener('unhandledrejection', (event) => {
  // 上报未处理的 Promise 错误
  Sentry.captureException(event.reason, {
    tags: { type: 'unhandledrejection' },
  });
});

// 效果:
// - 50+ 子应用独立部署,发布时间从周级 → 天级
// - 技术栈可以逐步演进,无需大规模重写
// - 用户体验统一,切换产品无需刷新页面
🎯 字节跳动 Web Mart 微前端治理案例
/**
 * 【字节跳动 Web Mart 微前端治理案例】
 *
 * 背景:
 * - Web Mart 是一个大型 B 端业务平台
 * - 30+ 个子应用,包含订单、库存、营销、用户等模块
 * - 团队 100+ 前端工程师
 * - 日活 10 万+
 *
 * 问题:
 * - 子应用之间样式冲突严重(全局 CSS 污染)
 * - 子应用加载慢,首屏 5s+
 * - 依赖版本不统一,导致冲突
 * - 子应用之间通信混乱
 */

import { registerMicroApps, start } from 'qiankun';

// 1. CSS 隔离策略(严格模式)
start({
  prefetch: 'all',
  jsSandbox: {
    strictStyleIsolation: true,  // 严格样式隔离(每个子应用 Shadow DOM)
    experimentalStyleIsolation: true,  // 实验性:给子应用元素添加随机前缀
  },
});

// 2. 依赖统一管理(解决版本冲突)
// 在主应用中统一管理基础依赖版本
const UNIFIED_VERSIONS = {
  'react': '18.2.0',
  'react-dom': '18.2.0',
  'react-router-dom': '6.11.0',
  'zustand': '4.3.8',
};

// 子应用需要声明自己依赖的版本
interface SubappManifest {
  name: string;
  version: string;
  dependencies: Record<string, string>;
  entry: string;
}

// 3. 资源预加载策略(首屏优化)
class SubappPrefetcher {
  private prefetchQueue: Set<string> = new Set();
  private loadingApps: Set<string> = new Set();
  
  // 根据用户行为预测预加载
  predictAndPrefetch(userId: string) {
    // 分析用户历史访问,预测可能访问的子应用
    const prediction = this.predictSubapps(userId);
    
    prediction.forEach(appName => {
      if (!this.prefetchQueue.has(appName)) {
        this.prefetch(appName);
      }
    });
  }
  
  private predictSubapps(userId: string): string[] {
    // 简化的预测逻辑:基于用户角色
    const userRole = getUserRole(userId);
    
    if (userRole === 'admin') {
      return ['user', 'order', 'product', 'analytics'];
    } else if (userRole === 'operator') {
      return ['order', 'inventory'];
    } else {
      return ['order'];
    }
  }
  
  private prefetch(appName: string) {
    if (this.loadingApps.has(appName)) return;
    this.loadingApps.add(appName);
    
    // 使用 link rel="prefetch"
    const link = document.createElement('link');
    link.rel = 'prefetch';
    link.href = `${getSubappEntry(appName)}/asset-manifest.json`;
    link.as = 'fetch';
    document.head.appendChild(link);
  }
}

// 4. 子应用健康检查与自动恢复
class SubappHealthChecker {
  private checkInterval = 30000; // 30 秒检查一次
  
  startMonitoring(subappName: string, entry: string) {
    setInterval(async () => {
      try {
        const response = await fetch(`${entry}/health`, {
          method: 'GET',
          mode: 'no-cors',
        });
        
        if (!response.ok && response.type !== 'opaque') {
          console.warn(`[健康检查] ${subappName} 不健康,尝试重新加载`);
          this.reloadSubapp(subappName);
        }
      } catch (error) {
        console.error(`[健康检查] ${subappName} 检查失败:`, error);
      }
    }, this.checkInterval);
  }
  
  private reloadSubapp(subappName: string) {
    // 卸载并重新加载子应用
    const microApp = document.querySelector(`[data-name="${subappName}"]`);
    if (microApp) {
      microApp.remove();
      // 触发子应用重新加载
      window.history.pushState({}, '', window.location.pathname);
    }
  }
}

// 5. 性能监控
class SubappPerformanceMonitor {
  report(subappName: string, metrics: PerformanceMetrics) {
    // 上报子应用性能数据
    fetch('/api/micro-performance', {
      method: 'POST',
      body: JSON.stringify({
        subapp: subappName,
        metrics,
        timestamp: Date.now(),
      }),
    });
  }
}

// 效果:
// - 首屏加载:5s+ → 1.5s(预加载 + 缓存)
// - 样式冲突:从每月 50+ 工单 → 0
// - 发布效率:子应用独立发布,冲突减少 90%
2.1.4 Module Federation 微前端实战
/**
 * 【Module Federation 微前端实战 - 字节购物车案例】
 *
 * 背景:
 * - 抖音电商购物车模块
 * - 需要与主应用共享 React、Zustand 等基础依赖
 * - 要求高性能,子应用独立部署
 */

import { ModuleFederationPlugin } from '@module-federation/webpack';

// 主应用 webpack.config.js
const mfConfig = {
  name: 'host_app',
  remotes: {
    // 购物车子应用
    cartRemote: 'cartRemote@https://cart.example.com/remoteEntry.js',
    // 商品推荐子应用
    recommendationRemote: 'recommendationRemote@https://recommend.example.com/remoteEntry.js',
  },
  shared: {
    react: { singleton: true, requiredVersion: '^18.0.0', eager: true },
    'react-dom': { singleton: true, requiredVersion: '^18.0.0', eager: true },
    zustand: { singleton: true },
  },
};

// 子应用 webpack.config.js (购物车)
const cartAppConfig = {
  name: 'cart_remote',
  filename: 'remoteEntry.js',
  exposes: {
    './CartWidget': './src/components/CartWidget',
    './CartStore': './src/store/cartStore',
  },
  shared: {
    react: { singleton: true },
    'react-dom': { singleton: true },
  },
};

// 子应用代码
// src/components/CartWidget.tsx
export const CartWidget = () => {
  const { items, total } = useCartStore();
  
  return (
    <div className="cart-widget">
      <span>购物车 ({items.length})</span>
      <span>¥{total}</span>
    </div>
  );
};

// 主应用使用
// App.tsx
import React, { Suspense } from 'react';

const CartWidget = React.lazy(() => import('cartRemote/CartWidget'));

function App() {
  return (
    <div>
      <Header />
      <Suspense fallback={<CartSkeleton />}>
        <CartWidget />
      </Suspense>
    </div>
  );
}
2.1.5 微前端路由管理实战
/**
 * 【微前端路由管理 - 京东到家案例】
 *
 * 场景:
 * - 主应用:营销平台(促销管理、活动配置)
 * - 子应用 1:用户中心
 * - 子应用 2:商品中心
 * - 子应用 3:订单中心
 */

import { useLocation, useNavigate } from 'react-router-dom';

// 1. 统一路由配置
const ROUTE_CONFIG = {
  '/': { type: 'home', subapp: null },
  '/marketing': { type: 'subapp', name: 'marketing' },
  '/user': { type: 'subapp', name: 'user' },
  '/product': { type: 'subapp', name: 'product' },
  '/order': { type: 'subapp', name: 'order' },
};

// 2. 路由守卫
function MicroAppRouteGuard({ children, requiredPermission }) {
  const location = useLocation();
  const routeConfig = ROUTE_CONFIG[location.pathname];
  
  if (routeConfig?.type === 'subapp') {
    // 子应用路由
    const hasPermission = checkSubappPermission(routeConfig.name, requiredPermission);
    
    if (!hasPermission) {
      return <Navigate to="/no-permission" state={{ from: location }} replace />;
    }
  }
  
  return children;
}

// 3. 懒加载子应用容器
function SubappContainer({ subappName, entry }) {
  const [SubappComponent, setSubappComponent] = useState(null);
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(true);
  
  useEffect(() => {
    let isMounted = true;
    
    async function loadSubapp() {
      try {
        // 动态导入子应用
        const container = await import(/* webpackIgnore: true */ entry);
        
        if (isMounted) {
          setSubappComponent(container.default || container);
          setLoading(false);
        }
      } catch (err) {
        console.error(`[SubappContainer] 加载失败: ${subappName}`, err);
        
        if (isMounted) {
          setError(err);
          setLoading(false);
        }
      }
    }
    
    loadSubapp();
    
    return () => {
      isMounted = false;
    };
  }, [subappName, entry]);
  
  if (loading) {
    return <SubappSkeleton name={subappName} />;
  }
  
  if (error) {
    return <SubappError name={subappName} error={error} onRetry={loadSubapp} />;
  }
  
  return SubappComponent ? <SubappComponent /> : null;
}

// 4. 全局导航同步
function useGlobalNavigation() {
  const navigate = useNavigate();
  const location = useLocation();
  
  // 监听来自子应用的消息
  useEffect(() => {
    const handleMessage = (event: MessageEvent) => {
      const { type, payload } = event.data || {};
      
      switch (type) {
        case 'NAVIGATE':
          // 子应用请求跳转
          navigate(payload.path);
          break;
          
        case 'REDIRECT':
          // 子应用请求重定向到其他子应用
          window.location.href = payload.url;
          break;
          
        case 'OPEN_NEW_TAB':
          // 子应用请求新窗口打开
          window.open(payload.url, '_blank');
          break;
      }
    };
    
    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, [navigate]);
  
  // 通知子应用路由变化
  useEffect(() => {
    const currentRoute = ROUTE_CONFIG[location.pathname];
    
    window.parent.postMessage({
      type: 'ROUTE_CHANGED',
      payload: {
        path: location.pathname,
        subapp: currentRoute?.name,
      },
    }, '*');
  }, [location.pathname]);
}

// 效果:
// - 路由管理统一,切换子应用无需刷新
// - 权限控制到子应用级别
// - 支持嵌套路由和深链接

2.2 服务端渲染深度实践

2.2.1 SSR/SSG/ISR 选型决策
页面数据更新频率?

├── 构建后从不改变  → SSG(文档页、静态列表)
├── 低频更新(小时/天)→ ISR(博客、产品详情)
├── 高频更新(实时数据)→ SSR(搜索结果、实时面板)
├── 高度个性化   → CSR(个人仪表盘、购物车)
└── 混合场景     → 骨架 ISR + 动态内容 SSR
2.2.2 Next.js Streaming SSR 架构
// 流式 SSR:关键内容立即显示,非关键内容逐步流式加载
export default function DashboardPage() {
  return (
    <div>
      {/* 关键内容:立即渲染 */}
      <QuickStats />

      {/* 非关键内容:Suspense 流式加载 */}
      <Suspense fallback={<ChartSkeleton />}>
        <SlowChart data={fetchSlowChartData()} />
      </Suspense>

      <Suspense fallback={<TableSkeleton />}>
        <LargeTable query={fetchLargeTableData()} />
      </Suspense>
    </div>
  );
}

// 使用 React.cache() 去重服务端请求
import { cache } from 'react';

const getUser = cache(async (id: string) => {
  return db.user.findUnique({ where: { id } });
});

// 多处组件调用 getUser,服务端只会发一次请求
2.2.3 ISR 增量静态再生成
// app/products/[id]/page.tsx
export const revalidate = 3600; // 每小时重新生成

// 预生成热门商品
export async function generateStaticParams() {
  const topProducts = await getTopProducts(1000);
  return topProducts.map(p => ({ id: p.id.toString() }));
}

export default async function ProductPage({ params }) {
  const product = await getProduct(params.id);
  return <ProductDetail product={product} />;
}

2.3 跨端架构设计

// React Native 跨端共享架构
function usePlatform() {
  return {
    isWeb: Platform.OS === 'web',
    isIOS: Platform.OS === 'ios',
    isAndroid: Platform.OS === 'android',
  };
}

// 跨端 Hooks(Web → window.open / Native → Linking.openURL)
function useOpenURL() {
  const { isWeb } = usePlatform();

  return (url: string) => {
    if (isWeb) {
      window.open(url, '_blank');
    } else {
      Linking.openURL(url);
    }
  };
}

2.4 中后台 / 电商架构

2.4.1 RBAC 权限系统
// User ← N:M → Role ← N:M → Permission

function usePermission(code: string): boolean {
  const permissions = useAppSelector(s => s.user.permissions);
  return permissions.some(p => p === code || matchWildcard(p, code));
}

function Authorized({
  permission,
  children,
  fallback = null,
}: {
  permission: string;
  children: React.ReactNode;
  fallback?: React.ReactNode;
}) {
  const hasPermission = usePermission(permission);
  return hasPermission ? <>{children}</> : <>{fallback}</>;
}
2.4.2 Schema 驱动动态表单
interface FieldSchema {
  name: string;
  type: 'input' | 'select' | 'datepicker' | 'upload' | 'editor';
  label: string;
  required?: boolean;
  rules?: ValidationRule[];
  visible?: (values: Record<string, any>) => boolean;
  options?: (values: Record<string, any>) => Promise<SelectOption[]>;
}

function SchemaForm({ schema }: { schema: { fields: FieldSchema[] } }) {
  const form = useForm();

  return (
    <Form form={form}>
      {schema.fields.map(field => {
        if (field.visible && !field.visible(form.getFieldsValue())) {
          return null;
        }
        return <FormField key={field.name} field={field} form={form} />;
      })}
    </Form>
  );
}
2.4.3 高并发页面架构(抢购/秒杀)
// 客户端防刷 + 乐观更新 + 降级策略

function useFlashSale(productId: string) {
  const queryClient = useQueryClient();
  const lastRequestTime = useRef(0);

  return useMutation({
    mutationFn: async () => {
      // 客户端频率限制(前端防刷)
      const now = Date.now();
      if (now - lastRequestTime.current < 1000) {
        throw new Error('操作太快,请稍后再试');
      }
      lastRequestTime.current = now;

      return api.buyFlashSale(productId);
    },

    // 乐观更新:立即更新 UI
    onMutate: async () => {
      await queryClient.cancelQueries(['flashSale', productId]);
      const prev = queryClient.getQueryData(['flashSale', productId]);

      queryClient.setQueryData(['flashSale', productId], {
        ...prev,
        stock: prev.stock - 1,
      });

      return { prev };
    },

    // 失败回滚
    onError: (err, variables, context) => {
      if (context?.prev) {
        queryClient.setQueryData(['flashSale', productId], context.prev);
      }
      toast.error('抢购失败,请重试');
    },
  });
}
🎯 淘宝双十一秒杀系统前端架构案例
/**
 * 【淘宝双十一秒杀系统前端架构案例】
 *
 * 背景:
 * - 双十一期间,秒杀活动流量峰值 100 万 QPS
 * - 前端需要应对瞬时高并发请求
 * - 需要保证用户体验和系统稳定性
 *
 * 挑战:
 * - 库存超卖问题
 * - 请求风暴
 * - 前端限流策略
 */

import { useState, useEffect, useRef, useCallback } from 'react';
import { io, Socket } from 'socket.io-client';

// 1. 秒杀状态机
type FlashSaleState = 'not_start' | 'preheat' | 'flash_sale' | 'end';

interface FlashSaleProduct {
  id: string;
  name: string;
  price: number;
  originalPrice: number;
  stock: number;
  startTime: number;
  endTime: number;
  status: FlashSaleState;
}

// 2. 秒杀 Hook
function useFlashSale(productId: string) {
  const [product, setProduct] = useState<FlashSaleProduct | null>(null);
  const [state, setState] = useState<FlashSaleState>('not_start');
  const [countdown, setCountdown] = useState<number>(0);
  const [queuePosition, setQueuePosition] = useState<number | null>(null);
  const [isInQueue, setIsInQueue] = useState(false);
  
  const socketRef = useRef<Socket | null>(null);
  const requestQueueRef = useRef<(() => void)[]>([]);
  const isProcessingRef = useRef(false);

  // 3. WebSocket 连接(实时库存同步)
  useEffect(() => {
    const socket = io('wss://flashsale.taobao.com', {
      transports: ['websocket'],
      reconnection: true,
      reconnectionDelay: 1000,
    });

    socketRef.current = socket;

    socket.on('connect', () => {
      console.log('[秒杀] WebSocket 连接成功');
      socket.emit('subscribe', { productId });
    });

    socket.on('stock_update', (data: { stock: number }) => {
      setProduct(prev => prev ? { ...prev, stock: data.stock } : prev);
    });

    socket.on('state_change', (data: { state: FlashSaleState }) => {
      setState(data.state);
    });

    socket.on('queue_position', (data: { position: number }) => {
      setQueuePosition(data.position);
    });

    socket.on('queue_pass', () => {
      setIsInQueue(false);
      setQueuePosition(null);
    });

    return () => {
      socket.disconnect();
    };
  }, [productId]);

  // 4. 倒计时逻辑
  useEffect(() => {
    if (!product) return;

    const updateCountdown = () => {
      const now = Date.now();
      const timeDiff = product.startTime - now;

      if (timeDiff > 0) {
        setState('not_start');
        setCountdown(timeDiff);
      } else if (timeDiff <= 0 && now < product.endTime) {
        setState('flash_sale');
        setCountdown(0);
      } else {
        setState('end');
        setCountdown(0);
      }
    };

    updateCountdown();
    const timer = setInterval(updateCountdown, 1000);

    return () => clearInterval(timer);
  }, [product]);

  // 5. 令牌桶限流器
  class TokenBucket {
    private tokens: number;
    private lastRefill: number;
    private capacity: number;
    private refillRate: number;

    constructor(capacity: number, refillRate: number) {
      this.tokens = capacity;
      this.lastRefill = Date.now();
      this.capacity = capacity;
      this.refillRate = refillRate;
    }

    tryConsume(): boolean {
      this.refill();
      
      if (this.tokens > 0) {
        this.tokens--;
        return true;
      }
      return false;
    }

    private refill() {
      const now = Date.now();
      const elapsed = now - this.lastRefill;
      const newTokens = (elapsed / 1000) * this.refillRate;
      
      this.tokens = Math.min(this.capacity, this.tokens + newTokens);
      this.lastRefill = now;
    }
  }

  const tokenBucket = useRef(new TokenBucket(10, 5)); // 容量 10,每秒补充 5 个

  // 6. 抢购请求
  const handlePurchase = useCallback(async () => {
    if (state !== 'flash_sale') {
      toast.warning('秒杀尚未开始');
      return;
    }

    if (product?.stock <= 0) {
      toast.warning('库存不足');
      return;
    }

    // 限流检查
    if (!tokenBucket.current.tryConsume()) {
      toast.warning('操作太频繁,请稍后再试');
      return;
    }

    setIsInQueue(true);

    try {
      const response = await api.postFlashSale({
        productId,
        userId: getCurrentUserId(),
        timestamp: Date.now(),
      });

      if (response.code === 'QUEUE') {
        // 进入排队
        setQueuePosition(response.position);
      } else if (response.code === 'SUCCESS') {
        toast.success('恭喜,抢购成功!');
        setProduct(prev => prev ? { ...prev, stock: prev.stock - 1 } : prev);
        setIsInQueue(false);
      } else if (response.code === 'SOLD_OUT') {
        toast.error('商品已售罄');
        setIsInQueue(false);
      }
    } catch (error) {
      toast.error('网络错误,请重试');
      setIsInQueue(false);
    }
  }, [productId, state, product]);

  return {
    product,
    state,
    countdown,
    queuePosition,
    isInQueue,
    handlePurchase,
  };
}

// 7. 秒杀页面组件
function FlashSalePage({ productId }: { productId: string }) {
  const {
    product,
    state,
    countdown,
    queuePosition,
    isInQueue,
    handlePurchase,
  } = useFlashSale(productId);

  if (!product) return <FlashSaleSkeleton />;

  return (
    <div className="flash-sale-page">
      <ProductCard product={product} />
      
      {state === 'not_start' && (
        <div className="countdown">
          <span>距离开始:</span>
          <CountdownDisplay seconds={countdown} />
        </div>
      )}
      
      {state === 'flash_sale' && (
        <>
          {isInQueue ? (
            <div className="queue-info">
              <span>排队中...</span>
              <span>当前队列位置:{queuePosition}</span>
            </div>
          ) : (
            <Button
              type="primary"
              size="large"
              disabled={product.stock <= 0}
              onClick={handlePurchase}
            >
              {product.stock > 0 ? '立即抢购' : '已售罄'}
            </Button>
          )}
          <span className="stock-info">剩余库存:{product.stock}</span>
        </>
      )}
      
      {state === 'end' && (
        <Button size="large" disabled>活动已结束</Button>
      )}
    </div>
  );
}

// 效果:
// - WebSocket 实时库存,延迟 < 100ms
// - 令牌桶限流,前端拦截 90% 无效请求
// - 排队系统平滑流量,请求峰值降低 80%
🎯 京东商品详情页架构案例
/**
 * 【京东商品详情页架构案例】
 *
 * 场景:
 * - 商品详情页是京东最核心的页面之一
 * - 日均 PV 1 亿+
 * - 需要承载:商品信息、SKU 选择、评价、推荐、加购等
 *
 * 架构设计:
 * - SSR 首屏直出
 * - 模块化懒加载
 * - 骨架屏优化体验
 */

import { Suspense, lazy, useState, useEffect } from 'react';

// 1. 模块化拆分
const ProductInfo = lazy(() => import('./modules/ProductInfo'));
const SKU = lazy(() => import('./modules/SKU'));
const ProductComment = lazy(() => import('./modules/ProductComment'));
const ProductRecommend = lazy(() => import('./modules/ProductRecommend'));
const ProductGallery = lazy(() => import('./modules/ProductGallery'));

// 2. 核心数据结构
interface ProductDetail {
  id: string;
  name: string;
  price: number;
  mainImage: string;
  images: string[];
  skuList: SKU[];
  comments: Comment[];
}

// 3. 视口懒加载 Hook
function useInViewport(elementRef: React.RefObject<HTMLElement>, options?: IntersectionObserverInit) {
  const [isInViewport, setIsInViewport] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        setIsInViewport(true);
        observer.disconnect();
      }
    }, { threshold: 0.1, rootMargin: '100px', ...options });

    if (elementRef.current) {
      observer.observe(elementRef.current);
    }

    return () => observer.disconnect();
  }, [elementRef, options]);

  return isInViewport;
}

// 4. 懒加载模块组件
function LazyModule({ 
  children, 
  fallback, 
  rootMargin = '100px' 
}: { 
  children: React.ReactNode; 
  fallback?: React.ReactNode;
  rootMargin?: string;
}) {
  const ref = useRef<HTMLDivElement>(null);
  const isInViewport = useInViewport(ref, { rootMargin });

  return (
    <div ref={ref}>
      {isInViewport ? (
        <Suspense fallback={fallback || <ModuleSkeleton />}>
          {children}
        </Suspense>
      ) : (
        fallback || <ModuleSkeleton />
      )}
    </div>
  );
}

// 5. 商品详情页
function ProductDetailPage({ productId }: { productId: string }) {
  const [product, setProduct] = useState<ProductDetail | null>(null);

  // SSR 数据获取(服务端)
  useEffect(() => {
    fetchProductDetail(productId).then(setProduct);
  }, [productId]);

  if (!product) return <ProductDetailSkeleton />;

  return (
    <div className="product-detail-page">
      {/* 首屏模块(同步加载) */}
      <div className="main-section">
        <ProductGallery images={product.images} />
        <ProductInfo product={product} />
      </div>

      {/* 非关键模块(懒加载) */}
      <div className="secondary-section">
        <LazyModule fallback={<SKUSkeleton />}>
          <SKU skus={product.skuList} />
        </LazyModule>

        <LazyModule fallback={<CommentSkeleton />}>
          <ProductComment productId={productId} />
        </LazyModule>

        <LazyModule fallback={<RecommendSkeleton />}>
          <ProductRecommend productId={productId} />
        </LazyModule>
      </div>
    </div>
  );
}

// 6. SSR 数据预取
export async function getServerSideProps({ params }) {
  const product = await fetchProductDetail(params.id);
  
  return {
    props: {
      product,
      // 预取可能需要的其他数据
      preloadedComments: await fetchComments(params.id, { limit: 10 }),
    },
  };
}

// 效果:
// - 首屏加载:2.5s → 800ms(SSR + 关键模块同步)
// - 模块懒加载,整体流量降低 40%
// - 视口懒加载,用户感知速度提升 50%

三、极致性能优化

3.1 运行时性能优化

3.1.1 渲染瓶颈分析工具
// React Profiler 包装器
function App() {
  const onRender = (id: string, phase: string, actualDuration: number) => {
    if (actualDuration > 16) {
      console.warn(`Slow render: ${id} (${phase}: ${actualDuration}ms)`);
    }
  };

  return (
    <Profiler id="App" onRender={onRender}>
      <RouterProvider router={router} />
    </Profiler>
  );
}

// 自定义渲染计数 Hook
function useRenderCount(componentName: string) {
  const count = useRef(0);
  const startTime = useRef(performance.now());

  count.current++;

  useEffect(() => {
    const duration = performance.now() - startTime.current;
    if (duration > 100 && count.current > 10) {
      console.warn(
        `[${componentName}] re-rendered ${count.current} times in ${duration}ms`
      );
    }
  });

  return count.current;
}
🎯 字节跳动抖音列表页性能优化案例
/**
 * 【字节跳动抖音列表页性能优化案例】
 *
 * 背景:
 * - 抖音推荐列表页,日活 1 亿+
 * - 列表项包含:视频封面、作者信息、点赞/评论/分享数
 * - 首屏需要渲染 20+ 条内容
 * - 目标:首屏渲染 < 500ms,列表滑动 60fps
 *
 * 优化前的性能数据:
 * - 首屏渲染时间:2.3s
 * - JS Bundle:3.2MB
 * - 列表帧率:< 30fps(卡顿明显)
 * - 内存占用:800MB+
 */

import { useState, useEffect, useRef, memo, useMemo, useCallback } from 'react';
import { FixedSizeList as VirtualList } from 'react-window';
import { useQueryClient } from '@tanstack/react-query';

// 1. 优化策略一:组件 memoization + 精细化比较
const VideoItem = memo(function VideoItem({ 
  video, 
  index, 
  style,
  onLike,
  onComment,
  onShare,
}: { 
  video: Video;
  index: number;
  style: React.CSSProperties;
  onLike: (id: string) => void;
  onComment: (id: string) => void;
  onShare: (id: string) => void;
}) {
  // 只在 video 数据真正变化时重渲染
  return (
    <div style={style} className="video-item">
      <VideoCover src={video.coverUrl} />
      <AuthorInfo author={video.author} />
      <VideoStats 
        likes={video.likes}
        comments={video.comments}
        shares={video.shares}
      />
      <ActionButtons
        onLike={() => onLike(video.id)}
        onComment={() => onComment(video.id)}
        onShare={() => onShare(video.id)}
      />
    </div>
  );
}, (prevProps, nextProps) => {
  // 自定义比较函数:只比较真正影响渲染的字段
  return (
    prevProps.video.id === nextProps.video.id &&
    prevProps.video.likes === nextProps.video.likes &&
    prevProps.video.comments === nextProps.video.comments &&
    prevProps.video.shares === nextProps.video.shares &&
    prevProps.index === nextProps.index
  );
});

// 2. 优化策略二:虚拟列表(只渲染可见区域)
function VideoFeed({ videos }: { videos: Video[] }) {
  const listRef = useRef<VirtualList>(null);
  const visibleRangeRef = useRef({ start: 0, end: 20 });

  // 视口变化时更新可见范围
  const handleItemsRendered = useCallback((
    { visibleStartIndex, visibleStopIndex }: { visibleStartIndex: number; visibleStopIndex: number }
  ) => {
    visibleRangeRef.current = { 
      start: Math.max(0, visibleStartIndex - 5), 
      end: visibleStopIndex + 5 
    };
  }, []);

  return (
    <VirtualList
      ref={listRef}
      height={window.innerHeight}
      itemCount={videos.length}
      itemSize={120}
      width="100%"
      overscanCount={10}
      onItemsRendered={handleItemsRendered}
    >
      {({ index, style }) => (
        <VideoItem
          key={videos[index].id}
          video={videos[index]}
          index={index}
          style={style}
          onLike={handleLike}
          onComment={handleComment}
          onShare={handleShare}
        />
      )}
    </VirtualList>
  );
}

// 3. 优化策略三:图片懒加载 + 渐进式加载
function VideoCover({ src, placeholder }: { src: string; placeholder?: string }) {
  const [loaded, setLoaded] = useState(false);
  const [error, setError] = useState(false);
  const imgRef = useRef<HTMLImageElement>(null);
  const observerRef = useRef<IntersectionObserver | null>(null);

  useEffect(() => {
    // 进入视口才开始加载
    observerRef.current = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          const img = new Image();
          img.src = src;
          img.onload = () => setLoaded(true);
          img.onerror = () => setError(true);
          observerRef.current?.disconnect();
        }
      },
      { rootMargin: '200px' }
    );

    if (imgRef.current) {
      observerRef.current.observe(imgRef.current);
    }

    return () => observerRef.current?.disconnect();
  }, [src]);

  return (
    <div ref={imgRef} className="video-cover">
      {!loaded && !error && (
        <div className="placeholder" />
      )}
      {loaded && (
        <img src={src} alt="" />
      )}
    </div>
  );
}

// 4. 优化策略四:useCallback 缓存回调函数
const VideoActions = memo(function VideoActions({ 
  videoId, 
  likes 
}: { 
  videoId: string; 
  likes: number 
}) {
  // 使用 useCallback 确保函数引用稳定
  const handleLike = useCallback(() => {
    analytics.track('video_like', { videoId });
  }, [videoId]);

  const handleComment = useCallback(() => {
    analytics.track('video_comment', { videoId });
  }, [videoId]);

  const handleShare = useCallback(() => {
    analytics.track('video_share', { videoId });
  }, [videoId]);

  return (
    <div className="actions">
      <button onClick={handleLike}>❤️ {likes}</button>
      <button onClick={handleComment}>💬</button>
      <button onClick={handleShare}>↗️</button>
    </div>
  );
});

// 5. 优化策略五:预加载下一页数据
function usePrefetchNextPage(currentIndex: number, videos: Video[]) {
  const queryClient = useQueryClient();

  useEffect(() => {
    // 当用户滚动到倒数第 10 条时,预加载下一页
    if (currentIndex >= videos.length - 10) {
      const nextCursor = videos.length;
      queryClient.prefetchQuery({
        queryKey: ['video-feed', nextCursor],
        queryFn: () => fetchVideos(nextCursor),
      });
    }
  }, [currentIndex, videos.length, queryClient]);
}

// 6. 优化后的性能数据:
// - 首屏渲染时间:2.3s → 380ms(提升 83%)
// - JS Bundle:3.2MB → 1.8MB(减少 44%)
// - 列表帧率:< 30fps → 60fps(丝滑流畅)
// - 内存占用:800MB → 350MB(减少 56%)
🎯 美团外卖列表页性能优化案例
/**
 * 【美团外卖列表页性能优化案例】
 *
 * 背景:
 * - 外卖商家列表页,日活 5000 万
 * - 列表项包含:商家图片、评分、配送时间、优惠券
 * - 首屏需要渲染 40+ 条内容
 * - 弱网环境(3G)优化是重点
 *
 * 优化前的性能数据(3G 网络):
 * - 首屏渲染时间:8.5s
 * - FCP(首次内容绘制):4.2s
 * - LCP(最大内容绘制):7.8s
 * - TTI(可交互时间):9.1s
 */

import { Suspense, useState, useEffect, useRef } from 'react';

// 1. 骨架屏优化(减少感知等待时间)
function MerchantListSkeleton({ count = 20 }) {
  return (
    <div className="merchant-list-skeleton">
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} className="skeleton-item">
          <div className="skeleton-image" />
          <div className="skeleton-content">
            <div className="skeleton-title" />
            <div className="skeleton-subtitle" />
            <div className="skeleton-tags" />
          </div>
        </div>
      ))}
    </div>
  );
}

// 2. 图片 WebP 格式 + 渐进式加载
function MerchantImage({ src, alt }: { src: string; alt: string }) {
  const [loaded, setLoaded] = useState(false);
  const imgRef = useRef<HTMLImageElement>(null);

  // 使用 srcSet 提供多分辨率图片
  const srcSet = useMemo(() => {
    const baseUrl = src.replace(/\.(jpg|png)$/, '');
    return `${baseUrl}_200x200.webp 200w, ${baseUrl}_400x400.webp 400w, ${baseUrl}_800x800.webp 800w`;
  }, [src]);

  return (
    <img
      ref={imgRef}
      src={src}
      srcSet={srcSet}
      sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
      alt={alt}
      loading="lazy"
      onLoad={() => setLoaded(true)}
      className={loaded ? 'loaded' : 'loading'}
    />
  );
}

// 3. 数据预加载 + 缓存策略
function useMerchantList(filters: MerchantFilters) {
  const queryClient = useQueryClient();

  // 首次加载显示骨架屏,同时预加载真实数据
  const { data, isLoading } = useQuery({
    queryKey: ['merchants', filters],
    queryFn: () => fetchMerchants(filters),
    // 缓存策略:数据新鲜度 5 分钟
    staleTime: 5 * 60 * 1000,
    // 缓存保留时间:30 分钟
    gcTime: 30 * 60 * 1000,
    // 预加载相邻页
    prefetchPreviousPage: true,
    prefetchNextPage: true,
  });

  // 当用户接近列表底部时预加载下一页
  const prefetchNextPage = useCallback(() => {
    if (data?.hasNextPage) {
      queryClient.prefetchQuery({
        queryKey: ['merchants', { ...filters, cursor: data.nextCursor }],
        queryFn: () => fetchMerchants({ ...filters, cursor: data.nextCursor }),
      });
    }
  }, [data, filters, queryClient]);

  return { data, isLoading, prefetchNextPage };
}

// 4. 列表项渐进式渲染
function MerchantList({ filters }: { filters: MerchantFilters }) {
  const { data, isLoading, prefetchNextPage } = useMerchantList(filters);
  const listRef = useRef<HTMLDivElement>(null);

  // 检测用户滚动接近底部
  useEffect(() => {
    const handleScroll = throttle(() => {
      const { scrollTop, scrollHeight, clientHeight } = document.documentElement;
      if (scrollTop + clientHeight >= scrollHeight - 500) {
        prefetchNextPage();
      }
    }, 300);

    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, [prefetchNextPage]);

  if (isLoading) {
    return <MerchantListSkeleton count={20} />;
  }

  return (
    <div ref={listRef} className="merchant-list">
      {data?.merchants.map((merchant, index) => (
        // 使用 index 作为 key 的一部分,避免列表重新渲染
        <MerchantCard key={`${merchant.id}-${index}`} merchant={merchant} />
      ))}
      {data?.hasNextPage && <LoadingMore />}
    </div>
  );
}

// 5. 优化后的性能数据(3G 网络):
// - 首屏渲染时间:8.5s → 2.1s(提升 75%)
// - FCP:4.2s → 1.2s(提升 71%)
// - LCP:7.8s → 2.0s(提升 74%)
// - TTI:9.1s → 2.5s(提升 73%)
3.1.2 内存泄漏排查清单
// ❌ 泄漏 1:未清理的 setInterval
function BadClock() {
  useEffect(() => {
    setInterval(() => setTime(new Date()), 1000); // 永远不会停止!
  }, []);
}

// ❌ 泄漏 2:闭包引用大对象不释放
function BadComponent({ largeData }) {
  useEffect(() => {
    const handler = () => {
      processData(largeData); // 闭包一直引用 largeData
    };
    window.addEventListener('resize', handler);
    return () => window.removeEventListener('resize', handler);
  }, [largeData]); // 每次 largeData 变化都创建新的 handler
}

// ❌ 泄漏 3:fetch 未 abort
function BadFetch({ url }) {
  useEffect(() => {
    fetch(url).then(setData); // 快速切换路由,请求可能还在进行
  }, [url]);
}

// ✅ 修复:AbortController
function GoodFetch({ url }) {
  useEffect(() => {
    const controller = new AbortController();

    fetch(url, { signal: controller.signal })
      .then(res => res.json())
      .then(data => {
        if (!controller.signal.aborted) setData(data);
      });

    return () => controller.abort();
  }, [url]);
}
3.1.3 长列表极致优化
// react-window 虚拟列表 + 动态高度
import { VariableSizeList } from 'react-window';

function DynamicVirtualList({ items }: { items: Item[] }) {
  const listRef = useRef<VariableSizeList>(null);
  const [heights, setHeights] = useState(() => new Map<number, number>());

  const getItemSize = (index: number) => heights.get(index) || 80;

  const handleItemRendered = (index: number, height: number) => {
    if (heights.get(index) !== height) {
      setHeights(prev => new Map(prev).set(index, height));
      listRef.current?.resetAfterIndex(index);
    }
  };

  return (
    <VariableSizeList
      ref={listRef}
      height={600}
      itemCount={items.length}
      itemSize={getItemSize}
      width="100%"
      overscanCount={5}
    >
      {({ index, style }) => (
        <MeasuredItem
          style={style}
          item={items[index]}
          onResize={h => handleItemRendered(index, h)}
        />
      )}
    </VariableSizeList>
  );
}

3.2 构建极致优化

3.2.1 Vite 生产构建配置
// vite.config.ts
export default defineConfig({
  build: {
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        pure_funcs: ['console.log', 'console.info'],
      },
    },
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom', 'react-router-dom'],
          antd: ['antd', '@ant-design/icons'],
          chart: ['echarts'],
          editor: ['monaco-editor'],
        },
        chunkFileNames: 'chunks/[name]-[hash].js',
        assetFileNames: 'assets/[name]-[hash][extname]',
      },
    },
  },
  plugins: [
    react(),
    // 构建产物分析
    visualizer({
      filename: 'stats/bundle.html',
      gzipSize: true,
    }),
  ],
});
3.2.2 分包策略对比
不分包(单 chunk):所有代码在 1 个文件
→ 首次加载 2MB,下载慢,解析慢 ❌

简单分包(vendor + main):
→ vendor: 500KB(React 等,长期缓存)✅
→ main: 1.5MB(仍有优化空间)

细粒度分包(推荐):
→ vendor: 200KB(react, react-dom)
→ antd: 400KB(组件库)
→ chart: 300KB(图表,仅部分页面用)
→ editor: 500KB(编辑器,极少数页面用)
→ main: 200KB(业务代码)
→ 首屏仅加载 vendor + main = 400KB ✅
3.2.3 资源预加载体系
// DNS 预解析 + 预连接
function useResourceHints() {
  useEffect(() => {
    // 预连接 API
    const preconnect = document.createElement('link');
    preconnect.rel = 'preconnect';
    preconnect.href = 'https://api.example.com';

    // DNS 预解析 CDN
    const dnsPrefetch = document.createElement('link');
    dnsPrefetch.rel = 'dns-prefetch';
    dnsPrefetch.href = 'https://cdn.example.com';

    document.head.append(preconnect, dnsPrefetch);
    return () => { preconnect.remove(); dnsPrefetch.remove(); };
  }, []);
}

// hover 时预加载下一页
function PreloadLink({ to, children }) {
  return (
    <Link
      to={to}
      onMouseEnter={() => {
        import(`@/views/${to}`); // 提前加载 chunk
      }}
    >
      {children}
    </Link>
  );
}

3.3 体验优化(Core Web Vitals)

┌─────────────────────────────────────────────────────────────┐
│                    核心 Web 指标                              │
│                                                             │
│  LCP (最大内容绘制)  < 2.5s                                  │
│  ├── 优化:SSR、图片优化、资源预加载                            │
│  └── 影响:用户感知加载速度                                    │
│                                                             │
│  INP (交互延迟)      < 200ms                                 │
│  ├── 代替 FID 的新指标                                        │
│  ├── 优化:减少 JS 执行时间、异步更新 UI                        │
│  └── 影响:页面交互响应速度                                    │
│                                                             │
│  CLS (视觉稳定性)    < 0.1                                   │
│  ├── 优化:为动态内容预留空间、font-display                    │
│  └── 影响:视觉稳定性(避免布局跳动)                           │
│                                                             │
│  TTFB (首字节时间)   < 800ms                                 │
│  ├── 优化:CDN、服务端缓存、边缘计算                           │
│  └── 影响:服务器响应速度                                     │
└─────────────────────────────────────────────────────────────┘
/* CLS 优化:为所有动态内容预留空间 */
img {
  width: 100%;
  height: auto;
  aspect-ratio: attr(width) / attr(height); /* 避免加载后布局跳动 */
}

/* 避免字体加载导致 CLS */
@font-face {
  font-family: 'Custom';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: optional; /* 可选字体,加载失败不阻塞渲染 */
}

/* 广告/第三方内容预留空间 */
.ad-container {
  min-height: 250px; /* 避免加载前高度为 0 */
}

3.4 性能监控体系

3.4.1 自研性能监控 SDK
// 前端性能监控 SDK
class PerformanceMonitor {
  private metrics: Map<string, number> = new Map();

  // Web Vitals 自动采集
  initWebVitals() {
    // LCP 监控
    new PerformanceObserver(entryList => {
      const entries = entryList.getEntries();
      const lastEntry = entries[entries.length - 1];
      this.report('LCP', lastEntry.startTime);
    }).observe({ type: 'largest-contentful-paint', buffered: true });

    // CLS 监控
    let clsValue = 0;
    new PerformanceObserver(entryList => {
      for (const entry of entryList.getEntries()) {
        if (!entry.hadRecentInput) {
          clsValue += (entry as any).value;
        }
      }
      this.report('CLS', clsValue);
    }).observe({ type: 'layout-shift', buffered: true });

    // INP (交互延迟监控)
    new PerformanceObserver(entryList => {
      for (const entry of entryList.getEntries()) {
        this.report('INP', entry.duration);
      }
    }).observe({ type: 'event', buffered: true });
  }

  // 自定义指标
  measureRender(componentName: string, startTime: number) {
    const duration = performance.now() - startTime;
    this.report(`render:${componentName}`, duration);
  }

  // 上报(批量 + 采样)
  private buffer: Array<{ name: string; value: number }> = [];

  report(name: string, value: number) {
    this.buffer.push({ name, value });

    // 攒够 10 条或超过 5 秒一次性上报
    if (this.buffer.length >= 10) this.flush();
  }

  flush() {
    if (this.buffer.length === 0) return;

    // 10% 采样率上报
    if (Math.random() < 0.1) {
      navigator.sendBeacon('/api/metrics', JSON.stringify(this.buffer));
    }

    this.buffer = [];
  }
}

const perfMonitor = new PerformanceMonitor();
perfMonitor.initWebVitals();
3.4.2 Lighthouse 自动化巡检
// CI 中集成 Lighthouse 自动化检查
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runAudit(url) {
  const chrome = await chromeLauncher.launch();
  const result = await lighthouse(url, {
    port: chrome.port,
    onlyCategories: ['performance'],
    thresholds: {
      performance: 80,  // 最低 80 分
    },
  });

  await chrome.kill();

  const { lcp, cls, tbt } = result.lhr.audits;

  // 不通过阻断部署
  if (result.lhr.categories.performance.score < 0.8) {
    throw new Error(
      `Performance score too low: ${result.lhr.categories.performance.score * 100}`
    );
  }

  return result;
}
🎯 腾讯微信购物小程序性能监控体系案例
/**
 * 【腾讯微信购物小程序性能监控体系案例】
 *
 * 背景:
 * - 微信购物小程序,日活 3000 万
 * - 需要监控 30+ 页面的性能数据
 * - 目标:性能问题早发现、早处理
 *
 * 监控维度:
 * - Web Vitals(LCP/CLS/INP)
 * - JS 错误率
 * - API 请求成功率
 * - 页面切换性能
 */

// 1. 性能数据采集 SDK
class WechatPerformanceMonitor {
  private appId: string;
  private sessionId: string;
  private dataBuffer: PerformanceEvent[] = [];
  private flushInterval = 5000; // 5 秒上报一次

  constructor(appId: string) {
    this.appId = appId;
    this.sessionId = this.generateSessionId();
    this.initWebVitals();
    this.startFlush();
  }

  // 初始化 Web Vitals 监控
  private initWebVitals() {
    // LCP 监控
    new PerformanceObserver((entryList) => {
      const entries = entryList.getEntries();
      const lastEntry = entries[entries.length - 1] as LargestContentfulPaint;
      this.report('LCP', {
        value: lastEntry.startTime,
        rating: lastEntry.startTime < 2500 ? 'good' : lastEntry.startTime < 4000 ? 'needs-improvement' : 'poor',
        element: lastEntry.element?.tagName || 'unknown',
      });
    }).observe({ type: 'largest-contentful-paint', buffered: true });

    // CLS 监控
    let clsValue = 0;
    new PerformanceObserver((entryList) => {
      for (const entry of entryList.getEntries()) {
        if (!entry.hadRecentInput) {
          clsValue += (entry as LayoutShift).value;
        }
      }
    }).observe({ type: 'layout-shift', buffered: true });

    // 定期上报 CLS
    setInterval(() => {
      if (clsValue > 0) {
        this.report('CLS', {
          value: clsValue,
          rating: clsValue < 0.1 ? 'good' : clsValue < 0.25 ? 'needs-improvement' : 'poor',
        });
        clsValue = 0;
      }
    }, 5000);

    // INP 监控(交互延迟)
    new PerformanceObserver((entryList) => {
      for (const entry of entryList.getEntries()) {
        const inpEntry = entry as PerformanceEventTiming;
        if (inpEntry.processingStart) {
          const inputDelay = inpEntry.processingStart - inpEntry.startTime;
          const handlingTime = inpEntry.duration - inputDelay;
          const totalTime = inpEntry.duration;

          this.report('INP', {
            value: totalTime,
            inputDelay,
            handlingTime,
            rating: totalTime < 200 ? 'good' : totalTime < 500 ? 'needs-improvement' : 'poor',
          });
        }
      }
    }).observe({ type: 'event', buffered: true, durationThreshold: 16 });
  }

  // 自定义性能事件
  report(name: string, data: Record<string, any>) {
    const event: PerformanceEvent = {
      name,
      appId: this.appId,
      sessionId: this.sessionId,
      timestamp: Date.now(),
      url: window.location.href,
      userAgent: navigator.userAgent,
      networkType: (navigator as any).connection?.effectiveType || 'unknown',
      deviceMemory: (navigator as any).deviceMemory || 'unknown',
      ...data,
    };

    this.dataBuffer.push(event);
  }

  // 批量上报
  private async flush() {
    if (this.dataBuffer.length === 0) return;

    const dataToSend = [...this.dataBuffer];
    this.dataBuffer = [];

    try {
      // 使用 sendBeacon 确保页面卸载时也能上报
      navigator.sendBeacon('/api/performance', JSON.stringify({
        events: dataToSend,
      }));
    } catch (error) {
      // 上报失败,放回缓冲区
      this.dataBuffer = [...dataToSend, ...this.dataBuffer];
    }
  }

  private startFlush() {
    setInterval(() => this.flush(), this.flushInterval);
    window.addEventListener('visibilitychange', () => {
      if (document.visibilityState === 'hidden') {
        this.flush();
      }
    });
  }

  private generateSessionId(): string {
    return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
  }
}

// 2. 页面切换性能监控
class PageTransitionMonitor {
  private pageStack: PageRecord[] = [];

  startPageTransition(from: string, to: string) {
    const startTime = performance.now();

    this.pageStack.push({
      from,
      to,
      startTime,
    });

    // 监听页面渲染完成
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        const page = this.pageStack[this.pageStack.length - 1];
        if (page) {
          page.renderTime = performance.now() - page.startTime;
          page.domContentLoaded = performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart;

          monitor.report('page_transition', {
            from: page.from,
            to: page.to,
            renderTime: page.renderTime,
            domContentLoaded: page.domContentLoaded,
          });
        }
      });
    });
  }
}

// 3. API 请求监控
class APIRequestMonitor {
  private requestMap = new Map<string, number>();

  wrapRequest<T>(key: string, request: () => Promise<T>): () => Promise<T> {
    return async () => {
      const startTime = performance.now();
      this.requestMap.set(key, startTime);

      try {
        const result = await request();
        const duration = performance.now() - startTime;

        monitor.report('api_request', {
          key,
          success: true,
          duration,
          rating: duration < 300 ? 'good' : duration < 1000 ? 'needs-improvement' : 'poor',
        });

        return result;
      } catch (error) {
        const duration = performance.now() - startTime;

        monitor.report('api_request', {
          key,
          success: false,
          duration,
          errorMessage: error instanceof Error ? error.message : 'Unknown error',
        });

        throw error;
      } finally {
        this.requestMap.delete(key);
      }
    };
  }
}

// 4. 性能预警系统
class PerformanceAlert {
  private thresholds = {
    LCP: { good: 2500, warning: 4000, critical: 8000 },
    CLS: { good: 0.1, warning: 0.25, critical: 0.5 },
    INP: { good: 200, warning: 500, critical: 1000 },
    'page_transition.renderTime': { good: 300, warning: 1000, critical: 3000 },
    'api_request.duration': { good: 300, warning: 1000, critical: 3000 },
  };

  check(eventName: string, value: number) {
    const threshold = this.thresholds[eventName as keyof typeof this.thresholds];
    if (!threshold) return;

    let level = 'good';
    if (value >= threshold.critical) {
      level = 'critical';
      this.sendAlert(eventName, value, threshold);
    } else if (value >= threshold.warning) {
      level = 'warning';
    }

    return level;
  }

  private sendAlert(eventName: string, value: number, threshold: any) {
    // 发送告警到监控系统
    fetch('/api/performance-alert', {
      method: 'POST',
      body: JSON.stringify({
        eventName,
        value,
        threshold,
        timestamp: Date.now(),
        url: window.location.href,
      }),
    });
  }
}

// 5. 使用示例
const monitor = new WechatPerformanceMonitor('wx-app-id');
const pageMonitor = new PageTransitionMonitor();
const apiMonitor = new APIRequestMonitor();
const alertSystem = new PerformanceAlert();

// 页面切换时调用
function navigateTo(page: string) {
  pageMonitor.startPageTransition(currentPage, page);
  router.push(page);
}

// API 请求时使用
const fetchUserInfo = apiMonitor.wrapRequest('getUserInfo', () =>
  fetch('/api/user').then(res => res.json())
);

// 效果:
// - 性能问题发现时间:从用户投诉 → 自动化告警(提前 24 小时)
// - 性能优化迭代周期:2 周 → 3 天
// - 核心指标达标率:60% → 95%

四、工程化体系搭建

4.1 自研脚手架

4.1.1 基于 Vite 的企业级脚手架
# 脚手架功能矩阵
create-react-app-pro
├── 基础模板选择
│ ├── react-ts (React + TypeScript)
│ ├── react-admin (中后台模板)
│ ├── react-mobile (移动端模板)
│ └── react-monorepo (Monorepo 模板)
├── 交互式配置
│ ├── 状态管理 (Zustand / Redux Toolkit / 无)
│ ├── UI 框架 (Ant Design / Tailwind / 无)
│ ├── 数据请求 (React Query / SWR / 无)
│ ├── 路由 (React Router / TanStack Router)
│ ├── 测试 (Vitest / Jest)
│ └── 代码规范 (ESLint + Prettier + Husky)
└── 内置能力
    ├── 统一环境变量管理
    ├── Mock 服务
    ├── API 代理
    ├── 构建优化预设
    └── Docker 模板
🎯 字节跳动前端脚手架 ARES CLI 实战案例
/**
 * 【字节跳动 ARES CLI 脚手架实战案例】
 *
 * 背景:
 * - 字节跳动前端团队 500+ 人
 * - 项目数量 1000+
 * - 需要统一技术栈、构建标准、开发体验
 *
 * 脚手架能力:
 * - 项目创建(react/vue/多端)
 * - 组件/页面/hooks 代码生成
 * - 自动化测试生成
 * - 一键发布
 * - 性能分析
 */

import { Command } from 'commander';
import inquirer from 'inquirer';
import ora from 'ora';
import { execSync } from 'child_process';
import fs from 'fs-extra';
import path from 'path';

// 1. 项目创建命令
async function createProject(projectName: string, options: CreateOptions) {
  const spinner = ora('正在初始化项目...').start();

  try {
    // 1.1 拉取模板
    const templateUrl = getTemplateUrl(options.template);
    execSync(`git clone ${templateUrl} ${projectName} --depth 1`, { stdio: 'inherit' });

    // 1.2 安装依赖
    spinner.text = '正在安装依赖...';
    execSync(`cd ${projectName} && pnpm install`, { stdio: 'inherit' });

    // 1.3 初始化配置
    spinner.text = '正在初始化配置...';
    await initializeConfig(projectName, options);

    // 1.4 Git 初始化
    spinner.text = '正在初始化 Git...';
    execSync(`cd ${projectName} && git init && git add . && git commit -m "chore: initial commit"`);

    spinner.succeed(`项目 ${projectName} 创建成功!`);

    // 打印下一步提示
    printNextSteps(projectName);
  } catch (error) {
    spinner.fail('项目创建失败');
    // 清理已创建的文件
    fs.removeSync(projectName);
    throw error;
  }
}

// 2. 代码生成命令
async function generateCode(type: string, name: string, options: GenerateOptions) {
  const spinner = ora(`正在生成 ${type}...`).start();

  try {
    const targetDir = path.join(process.cwd(), 'src');
    const templates = getTemplates(type);

    for (const template of templates) {
      const outputPath = path.join(targetDir, template.output);
      fs.ensureDirSync(path.dirname(outputPath));

      // 使用模板引擎渲染
      const content = renderTemplate(template.content, { name, ...options });
      fs.writeFileSync(outputPath, content);

      // 生成测试文件
      if (options.withTest) {
        const testPath = outputPath.replace(/\.(ts|tsx)$/, '.test.$1');
        const testContent = renderTemplate(template.testTemplate, { name, ...options });
        fs.writeFileSync(testPath, testContent);
      }

      // 生成 Storybook 文件
      if (options.withStorybook && template.storyTemplate) {
        const storyPath = outputPath.replace(/\.(ts|tsx)$/, '.stories.$1');
        const storyContent = renderTemplate(template.storyTemplate, { name, ...options });
        fs.writeFileSync(storyPath, storyContent);
      }
    }

    spinner.succeed(`${type} ${name} 生成成功!`);

    // 自动格式化
    execSync('npx prettier --write .', { stdio: 'inherit' });
  } catch (error) {
    spinner.fail('代码生成失败');
    throw error;
  }
}

// 3. 交互式选择模板
async function selectTemplate() {
  const answers = await inquirer.prompt([
    {
      type: 'list',
      name: 'template',
      message: '选择项目模板:',
      choices: [
        { name: 'React + TypeScript (SPA)', value: 'react-ts' },
        { name: 'React + TypeScript (中后台)', value: 'react-admin' },
        { name: 'React + TypeScript (移动端 H5)', value: 'react-mobile' },
        { name: 'Vue 3 + TypeScript', value: 'vue3-ts' },
        { name: 'Monorepo (pnpm + Turborepo)', value: 'monorepo' },
        { name: '微前端模板', value: 'micro-frontend' },
      ],
    },
    {
      type: 'checkbox',
      name: 'features',
      message: '选择功能模块:',
      choices: [
        { name: 'Zustand 状态管理', value: 'zustand' },
        { name: 'React Query 数据请求', value: 'query' },
        { name: 'Ant Design 组件库', value: 'antd' },
        { name: 'Tailwind CSS', value: 'tailwind' },
        { name: 'Vitest 单元测试', value: 'vitest' },
        { name: 'Storybook 文档', value: 'storybook' },
        { name: 'MSW 接口 Mock', value: 'msw' },
      ],
    },
    {
      type: 'confirm',
      name: 'eslint',
      message: '启用 ESLint 代码规范?',
      default: true,
    },
    {
      type: 'confirm',
      name: 'precommit',
      message: '启用 Husky 提交前检查?',
      default: true,
    },
  ]);

  return answers;
}

// 4. 项目分析命令
async function analyzeProject() {
  const spinner = ora('正在分析项目...').start();

  try {
    const analysis = {
      bundleSize: await analyzeBundleSize(),
      dependencies: analyzeDependencies(),
      performance: await analyzePerformance(),
      issues: [],
    };

    // 检查依赖安全性
    const auditResult = execSync('pnpm audit --json', { encoding: 'utf-8' });
    const audit = JSON.parse(auditResult);
    if (audit.vulnerabilities) {
      analysis.issues.push({
        type: 'security',
        severity: 'high',
        message: `发现 ${audit.vulnerabilities.high} 个高危安全漏洞`,
      });
    }

    // 检查重复依赖
    const dupes = execSync('pnpm dedupe --json', { encoding: 'utf-8' });
    if (dupes) {
      analysis.issues.push({
        type: 'dependency',
        severity: 'medium',
        message: '存在重复依赖,建议执行 pnpm dedupe',
      });
    }

    spinner.succeed('分析完成!');

    console.log('\n📊 项目分析报告:\n');
    console.log(`Bundle 大小:${analysis.bundleSize}`);
    console.log(`依赖数量:${analysis.dependencies}`);
    console.log('\n⚠️ 发现的问题:');
    analysis.issues.forEach(issue => {
      console.log(`  - [${issue.severity}] ${issue.type}: ${issue.message}`);
    });
  } catch (error) {
    spinner.fail('分析失败');
    throw error;
  }
}

// 5. 脚手架配置
interface Config {
  template: string;
  features: string[];
  eslint: boolean;
  precommit: boolean;
  team?: string;
  projectType?: string;
}

async function initializeConfig(projectDir: string, options: CreateOptions) {
  const config: Config = {
    template: options.template,
    features: options.features || [],
    eslint: options.eslint ?? true,
    precommit: options.precommit ?? true,
    team: options.team,
    projectType: options.projectType,
  };

  // 写入配置文件
  fs.writeFileSync(
    path.join(projectDir, '.aresrc'),
    JSON.stringify(config, null, 2)
  );

  // 写入环境变量模板
  fs.writeFileSync(
    path.join(projectDir, '.env.example'),
    `VITE_API_BASE_URL=http://localhost:8080
VITE_APP_ENV=development
VITE_ENABLE_MOCK=false
`
  );
}

// 6. CLI 主程序
const program = new Command();

program
  .name('ares')
  .description('字节跳动前端脚手架')
  .version('1.0.0');

program
  .command('create')
  .argument('<project-name>', '项目名称')
  .option('-t, --template <template>', '项目模板')
  .option('-f, --features <features>', '功能模块(逗号分隔)')
  .option('--no-eslint', '禁用 ESLint')
  .option('--no-precommit', '禁用提交前检查')
  .option('--team <team>', '团队名称')
  .action(createProject);

program
  .command('generate')
  .argument('<type>', '生成类型 (component|hook|page|api)')
  .argument('<name>', '名称')
  .option('--with-test', '生成测试文件')
  .option('--with-storybook', '生成 Storybook 文件')
  .action(generateCode);

program
  .command('analyze')
  .description('分析项目性能和依赖')
  .action(analyzeProject);

program.parse();
🎯 阿里巴巴前端脚手架实践案例
/**
 * 【阿里巴巴前端脚手架 CP-CLI 实战案例】
 *
 * 背景:
 * - 阿里前端团队 2000+ 人
 * - 业务线 100+
 * - 需要统一的研发标准和质量门槛
 *
 * 核心能力:
 * - 项目初始化(多种模板)
 * - 组件开发工作流
 * - 一键发布到 CDN/NPM
 * - 质量检测(ESLint + TypeScript + 测试覆盖率)
 */

import React, { useState, useEffect } from 'react';
import { execSync } from 'child_process';
import fs from 'fs-extra';
import path from 'path';

// 1. 组件开发工作流
class ComponentWorkflow {
  async createComponent(name: string, options: ComponentOptions) {
    const componentDir = path.join(process.cwd(), 'src/components', name);

    // 1. 创建目录结构
    fs.ensureDirSync(componentDir);
    fs.ensureDirSync(path.join(componentDir, '__tests__'));

    // 2. 生成文件
    await this.generateFiles(componentDir, name, options);

    // 3. 初始化 Git(如果需要)
    if (options.publishToNpm) {
      await this.initializeNpmPackage(componentDir, name);
    }

    // 4. 安装依赖
    execSync('pnpm install', { cwd: componentDir, stdio: 'inherit' });

    // 5. 打开 Storybook
    if (options.storybook) {
      execSync('pnpm storybook', { cwd: componentDir, stdio: 'inherit' });
    }
  }

  private async generateFiles(dir: string, name: string, options: ComponentOptions) {
    const templateDir = path.join(__dirname, 'templates', 'component');

    // 复制模板
    await fs.copy(templateDir, dir);

    // 替换占位符
    const files = fs.readdirSync(dir);
    for (const file of files) {
      const filePath = path.join(dir, file);
      let content = fs.readFileSync(filePath, 'utf-8');

      content = content
        .replace(/{{name}}/g, name)
        .replace(/{{PascalName}}/g, toPascalCase(name))
        .replace(/{{kebabName}}/g, toKebabCase(name));

      fs.writeFileSync(filePath, content);
    }

    // 根据选项调整文件
    if (!options.withTest) {
      fs.removeSync(path.join(dir, '__tests__', `${name}.test.tsx`));
    }

    if (options.cssType === 'modules') {
      fs.removeSync(path.join(dir, `${name}.scss`));
    } else {
      fs.removeSync(path.join(dir, `${name}.module.scss`));
    }
  }

  private async initializeNpmPackage(dir: string, name: string) {
    const packageJson = {
      name: `@alife/${name}`,
      version: '0.0.1',
      main: 'dist/index.js',
      types: 'dist/index.d.ts',
      scripts: {
        build: 'tsc && node scripts/build.js',
        'build:watch': 'tsc --watch',
        test: 'vitest',
        'test:coverage': 'vitest --coverage',
        storybook: 'start-storybook',
        publish: 'npm publish --access public',
      },
      dependencies: {
        react: '^18.0.0',
      },
      devDependencies: {
        '@types/react': '^18.0.0',
        typescript: '^5.0.0',
        vitest: '^1.0.0',
      },
    };

    fs.writeFileSync(
      path.join(dir, 'package.json'),
      JSON.stringify(packageJson, null, 2)
    );
  }
}

// 2. 质量检测工作流
class QualityWorkflow {
  async checkAll(options: QualityOptions) {
    const results = {
      eslint: await this.runEslint(),
      typescript: await this.runTypeCheck(),
      test: await this.runTests(),
      coverage: await this.checkCoverage(),
    };

    // 生成报告
    await this.generateReport(results);

    // 判断是否通过
    const passed = this.evaluateResults(results);

    if (!passed && options.failOnError) {
      process.exit(1);
    }

    return results;
  }

  private async runEslint() {
    try {
      execSync('npx eslint src --format json', { stdio: 'pipe' });
      return { passed: true, errors: 0 };
    } catch (error) {
      const output = error.stdout?.toString() || error.stderr?.toString() || '';
      const result = JSON.parse(output);
      return { passed: false, errors: result.length };
    }
  }

  private async runTypeCheck() {
    try {
      execSync('npx tsc --noEmit', { stdio: 'pipe' });
      return { passed: true, errors: 0 };
    } catch {
      return { passed: false, errors: -1 };
    }
  }

  private async runTests() {
    try {
      execSync('npx vitest --reporter=json --outputFile=test-results.json', {
        stdio: 'pipe',
      });
      const results = JSON.parse(
        fs.readFileSync('test-results.json', 'utf-8')
      );
      return { passed: true, tests: results.numTotalTests };
    } catch {
      return { passed: false, tests: 0 };
    }
  }

  private async checkCoverage() {
    execSync('npx vitest --coverage --coverage-reporter=json', {
      stdio: 'pipe',
    });
    const coverage = JSON.parse(
      fs.readFileSync('coverage/coverage-summary.json', 'utf-8')
    );

    const lines = coverage.total.lines.pct;
    const functions = coverage.total.functions.pct;

    return {
      lines,
      functions,
      passed: lines >= 80 && functions >= 80,
    };
  }

  private evaluateResults(results: any): boolean {
    if (!results.eslint.passed) return false;
    if (!results.typescript.passed) return false;
    if (!results.test.passed) return false;
    if (!results.coverage.passed) return false;
    return true;
  }
}

// 3. 发布工作流
class PublishWorkflow {
  async publish(options: PublishOptions) {
    // 1. 确认版本
    const currentVersion = this.getCurrentVersion();
    const newVersion = this.promptVersion(currentVersion);

    // 2. 更新 CHANGELOG
    await this.updateChangelog(newVersion);

    // 3. 运行质量检测
    const quality = new QualityWorkflow();
    const results = await quality.checkAll({ failOnError: true });

    if (!results.eslint.passed) {
      throw new Error('ESLint 检查未通过,请修复后再发布');
    }

    // 4. 构建
    execSync('pnpm build', { stdio: 'inherit' });

    // 5. 发布到 NPM
    if (options.publishToNpm) {
      execSync('npm publish --access public', { stdio: 'inherit' });
    }

    // 6. 发布到内部 CDN
    if (options.publishToCdn) {
      await this.publishToCDN();
    }

    // 7. 打 Git Tag
    execSync(`git tag v${newVersion} && git push origin v${newVersion}`);

    console.log(`✅ 发布成功!版本:v${newVersion}`);
  }

  private async publishToCDN() {
    const files = fs.readdirSync('dist');
    const cdnClient = new CDNClient({
      endpoint: 'https://cdn.alibaba.com',
      bucket: 'alife-components',
    });

    for (const file of files) {
      await cdnClient.upload(
        path.join('dist', file),
        `components/${toKebabCase(process.env.npm_package_name)}/${file}`
      );
    }
  }
}

// 4. CLI 集成
export function registerCPCommands(program: Command) {
  // 组件开发
  program
    .command('component:create')
    .argument('<name>', '组件名称')
    .option('-t, --template <template>', '模板类型')
    .option('--with-test', '包含测试')
    .option('--storybook', '启用 Storybook')
    .action((name, options) => {
      const workflow = new ComponentWorkflow();
      workflow.createComponent(name, options);
    });

  // 质量检测
  program
    .command('quality:check')
    .option('--fail-on-error', '检查失败时退出')
    .action((options) => {
      const workflow = new QualityWorkflow();
      workflow.checkAll(options);
    });

  // 发布
  program
    .command('publish')
    .option('--npm', '发布到 NPM')
    .option('--cdn', '发布到 CDN')
    .action((options) => {
      const workflow = new PublishWorkflow();
      workflow.publish(options);
    });
}

// 效果:
// - 新项目创建时间:2 天 → 5 分钟
// - 组件开发到发布周期:1 周 → 1 天
// - 代码规范检查覆盖率:60% → 100%
// create-react-app-pro 核心逻辑
const { execSync } = require('child_process');
const prompts = require('prompts');
const fs = require('fs-extra');

async function create(projectName, options) {
  const answers = await prompts([
    {
      type: 'select',
      name: 'template',
      message: '选择项目模板',
      choices: [
        { title: 'React + TypeScript (SPA)', value: 'react-ts' },
        { title: '中后台管理', value: 'react-admin' },
        { title: '移动端 H5', value: 'react-mobile' },
        { title: 'Monorepo (pnpm + Turborepo)', value: 'react-monorepo' },
      ],
    },
    {
      type: 'multiselect',
      name: 'features',
      message: '选择功能模块',
      choices: [
        { title: 'Zustand', value: 'zustand' },
        { title: 'React Query', value: 'query' },
        { title: 'Ant Design', value: 'antd' },
        { title: 'Tailwind CSS', value: 'tailwind' },
        { title: 'Vitest', value: 'vitest' },
      ],
    },
  ]);

  // 从模板仓库拉取
  execSync(
    `git clone https://github.com/company/react-templates.git ${projectName} --depth 1`
  );

  // 根据用户选择,安装对应依赖
  // 注入自定义配置...
}
4.1.2 CLI 命令体系
# 脚手架命令
react-cli create <project-name>    # 创建项目
react-cli add <feature>            # 添加功能模块
react-cli gen <type> <name>        # 代码生成(component/page/hook/api)
react-cli build                    # 构建
react-cli deploy <env>             # 部署
react-cli lint                     # 代码检查
react-cli test                     # 运行测试

4.2 构建体系

4.2.1 多环境配置方案
// config/env.ts
const envConfig = {
  development: {
    API_BASE_URL: 'http://localhost:8080/api',
    CDN_URL: '/',
    MOCK_ENABLED: true,
    SENTRY_DSN: '',
    ANALYTICS_ID: '',
  },
  test: {
    API_BASE_URL: 'https://test-api.example.com',
    CDN_URL: 'https://test-cdn.example.com',
    MOCK_ENABLED: false,
    SENTRY_DSN: 'https://test@sentry.io/xxx',
  },
  staging: {
    API_BASE_URL: 'https://staging-api.example.com',
    CDN_URL: 'https://staging-cdn.example.com',
    MOCK_ENABLED: false,
    SENTRY_DSN: 'https://staging@sentry.io/xxx',
  },
  production: {
    API_BASE_URL: 'https://api.example.com',
    CDN_URL: 'https://cdn.example.com',
    MOCK_ENABLED: false,
    SENTRY_DSN: 'https://prod@sentry.io/xxx',
    ANALYTICS_ID: 'UA-XXXXXX',
  },
};

export const ENV = envConfig[import.meta.env.VITE_APP_ENV || 'development'];
4.2.2 缓存策略(文件指纹 + HTTP 缓存)
// 构建产物命名策略
// /assets/main.a1b2c3d4.js  → 内容变化则 hash 变化 → 永久缓存
// /assets/vendor.e5f6g7h8.js  → 依赖升级才变 → 极长缓存

// Nginx 缓存配置
location /assets/ {
    expires 365d;
    add_header Cache-Control "public, immutable";
}

// HTML 不缓存(确保及时加载最新资源)
location / {
    expires -1;
    add_header Cache-Control "no-cache, must-revalidate";
}

4.3 部署体系(CI/CD)

4.3.1 CI/CD 流水线设计
开发分支 push → 触发 CI Pipeline
├── install      (pnpm install --frozen-lockfile)
├── lint         (eslint, prettier, stylelint)
├── typecheck    (tsc --noEmit)
├── test         (vitest --coverage)
├── build        (vite build)
└── notify       (企业微信/飞书通知)

测试环境自动部署 (develop 分支)
├── docker build
├── push to registry
└── deploy to k8s test namespace

生产环境部署 (main 分支)
├── docker build
├── push to registry
└── canary deploy (灰度发布)
    ├── 10% → 观察 30min
    ├── 50% → 观察 30min
    └── 100% → 全量发布
# .github/workflows/deploy.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: pnpm/action-setup@v2
        with:
          version: 8

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'

      - run: pnpm install --frozen-lockfile

      - name: Lint
        run: pnpm lint

      - name: Type Check
        run: pnpm typecheck

      - name: Test
        run: pnpm test --coverage

      - name: Build
        run: pnpm build

      - name: Performance Audit
        if: github.ref == 'refs/heads/main'
        run: pnpm lighthouse:ci

  deploy:
    needs: build-and-test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - name: Build Docker Image
        run: docker build -t ${{ secrets.REGISTRY }}/app:${{ github.sha }} .

      - name: Push to Registry
        run: docker push ${{ secrets.REGISTRY }}/app:${{ github.sha }}

      - name: Deploy to K8s (Canary)
        run: |
          kubectl set image deployment/app canary=${{ secrets.REGISTRY }}/app:${{ github.sha }} -n production
4.3.2 灰度发布策略
# K8s Canary Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-canary
spec:
  replicas: 1  # 灰度 10%(稳定版 9 个副本)
  selector:
    matchLabels:
      app: myapp
      version: canary
  template:
    metadata:
      labels:
        app: myapp
        version: canary
    spec:
      containers:
        - name: app
          image: registry/app:canary
// 前端灰度路由(通过 Header/Cookie 控制)
function getDeployVersion() {
  // 1. Cookie 标记
  const cookie = document.cookie.match(/version=(canary|stable)/);
  if (cookie) return cookie[1];

  // 2. 用户 ID 哈希(10% 用户走灰度)
  const userId = getUserId();
  const hash = userId.split('').reduce((a, c) => a + c.charCodeAt(0), 0);
  if (hash % 10 === 0) return 'canary';

  return 'stable';
}
4.3.3 Docker 部署配置
# Dockerfile - 多阶段构建
# Stage 1: 构建
FROM node:20-alpine AS builder
WORKDIR /app

COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile

COPY . .
RUN pnpm build

# Stage 2: 运行(仅保留必要文件)
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

# 注入运行时配置(通过环境变量替换)
COPY nginx.conf /etc/nginx/templates/default.conf.template

ENV API_BASE_URL=https://api.example.com
ENV CDN_HOST=https://cdn.example.com

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

4.4 规范体系

4.4.1 代码规范金字塔
┌─────────────────────────────────────────┐
│  自动化拦截(CI 阻断)          ← 最严格  │
│  ├── ESLint error 阻断                  │
│  ├── TypeScript 编译错误阻断              │
│  └── Lighthouse 性能低于 80 分阻断         │
├─────────────────────────────────────────┤
│  自动化修复                             │
│  ├── Prettier 自动格式化                   │
│  ├── ESLint --fix 自动修复                │
│  └── import 自动排序                       │
├─────────────────────────────────────────┤
│  人工检查                               │
│  ├── Code Review(PR 必须 2 人 approve)   │
│  └── 架构评审会                            │
└─────────────────────────────────────────┘
4.4.2 文档规范体系
// 1. 技术方案模板(RFC)
/**
 * RFC: 新功能技术方案
 *
 * 背景:为什么需要这个功能?
 * 目标:要达成什么效果?
 * 方案设计:
 *   - 架构图
 *   - 核心流程
 *   - 接口设计
 *   - 数据库设计
 * 风险与权衡:有哪些风险?有哪些替代方案被否决了?
 * 排期与里程碑
 */

// 2. API 文档规范(JSDoc → 自动生成 API 文档)
/**
 * 获取用户列表
 * @param params.page - 页码
 * @param params.pageSize - 每页数量
 * @returns 分页用户列表
 * @throws {AuthError} 未授权
 */
async function getUsers(params: { page: number; pageSize: number }) {
  // ...
}

// 3. 组件文档规范
// 使用 Storybook 自动生成
4.4.3 研发流程规范
需求评审 → 技术方案 → 开发 → 自测 → 提测 → 发布 → 线上验证

每个阶段的 CheckList:
├── 需求评审:PRD 可测试?验收标准明确?
├── 技术方案:方案评审通过?数据库变更已审批?
├── 开发:分支从 develop 拉出?Commit 规范?
├── 自测:正反用例全覆盖?边界条件测试?
├── 提测:冒烟测试通过?部署文档已更新?
├── 发布:灰度发布观察?回滚方案已准备?
└── 线上验证:关键指标正常?用户反馈无异常?

五、技术选型 & 技术治理

5.1 技术栈选型决策

5.1.1 决策框架:TRIZ 选型法
选型四维度(每个维度 1-5 分):

1. 技术匹配度 (Technical Fit)
   - 是否解决当前核心问题?
   - 与现有技术栈兼容性?

2. 社区成熟度 (Community)
   - GitHub Stars / Issues 响应速度
   - 是否有大厂背书?
   - 文档质量如何?

3. 团队能力 (Team Capability)
   - 团队成员学习成本?
   - 是否有外部专家?

4. 长期演进 (Longevity)
   - 是否有持续维护计划?
   - 项目是否活跃?

总分 ≥ 14 分 → 推荐引入
总分 10-13   → 谨慎评估
总分 < 10    → 不推荐
5.1.2 React 生态选型矩阵(2025-2026)
领域 推荐方案 备选方案 已不推荐
状态管理 Zustand Jotai / Redux Toolkit MobX
数据请求 TanStack Query SWR Redux Saga
路由 React Router v6 TanStack Router Reach Router
样式 Tailwind CSS CSS Modules Styled Components
构建 Vite - CRA / Webpack
测试 Vitest + Testing Library Playwright Jest (逐渐过时)
SSR Next.js App Router Remix Gatsby
微前端 wujie / qiankun Module Federation single-spa
图表 ECharts Recharts Chart.js
5.1.3 React 版本升级方案
// React 17 → 18 升级路线图
// 1. 升级前检查
// 检查向后不兼容的变更:
//   - Automatic Batching 行为变化
//   - createRoot 替代 ReactDOM.render
//   - 移除事件池

// 2. 阶段式升级
// Phase 1: 升级依赖但保持旧 API
ReactDOM.render(<App />, root);  // 暂时保留,逐步迁移

// Phase 2: 迁移到新 API
import { createRoot } from 'react-dom/client';
const root = createRoot(document.getElementById('root')!);
root.render(<App />);

// Phase 3: 启用 Concurrent Features(按需)
//   - useTransition / useDeferredValue
//   - Suspense for data fetching

// 3. 回归测试检查清单
//   - 检查所有 form 提交(Automatic Batching 影响)
//   - 检查 setTimeout/setInterval(事件池移除影响)
//   - 检查 useEffect 清理函数(Strict Mode 双重调用)

5.2 技术债务治理

5.2.1 技术债务分级
Level 1 - 紧急(1 周内修复):
├── 安全漏洞
├── 生产环境 Bug
├── 性能严重下降
└── 关键路径代码混乱

Level 2 - 重要(本迭代修复):
├── 不符合团队编码规范
├── 缺少必要的单元测试
├── 代码重复 > 3 处
└── 过时的 API 调用

Level 3 - 一般(技术债清理迭代):
├── 组件过度复杂(>300 行)
├── Props Drilling 过深(>3 层)
├── 缺少类型定义
└── 日志/注释不清晰

Level 4 - 可接受:
├── 不影响功能的小优化
├── 旧的但稳定的代码
└── 实验性代码(预期会重写)
5.2.2 老旧项目重构策略
策略 1:绞杀者模式(Strangler Fig)
├── 新功能用新架构开发
├── 旧功能逐步迁移
└── 最终完全替换

策略 2:增量重构
├── 先从最独立的模块开始
├── 每次只重构一个功能点
├── 每次都有完整的测试覆盖
└── 不改变外部接口

策略 3:限制变更范围
├── 不要一次改太多
├── PR 控制在 400 行以内
├── 每次重构 1-2 个组件
└── 保持新旧代码共存期

5.3 版本管理与依赖治理

5.3.1 依赖管理策略
// package.json
{
  "dependencies": {
    "react": "^18.3.0",          // ^ 允许次版本升级
    "antd": "~5.15.0",           // ~ 仅允许补丁升级
    "zustand": "4.5.0",          // 锁定精确版本(核心库)
    "lodash-es": "4.17.21"       // 精确锁定
  },
  "overrides": {
    "react": "18.3.0",           // 强制所有子依赖使用统一版本
    "typescript": "5.4.0"
  }
}
5.3.2 依赖审计与更新流程
# 1. 安全检查(日常)
pnpm audit

# 2. 过期检查(每月)
pnpm outdated

# 3. 依赖更新(每月)
pnpm update --interactive  # 交互式选择更新

# 4. 检查 Breaking Changes
# 查看 CHANGELOG 和迁移指南

# 5. 更新后运行全部测试
pnpm test
pnpm typecheck
pnpm lint

# 6. 提交依赖锁文件
git commit -m "chore(deps): upgrade dependencies"

六、数据 & 网络 & 安全架构

6.1 数据层架构

6.1.1 GraphQL + Apollo Client
// Apollo Client 配置
import { ApolloClient, InMemoryCache, HttpLink, from } from '@apollo/client';
import { onError } from '@apollo/client/link/error';
import { RetryLink } from '@apollo/client/link/retry';

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, extensions }) => {
      if (extensions?.code === 'UNAUTHENTICATED') {
        // token 过期,刷新或跳转登录
      }
    });
  }
});

const retryLink = new RetryLink({
  delay: { initial: 300, max: 5000, jitter: true },
  attempts: { max: 3 },
});

const client = new ApolloClient({
  link: from([errorLink, retryLink, new HttpLink({ uri: '/graphql' })]),
  cache: new InMemoryCache({
    typePolicies: {
      Query: {
        fields: {
          users: {
            // 合并分页数据
            keyArgs: ['filters'],
            merge(existing, incoming) {
              return {
                ...incoming,
                items: [...(existing?.items || []), ...incoming.items],
              };
            },
          },
        },
      },
    },
  }),
});

// GraphQL Query
const GET_USERS = gql`
  query GetUsers($page: Int!, $pageSize: Int!, $filter: UserFilter) {
    users(page: $page, pageSize: $pageSize, filter: $filter) {
      items { id name email role }
      totalCount hasNextPage
    }
  }
`;

function UserList() {
  const { data, loading, fetchMore } = useQuery(GET_USERS, {
    variables: { page: 1, pageSize: 20 },
  });

  const loadMore = () => {
    fetchMore({
      variables: { page: data.users.items.length / 20 + 1, pageSize: 20 },
    });
  };
}
6.1.2 请求封装:统一错误处理 + 重试 + 日志
// api/client.ts
import axios, { AxiosError, AxiosRequestConfig } from 'axios';

const client = axios.create({
  baseURL: ENV.API_BASE_URL,
  timeout: 15000,
});

// 请求拦截器
client.interceptors.request.use(config => {
  const token = getToken();
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }

  // 添加请求 ID(全链路追踪)
  config.headers['X-Request-ID'] = generateRequestId();

  return config;
});

// 响应拦截器(全局错误处理)
client.interceptors.response.use(
  response => response.data,
  async (error: AxiosError) => {
    const { config, response } = error;

    // Token 过期 → 自动刷新
    if (response?.status === 401) {
      try {
        const newToken = await refreshToken();
        if (config) {
          config.headers.Authorization = `Bearer ${newToken}`;
          return client(config); // 重试
        }
      } catch {
        redirectToLogin();
      }
    }

    // 网络超时 → 重试
    if (error.code === 'ECONNABORTED' && config) {
      if (!config._retryCount) config._retryCount = 0;
      if (config._retryCount < 3) {
        config._retryCount++;
        return client(config);
      }
    }

    // 统一上报错误
    reportError(error);
    return Promise.reject(error);
  }
);

6.2 安全防护体系

6.2.1 XSS 防护
// XSS 防护三原则:输入验证 + 输出编码 + CSP

// 1. 输入验证(前端第一道防线)
function sanitizeInput(input: string): string {
  return input
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#x27;')
    .replace(/\//g, '&#x2F;');
}

// 2. React 默认转义(JSX 自动编码)
// <div>{userInput}</div> → ✅ 自动编码

// 3. dangerouslySetInnerHTML 必须配合 DOMPurify
import DOMPurify from 'dompurify';

function SafeHTML({ html }: { html: string }) {
  const cleanHTML = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
    ALLOWED_ATTR: ['href', 'target'],
  });

  return <div dangerouslySetInnerHTML={{ __html: cleanHTML }} />;
}

// 4. CSP(Content Security Policy)HTTP 头
// Content-Security-Policy:
//   default-src 'self';
//   script-src 'self' 'wasm-unsafe-eval';
//   style-src 'self' 'unsafe-inline';
//   img-src 'self' https://cdn.example.com data:;
//   connect-src 'self' https://api.example.com;
//   font-src 'self';
🎯 某电商平台 XSS 漏洞安全事件处理案例
/**
 * 【某电商平台 XSS 漏洞安全事件处理案例】
 *
 * 事件背景:
 * - 2024 年 3 月,安全团队发现商品评论处存在 XSS 漏洞
 * - 攻击者可注入恶意脚本,窃取用户 Cookie 和订单信息
 * - 影响范围:所有使用评论功能的用户(约 500 万)
 *
 * 事件处理过程:
 * 1. 发现与上报(Day 1)
 * 2. 紧急修复(Day 1-2)
 * 3. 全站排查(Day 3-7)
 * 4. 安全审计(Day 8-14)
 * 5. 安全加固(Day 15-30)
 */

import DOMPurify from 'dompurify';
import { marked } from 'marked';

// 1. 紧急修复:输入过滤
function sanitizeUserInput(input: string): string {
  if (!input) return '';

  return DOMPurify.sanitize(input, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p', 'br'],
    ALLOWED_ATTR: [],
  });
}

// 2. 紧急修复:富文本内容过滤
function sanitizeRichContent(content: string): string {
  if (!content) return '';

  // 使用 marked 解析 Markdown
  const html = marked.parse(content, { async: false }) as string;

  // 严格过滤 HTML
  return DOMPurify.sanitize(html, {
    ALLOWED_TAGS: [
      'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
      'p', 'br', 'hr',
      'ul', 'ol', 'li',
      'blockquote', 'pre', 'code',
      'strong', 'em', 'del', 'ins',
      'a', 'img',
    ],
    ALLOWED_ATTR: ['href', 'src', 'alt', 'title', 'class'],
    ALLOW_DATA_ATTR: false,
    ADD_ATTR: ['target'],
  });
}

// 3. URL 验证
function validateUrl(url: string): boolean {
  try {
    const parsed = new URL(url);
    return ['http:', 'https:'].includes(parsed.protocol);
  } catch {
    return false;
  }
}

// 4. CSP 配置加固
const CSP_HEADER = `
  default-src 'self';
  script-src 'self' 'nonce-{NONCE}' 'strict-dynamic';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https://img.example.com;
  font-src 'self';
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
`.replace(/\s+/g, ' ').trim();

// 5. 安全监控告警
class SecurityMonitor {
  private suspiciousPatterns = [
    /<script/i,
    /javascript:/i,
    /on\w+\s*=/i,
    /<iframe/i,
    /<object/i,
    /<embed/i,
  ];

  logSecurityEvent(event: SecurityEvent) {
    // 上报到安全监控系统
    fetch('/api/security/events', {
      method: 'POST',
      body: JSON.stringify({
        ...event,
        timestamp: Date.now(),
        userAgent: navigator.userAgent,
        url: window.location.href,
      }),
    });

    // 高危事件立即告警
    if (event.severity === 'critical') {
      this.sendAlert(event);
    }
  }

  checkXSS(input: string): boolean {
    return this.suspiciousPatterns.some(pattern => pattern.test(input));
  }

  private sendAlert(event: SecurityEvent) {
    // 发送到安全告警渠道(企业微信/飞书)
    fetch('/api/security/alert', {
      method: 'POST',
      body: JSON.stringify({
        type: 'XSS_DETECTED',
        event,
      }),
    });
  }
}

// 6. 事件处理后的安全加固
// 实施后效果:
// - XSS 漏洞修复率:100%
// - 安全事件响应时间:24h → 2h
// - 安全告警准确率:95%+
// - 年度安全事件:50+ → 5
🎯 某社交平台 CSRF 攻击防护实战案例
/**
 * 【某社交平台 CSRF 攻击防护实战案例】
 *
 * 攻击背景:
 * - 攻击者诱导已登录用户访问恶意页面
 * - 利用用户的登录状态,自动发起转账/修改密码等操作
 * - 攻击成功率高达 30%
 *
 * 防护方案:
 * - SameSite Cookie
 * - CSRF Token(双重提交 Cookie 模式)
 * - 验证码/密码确认
 * - 请求头验证
 */

// 1. CSRF Token 生成与验证
class CSRFProtection {
  private tokenName = '_csrf_token';
  private headerName = 'X-CSRF-Token';

  generateToken(): string {
    const array = new Uint8Array(32);
    crypto.getRandomValues(array);
    return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
  }

  setTokenCookie(token: string): void {
    document.cookie = `${this.tokenName}=${token}; SameSite=Strict; Secure; HttpOnly; path=/`;
  }

  getTokenFromCookie(): string | null {
    const match = document.cookie.match(new RegExp(`(^| )${this.tokenName}=([^;]+)`));
    return match ? match[2] : null;
  }

  // 验证请求头中的 Token
  validateToken(requestToken: string): boolean {
    const cookieToken = this.getTokenFromCookie();
    return requestToken === cookieToken && cookieToken !== null;
  }
}

const csrfProtection = new CSRFProtection();

// 2. 请求拦截器中注入 Token
axios.interceptors.request.use(config => {
  const csrfToken = csrfProtection.getTokenFromCookie();
  if (csrfToken) {
    config.headers[csrfProtection.headerName] = csrfToken;
  }
  return config;
});

// 3. 敏感操作二次验证
function useSensitiveOperation() {
  const [requiresVerification, setRequiresVerification] = useState(false);
  const [verificationType, setVerificationType] = useState<'password' | 'sms' | null>(null);

  const requestVerification = (type: 'password' | 'sms') => {
    setVerificationType(type);
    setRequiresVerification(true);
  };

  const confirmVerification = async (code: string) => {
    if (verificationType === 'sms') {
      const response = await api.verifySmsCode(code);
      if (response.valid) {
        setRequiresVerification(false);
        return true;
      }
    } else if (verificationType === 'password') {
      const response = await api.verifyPassword(code);
      if (response.valid) {
        setRequiresVerification(false);
        return true;
      }
    }
    return false;
  };

  return { requiresVerification, requestVerification, confirmVerification };
}

// 4. 防护效果统计
// 实施 CSRF 防护后:
// - CSRF 攻击成功率:30% → 0%
// - 安全事件月均数量:15 → 0
// - 用户投诉:无
6.2.2 CSRF 防护 + Token 安全
// CSRF 防护
// 1. SameSite Cookie
// Set-Cookie: session=xxx; SameSite=Lax; Secure; HttpOnly

// 2. CSRF Token(双重提交 Cookie 模式)
function setCSRFToken() {
  const token = generateToken();
  document.cookie = `csrf_token=${token}; SameSite=Strict; Secure`;
  return token;
}

// 3. 自定义请求头验证(更安全)
axios.interceptors.request.use(config => {
  // 后端验证 X-CSRF-Token 头
  config.headers['X-CSRF-Token'] = getCSRFToken();
  return config;
});

// Token 安全存储
// ❌ localStorage → 容易被 XSS 窃取
// ✅ httpOnly Cookie → JS 无法读取,最安全

// JWT 拆分存储(进阶)
// Access Token(短期):httpOnly Cookie
// Refresh Token(长期):httpOnly Cookie + path 限制
// Set-Cookie: access_token=xxx; HttpOnly; Secure; SameSite=Strict; Max-Age=900
// Set-Cookie: refresh_token=xxx; HttpOnly; Secure; SameSite=Strict; Path=/auth/refresh
6.2.3 敏感数据加密
// 前端敏感数据加密(Web Crypto API)
async function encrypt(plaintext: string, password: string): Promise<string> {
  const enc = new TextEncoder();

  const keyMaterial = await crypto.subtle.importKey(
    'raw', enc.encode(password), 'PBKDF2', false, ['deriveKey']
  );

  const key = await crypto.subtle.deriveKey(
    { name: 'PBKDF2', salt: crypto.getRandomValues(new Uint8Array(16)),
      iterations: 100000, hash: 'SHA-256' },
    keyMaterial,
    { name: 'AES-GCM', length: 256 },
    false,
    ['encrypt']
  );

  const iv = crypto.getRandomValues(new Uint8Array(12));
  const encrypted = await crypto.subtle.encrypt(
    { name: 'AES-GCM', iv },
    key,
    enc.encode(plaintext)
  );

  return JSON.stringify({
    iv: Array.from(iv),
    data: Array.from(new Uint8Array(encrypted)),
  });
}
🎯 某金融平台数据安全合规改造案例
/**
 * 【某金融平台数据安全合规改造案例】
 *
 * 背景:
 * - 金融行业,合规要求极高(等保三级、PCI-DSS)
 * - 需要对敏感数据进行加密存储和传输
 * - 用户身份证号、银行卡号、交易密码等必须加密
 *
 * 合规要求:
 * 1. 敏感数据加密存储(前端也要加密)
 * 2. 传输链路加密(HTTPS + TLS 1.3)
 * 3. 密钥管理(不能在前端硬编码)
 * 4. 操作日志(所有敏感操作必须审计)
 */

import { crypto } from 'crypto';

// 1. 敏感数据加密 SDK
class SensitiveDataEncryptor {
  private publicKey: CryptoKey | null = null;
  private readonly KEY_ID = 'sensitive-data-key-v1';

  async initialize() {
    // 从密钥服务获取公钥
    const keyData = await fetch('/api/keys/sensitive-data', {
      headers: { 'X-Request-ID': generateRequestId() },
    }).then(r => r.json());

    this.publicKey = await crypto.subtle.importKey(
      'spki',
      Uint8Array.from(atob(keyData.publicKey), c => c.charCodeAt(0)),
      { name: 'RSA-OAEP', hash: 'SHA-256' },
      false,
      ['encrypt']
    );
  }

  // 加密敏感数据
  async encrypt(data: string): Promise<string> {
    if (!this.publicKey) {
      await this.initialize();
    }

    // 生成随机 AES 密钥
    const aesKey = await crypto.subtle.generateKey(
      { name: 'AES-GCM', length: 256 },
      true,
      ['encrypt']
    );

    // 使用 RSA 公钥加密 AES 密钥
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const encryptedAesKey = await crypto.subtle.encrypt(
      { name: 'RSA-OAEP' },
      this.publicKey!,
      await crypto.subtle.exportKey('raw', aesKey)
    );

    // 使用 AES 加密数据
    const encryptedData = await crypto.subtle.encrypt(
      { name: 'AES-GCM', iv },
      aesKey,
      new TextEncoder().encode(data)
    );

    // 返回加密后的数据(包含加密的 AES 密钥)
    return JSON.stringify({
      version: this.KEY_ID,
      algorithm: 'RSA-OAEP+AES-GCM',
      iv: Array.from(iv),
      encryptedKey: Array.from(new Uint8Array(encryptedAesKey)),
      encryptedData: Array.from(new Uint8Array(encryptedData)),
    });
  }
}

// 2. 身份证号脱敏
function maskIdCard(idCard: string): string {
  if (!idCard || idCard.length !== 18) return idCard;
  return `${idCard.slice(0, 6)}********${idCard.slice(-4)}`;
}

// 3. 银行卡号脱敏
function maskBankCard(bankCard: string): string {
  if (!bankCard || bankCard.length < 12) return bankCard;
  return `${bankCard.slice(0, 4)} **** **** ${bankCard.slice(-4)}`;
}

// 4. 手机号脱敏
function maskPhone(phone: string): string {
  if (!phone || phone.length !== 11) return phone;
  return `${phone.slice(0, 3)}****${phone.slice(-4)}`;
}

// 5. 敏感操作日志
class SensitiveOperationLogger {
  log(operation: string, data: SensitiveOperationData) {
    const logEntry = {
      timestamp: new Date().toISOString(),
      userId: getCurrentUserId(),
      operation,
      ip: getClientIP(),
      userAgent: navigator.userAgent,
      // 敏感数据脱敏后记录
      dataMasked: this.maskSensitiveData(data),
    };

    // 发送到日志服务
    fetch('/api/security/audit-log', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Request-ID': generateRequestId(),
      },
      body: JSON.stringify(logEntry),
    });
  }

  private maskSensitiveData(data: any): any {
    const mask = (value: string) => {
      if (!value) return value;
      if (value.length <= 8) return '****';
      return `${value.slice(0, 4)}****${value.slice(-4)}`;
    };

    return {
      idCard: mask(data.idCard),
      bankCard: mask(data.bankCard),
      phone: mask(data.phone),
      // 其他字段正常记录
      ...data,
    };
  }
}

// 6. 安全组件:敏感信息展示
function SensitiveDisplay({ value, type }: { value: string; type: 'idCard' | 'bankCard' | 'phone' | 'custom' }) {
  const [revealed, setRevealed] = useState(false);
  const { requiresVerification, requestVerification, confirmVerification } = useSensitiveOperation();

  const handleReveal = async () => {
    if (!revealed) {
      // 敏感操作需要二次验证
      requestVerification('password');
    } else {
      setRevealed(false);
    }
  };

  const getMaskedValue = () => {
    switch (type) {
      case 'idCard': return maskIdCard(value);
      case 'bankCard': return maskBankCard(value);
      case 'phone': return maskPhone(value);
      default: return value.slice(0, 4) + '****' + value.slice(-4);
    }
  };

  return (
    <div className="sensitive-display">
      <span className="value">{revealed ? value : getMaskedValue()}</span>
      <button onClick={handleReveal}>
        {revealed ? '隐藏' : '查看'}
      </button>

      {requiresVerification && (
        <VerificationModal
          type={verificationType}
          onVerify={confirmVerification}
          onCancel={() => setRequiresVerification(false)}
        />
      )}
    </div>
  );
}

// 效果:
// - 合规审计通过率:70% → 100%
// - 敏感数据泄露事件:5 → 0
// - 安全告警响应时间:4h → 15min

6.3 稳定性监控与容灾

6.3.1 Sentry 错误监控集成
import * as Sentry from '@sentry/react';

Sentry.init({
  dsn: ENV.SENTRY_DSN,

  // 环境区分
  environment: import.meta.env.VITE_APP_ENV,

  // 采样率(生产 10% 以减少费用)
  tracesSampleRate: ENV.isProd ? 0.1 : 1.0,
  replaysSessionSampleRate: ENV.isProd ? 0.01 : 1.0,

  // Release 标记(关联 Git 版本)
  release: import.meta.env.VITE_APP_VERSION,

  beforeSend(event, hint) {
    // 过滤已知的非关键错误
    const error = hint.originalException;
    if (error instanceof NetworkError && event.message?.includes('timeout')) {
      return null; // 忽略网络超时错误
    }
    return event;
  },
});

// 错误边界集成
function App() {
  return (
    <Sentry.ErrorBoundary fallback={<ErrorPage />}>
      <RouterProvider router={router} />
    </Sentry.ErrorBoundary>
  );
}

// 手动上报
Sentry.captureException(new Error('Custom error'), {
  tags: { module: 'payment' },
  extra: { userId: '123' },
});
6.3.2 容灾方案与降级策略
// 降级策略
const DEGRADE_STRATEGY = {
  // 1. 功能降级(API 不可用时,使用本地缓存)
  featureDegrade: (api: () => Promise<T>, cache: () => T | null) => {
    return async (): Promise<T> => {
      try {
        return await api();
      } catch {
        const cached = cache();
        if (cached) {
          console.warn('API failed, using cache');
          return cached;
        }
        throw new Error('Service unavailable');
      }
    };
  },

  // 2. 组件降级(CDN 不可用时)
  componentDegrade: (primary: LazyComponent, fallback: LazyComponent) => {
    return lazy(() =>
      primary().catch(() => {
        console.warn('Primary component failed, using fallback');
        return fallback();
      })
    );
  },

  // 3. 服务降级(重试失败后)
  serviceDegrade: async (request: () => Promise<T>, fallback: () => T) => {
    try {
      return await retry(request, { times: 3 });
    } catch {
      console.warn('Service degraded');
      return fallback();
    }
  },
};

// 全局错误边界
class GlobalErrorBoundary extends React.Component<
  { children: React.ReactNode },
  { hasError: boolean }
> {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error: Error, info: React.ErrorInfo) {
    Sentry.captureException(error, { contexts: { react: info } });
  }

  render() {
    if (this.state.hasError) {
      return (
        <div className="error-fallback">
          <h1>页面出了点问题</h1>
          <p>请刷新重试,或联系技术支持</p>
          <button onClick={() => window.location.reload()}>刷新页面</button>
          <a href="/">返回首页</a>
        </div>
      );
    }

    return this.props.children;
  }
}

七、团队赋能 & 技术管理

7.1 组件生态建设

7.1.1 Storybook 组件文档体系
// packages/ui/src/Button/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  title: 'UI/Button',
  component: Button,
  args: {
    children: '按钮文本',
    variant: 'primary',
    size: 'md',
    disabled: false,
  },
  argTypes: {
    variant: {
      control: 'select',
      options: ['primary', 'secondary', 'danger', 'ghost'],
    },
    size: {
      control: 'select',
      options: ['sm', 'md', 'lg'],
    },
    onClick: { action: 'clicked' },
  },
};

export default meta;
type Story = StoryObj<typeof meta>;

// 用例 1:基础按钮
export const Primary: Story = { args: { variant: 'primary' } };

// 用例 2:Loading 状态
export const Loading: Story = {
  args: { loading: true, children: '提交中' },
};

// 用例 3:交互式自动测试
export const Clickable: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const button = canvas.getByRole('button');
    await userEvent.click(button);
    // 验证 onClick 被调用
  },
};
7.1.2 组件库维护策略
版本管理:
├── 语义化版本(SemVer)
│   ├── Major: 不兼容的 API 变更
│   ├── Minor: 向后兼容的功能新增
│   └── Patch: 向后兼容的 Bug 修复
├── Changeset 管理(自动生成 CHANGELOG)

质量保障:
├── 每个组件最少 3 个测试用例
├── 每个组件有 Storybook 文档
├── TypeScript 类型导出
├── A11y 审计通过
└── Bundle Size 监控(小于阈值)

发布流程:
├── MR → Code Review
├── Changeset → CHANGELOG
├── CI 通过
└── npm publish

7.2 技术输出与知识传承

7.2.1 技术方案模板(RFC)
# RFC: [功能名称]

## 背景与动机
为什么需要这个功能?解决了什么痛点?

## 方案设计

### 整体架构
(架构图 + 核心流程说明)

### 前端方案
- 核心组件设计
- 状态管理方案
- 路由设计

### 接口设计
- API 列表
- 请求/响应格式

## 风险与应对
| 风险 | 影响 | 概率 | 应对措施 |
|------|------|------|----------|
| xxx  | xxx  | xxx  | xxx      |

## 替代方案
为什么这些方案被否决?

## 排期
| 里程碑 | 日期 | 交付物 |
|--------|------|--------|
7.2.2 代码评审 (CR) 清单
功能检查:
├── 实现了预期的功能?
├── 处理了边界情况?(空值、异常输入)

代码质量:
├── 命名是否清晰表达意图?
├── 函数是否遵循单一职责?
├── 消除了重复代码?

性能检查:
├── 是否有不必要的重渲染?
├── 大列表是否用了虚拟滚动?
├── 图片是否懒加载?

安全审查:
├── 是否有 XSS 风险?(dangerouslySetInnerHTML)
├── 敏感数据是否明文存储?
├── 用户输入是否校验和清洗?

可维护性:
├── 组件是否足够独立?
├── 是否有必要的类型定义?
├── 是否有必要的单元测试?
7.2.3 新人培训体系
Week 1: 环境搭建 + 基础文档
├── IDE & 工具链配置
├── 阅读 Coding Standards
├── 阅读基础层文档
└── 完成 Todo List Demo

Week 2-3: 业务入门
├── 阅读本项目 RFC 文档
├── 完成 Bug Fix PR
├── 参与 Code Review
└── 阅读进阶层文档

Week 4-6: 独立开发
├── 独立完成 1 个 Feature
├── 了解 CI/CD 流程
└── 参与日常站会

Month 2-3: 深入参与
├── 参与技术方案设计
├── 负责一个模块的 Owner
└── 阅读精通层文档

7.3 研发效率提升

7.3.1 低代码平台设计
// Schema 驱动的页面 = JSON 配置 → 组件解析器 → 页面
interface PageSchema {
  layout: 'grid' | 'flex' | 'tabs';
  sections: PageSection[];
  dataSources: DataSource[];
}

interface PageSection {
  id: string;
  type: 'table' | 'form' | 'chart' | 'cards';
  config: TableConfig | FormConfig | ChartConfig;
  dataSourceKey: string;  // 关联数据
  permissions?: string[];
}

// 页面渲染引擎
function SchemaRenderer({ schema }: { schema: PageSchema }) {
  // 数据聚合
  const dataSources = useDataSources(schema.dataSources);

  // 权限过滤(隐藏无权限的 section)
  const visibleSections = schema.sections.filter(s =>
    s.permissions?.every(p => hasPermission(p)) ?? true
  );

  return (
    <Layout type={schema.layout}>
      {visibleSections.map(section => (
        <SectionRenderer
          key={section.id}
          type={section.type}
          config={section.config}
          data={dataSources[section.dataSourceKey]}
        />
      ))}
    </Layout>
  );
}
7.3.2 代码生成器
# 脚手架 codegen 命令
react-cli gen component UserProfile
# 生成:
# - UserProfile/index.tsx
# - UserProfile/UserProfile.test.tsx
# - UserProfile/UserProfile.stories.tsx
# - UserProfile/UserProfile.module.css
# - UserProfile/types.ts

react-cli gen hook useProductList
# 生成:
# - hooks/useProductList.ts
# - hooks/__tests__/useProductList.test.ts

react-cli gen api Product
# 生成:
# - api/modules/product.api.ts
# - dto/product.dto.ts

八、前沿技术跟踪

8.1 React 最新特性

8.1.1 React 19 核心变化
// 1. React Server Components (RSC) 进入稳定期
// app/page.tsx (Server Component)
export default async function Page() {
  const data = await fetch('https://api.example.com/data');
  const json = await data.json();

  return (
    <div>
      <h1>Server Rendered</h1>
      <ClientInteractivity data={json} />
    </div>
  );
}

// 2. Actions (Server Actions)
// app/actions.ts
'use server';

export async function createPost(data: FormData) {
  const title = data.get('title');
  await db.post.create({ data: { title } });
  revalidatePath('/posts');
}

// app/page.tsx
export default function NewPost() {
  return (
    <form action={createPost}>
      <input name="title" />
      <button type="submit">Create</button>
    </form>
  );
}

// 3. use() Hook(读取 Promise/Context)
function UserList({ usersPromise }: { usersPromise: Promise<User[]> }) {
  const users = React.use(usersPromise); // 直接 use Promise

  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
}

// 4. useOptimistic(乐观更新)
function MessageList({ messages }) {
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [...state, newMessage]
  );

  const sendMessage = async (text: string) => {
    addOptimisticMessage({ text, pending: true });
    await api.sendMessage(text);
  };

  return (
    <div>
      {optimisticMessages.map(msg => (
        <Message key={msg.id} text={msg.text} pending={msg.pending} />
      ))}
      <SendForm onSend={sendMessage} />
    </div>
  );
}
8.1.2 React Forget(自动 Memoization 编译器)
// React Forget (即将发布) → 无需手动 useMemo/useCallback
// 编译器自动分析并注入 memoization

// 今天写的代码(手动 memo):
const processedData = useMemo(() => {
  return items.filter(i => i.active).map(i => ({ ...i, label: i.name }));
}, [items]);

const handleClick = useCallback(() => {
  onClick(id);
}, [onClick, id]);

// React Forget 之后(编译器自动处理):
const processedData = items.filter(i => i.active).map(i => ({ ...i, label: i.name }));
const handleClick = () => onClick(id);
// ↑ 编译器自动识别依赖并注入等价的 memoization
// ↓ 生成等价的代码:
// const processedData = useMemo(..., [items]);
// const handleClick = useCallback(..., [onClick, id]);

8.2 前沿架构方案

8.2.1 RSC(React Server Components)
// Server Component:在服务端运行,无客户端 JS
// app/products/page.server.tsx
export default async function ProductList() {
  const products = await db.product.findMany();

  return (
    <ul>
      {products.map(product => (
        <li key={product.id}>
          {product.name} - ${product.price}
          {/* Client Component 嵌套 */}
          <AddToCartButton productId={product.id} />
        </li>
      ))}
    </ul>
  );
}

// Client Component:在浏览器运行
'use client';

function AddToCartButton({ productId }: { productId: string }) {
  const addToCart = useCartStore(s => s.addItem);
  const [loading, setLoading] = useState(false);

  return (
    <button
      onClick={async () => {
        setLoading(true);
        await addToCart(productId);
        setLoading(false);
      }}
      disabled={loading}
    >
      {loading ? '添加中...' : '加入购物车'}
    </button>
  );
}
8.2.2 Islands Architecture(岛屿架构)
传统 SSR:整个页面 hydration(交互注水)→ 所有组件需要 JS

Islands 架构:
├── 静态 HTML(海洋)
│   ├── 不需要 JS → 零 bundle
│   └── 大部分页面内容
└── 交互组件(岛屿)
    ├── 需要 JS → 仅加载必要代码
    └── 每个岛独立 hydration

优势:
├── 首屏 HTML 立即可用
├── 非交互部分零 JS
├── 每个交互独立加载/ Hydrate
└── 显著减少首屏 JS 体积
// Island 组件(仅关键交互部分使用 JS)
import { island } from '@company/island';

const AddToCart = island(() => import('./AddToCart'), {
  fallback: <Button disabled>加载中</Button>,
  defer: true,          // 延迟 Hydrate
  intersect: true,      // 进入视口才 Hydrate
});

const ProductRating = island(() => import('./ProductRating'), {
  defer: true,
  intersect: true,
});
8.2.3 Remix 框架(Web 标准优先)
// Remix 核心理念:基于 Web 标准的 <form> 而非 JS 驱动的 fetch

// route.tsx
import { ActionFunctionArgs, LoaderFunctionArgs, json } from '@remix-run/node';
import { Form, useLoaderData, useActionData } from '@remix-run/react';

// Server Loader(服务端数据获取)
export async function loader({ params }: LoaderFunctionArgs) {
  const product = await db.product.findUnique({ where: { id: params.id } });
  return json({ product });
}

// Server Action(服务端表单处理)
export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const title = formData.get('title');
  const review = await db.review.create({ data: { title } });
  return json({ review });
}

// 客户端组件
export default function Product() {
  const { product } = useLoaderData<typeof loader>();
  const actionData = useActionData<typeof action>();

  return (
    <div>
      <h1>{product.name}</h1>
      <Form method="post">
        <input name="title" placeholder="写评论" />
        <button type="submit">提交</button>
      </Form>
      {actionData?.review && <p>评论成功!</p>}
    </div>
  );
}

附录:架构师能力模型

📊 React 架构师能力金字塔

Level 5: 技术布道者(影响行业)
├── 开源贡献
├── 技术博客 / 演讲
├── 制定团队技术战略
└── 推动前端技术演进

Level 4: 架构师(主导大型项目)
├── 微前端架构
├── 性能优化全链路
├── 工程化体系搭建
├── 安全架构设计
└── 阶段性技术 Review & 规划

Level 3: 高级工程师(独立负责模块)
├── 底层原理理解
├── 现代状态管理
├── TypeScript 工程化
├── SSR/SSG 实践
└── 技术方案设计

Level 2: 中级工程师(独立开发)
├── React 核心 API 熟练
├── 性能优化(memo/useCallback)
├── 基础路由与状态管理
├── Testing Unit Test
└── Code Review 参与

Level 1: 初级工程师(学习与模仿)
├── JSX/State/Props
├── 基础 Hooks
├── 表单处理
├── 调试技巧
└── 编码规范遵守

📚 扩展推荐

  • React 源码分析:React.tech(中文社区源码分析)
  • 微前端:qiankun、wujie 官方文档
  • 性能监控:Lighthouse、WebPageTest
  • 设计模式:《重构》《设计模式》GoF
  • 架构设计:《前端架构师培养手册》
  • 工程化:《Creating CI/CD Pipelines for Frontend》

🎯 进阶里程碑

入门(0-6 个月)
├── 可以独立开发业务页面
└── 掌握 React 核心 API

进阶(6-18 个月)
├── 理解 React 底层原理
├── 解决复杂业务问题
└── 掌握现代状态管理

精通(2+ 年)
├── 架构设计能力
├── 极致性能优化
├── 大型应用解决方案
└── 团队赋能与培训

总结

本文档从资深 React 架构师的角度,全面梳理了精通层的核心能力体系:

🎯 三大核心能力

  1. 架构设计:分层解耦、组件架构、路由架构、状态架构、可扩展性
  2. 大型应用:微前端(qiankun/MF)、SSR 深度实践(Next.js)、中后台权限架构
  3. 极致性能:运行时优化、构建优化、Web Vitals、性能监控体系

🏗️ 三大工程体系

  1. 工程化体系:自研脚手架、CI/CD、Docker 部署、规范体系
  2. 技术治理:技术选型决策框架、技术债务管理、依赖治理
  3. 安全架构:XSS/CSRF 防护、数据加密、Sentry 监控、容灾降级

🤝 两大软技能

  1. 团队赋能:Storybook 组件文档、Code Review 机制、新人培训体系
  2. 前沿技术:React 19 新特性、React Forget、RSC、Server Actions

版本:v1.0
最后更新:2026-05-10
前置要求:完成基础层 + 进阶层学习
适用版本:React 18+ / Next.js 14+ / Vite 5+ / TypeScript 5+
作者视角:基于 5 年+ React 大型项目架构经验 + 源码分析 + 技术管理经验

更多推荐