前端架构演进与模块化设计实践

avatar
@海尔优家智能科技(北京)有限公司

 引言:从"能运行"到"好维护"的转变

在快速迭代的业务需求面前,我们是否经常遇到这样的场景:新功能不敢轻易开发,因为担心影响现有业务;代码修改牵一发而动全身;不同业务模块间耦合严重,难以独立部署和测试。这些问题背后,反映的是前端架构设计的重要性。

1. 架构设计的核心目标

1.1 可持续性

  • 代码应易于理解和扩展
  • 新成员能够快速融入开发
  • 技术债务可控

1.2 可维护性

  • 模块职责清晰明确
  • 变更影响范围可控
  • 调试和定位问题高效

1.3 可测试性

  • 组件能够独立测试
  • 模拟各种业务场景
  • 自动化测试覆盖核心流程

2. 现代前端架构模式实践

2.1 分层架构设计

whiteboard_exported_image.png

实践案例:用户管理模块

// 表现层 - UserList.tsx
const UserList: React.FC = () => {
  const { users, loading, error } = useUserManagement();
  
  if (loading) return <Loading />;
  if (error) return <Error message={error} />;
  
  return (
    <div>
      {users.map(user => (
        <UserCard key={user.id} user={user} />
      ))}
    </div>
  );
};

// 业务层 - useUserManagement.ts
export const useUserManagement = () => {
  const [state, setState] = useState<UserState>(initialState);
  
  const fetchUsers = async () => {
    try {
      setState(prev => ({ ...prev, loading: true }));
      const users = await userAPI.fetchAll();
      setState(prev => ({ ...prev, users, loading: false }));
    } catch (error) {
      setState(prev => ({ ...prev, error: error.message, loading: false }));
    }
  };
  
  return { ...state, fetchUsers };
};

// 数据层 - userAPI.ts
export const userAPI = {
  fetchAll: async (): Promise<User[]> => {
    const response = await fetch('/api/users');
    return response.json();
  }
};

2.2 微前端架构实践

场景:大型管理平台,多个团队协作开发

解决方案:

// 主应用 - 路由配置
const routes = [
  {
    path: '/order/*',
    component: () => import('order-app/OrderModule'),
  },
  {
    path: '/user/*', 
    component: () => import('user-app/UserModule'),
  },
  {
    path: '/product/*',
    component: () => import('product-app/ProductModule'),
  }
];

// 模块联邦配置 - webpack.config.js
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      remotes: {
        orderApp: 'order@http://localhost:3001/remoteEntry.js',
        userApp: 'user@http://localhost:3002/remoteEntry.js',
      },
      shared: {
        react: { singleton: true },
        'react-dom': { singleton: true }
      }
    })
  ]
};

3. 模块化设计原则

3.1 单一职责原则

// ❌ 违反单一职责
class UserService {
  async getUser(id: string) { /* ... */ }
  validateEmail(email: string) { /* ... */ }
  sendEmail(content: string) { /* ... */ }
  formatUserData(user: User) { /* ... */ }
}

// ✅ 符合单一职责
class UserRepository {
  async getUser(id: string) { /* ... */ }
}

class ValidationService {
  validateEmail(email: string) { /* ... */ }
}

class EmailService {
  sendEmail(content: string) { /* ... */ }
}

class UserFormatter {
  formatUserData(user: User) { /* ... */ }
}

3.2 依赖倒置原则

// 定义抽象接口
interface UserStorage {
  save(user: User): Promise<void>;
  findById(id: string): Promise<User | null>;
}

// 具体实现
class LocalStorageUser implements UserStorage {
  async save(user: User) {
    localStorage.setItem(`user_${user.id}`, JSON.stringify(user));
  }
  
  async findById(id: string) {
    const data = localStorage.getItem(`user_${id}`);
    return data ? JSON.parse(data) : null;
  }
}

class APITUserStorage implements UserStorage {
  async save(user: User) {
    await fetch('/api/users', {
      method: 'POST',
      body: JSON.stringify(user)
    });
  }
  
  async findById(id: string) {
    const response = await fetch(`/api/users/${id}`);
    return response.json();
  }
}

// 业务逻辑依赖于抽象,而非具体实现
class UserService {
  constructor(private storage: UserStorage) {}
  
  async updateUser(user: User) {
    // 业务逻辑
    await this.storage.save(user);
  }
}

4. 状态管理架构演进

4.1 状态分类与管理策略

// 1. 本地状态 - 使用 useState/useReducer
const [formData, setFormData] = useState(initialFormData);

// 2. 全局状态 - 使用 Zustand(推荐轻量级方案)
const useUserStore = create((set, get) => ({
  users: [],
  loading: false,
  fetchUsers: async () => {
    set({ loading: true });
    const users = await userAPI.fetchAll();
    set({ users, loading: false });
  },
  addUser: (user: User) => {
    set(state => ({ 
      users: [...state.users, user] 
    }));
  }
}));

// 3. 服务端状态 - 使用 React Query/SWR
const { data: users, isLoading, error } = useQuery({
  queryKey: ['users'],
  queryFn: fetchUsers,
  staleTime: 5 * 60 * 1000, // 5分钟
});

4.2 状态规范化

//  嵌套深、难以更新的状态
const state = {
  posts: [
    {
      id: 1,
      title: 'Post 1',
      author: {
        id: 1,
        name: 'John',
        avatar: '...'
      },
      comments: [
        {
          id: 1,
          text: 'Great!',
          user: {
            id: 2,
            name: 'Alice'
          }
        }
      ]
    }
  ]
};

//  规范化状态
const normalizedState = {
  posts: {
    byId: {
      1: { id: 1, title: 'Post 1', author: 1, comments: [1] }
    },
    allIds: [1]
  },
  users: {
    byId: {
      1: { id: 1, name: 'John', avatar: '...' },
      2: { id: 2, name: 'Alice' }
    },
    allIds: [1, 2]
  },
  comments: {
    byId: {
      1: { id: 1, text: 'Great!', user: 2, post: 1 }
    },
    allIds: [1]
  }
};

5. 构建可测试的架构

5.1 依赖注入与测试

// 业务逻辑
class OrderService {
  constructor(
    private paymentGateway: PaymentGateway,
    private notificationService: NotificationService,
    private inventoryService: InventoryService
  ) {}
  
  async processOrder(order: Order) {
    // 1. 扣减库存
    await this.inventoryService.reserve(order.items);
    
    // 2. 处理支付
    const paymentResult = await this.paymentGateway.charge(order.total);
    
    // 3. 发送通知
    if (paymentResult.success) {
      await this.notificationService.sendOrderConfirmation(order);
    }
    
    return paymentResult;
  }
}

// 单元测试
describe('OrderService', () => {
  it('should process order successfully', async () => {
    // 准备测试替身
    const mockPaymentGateway = {
      charge: jest.fn().mockResolvedValue({ success: true })
    };
    const mockNotificationService = {
      sendOrderConfirmation: jest.fn().mockResolvedValue(undefined)
    };
    const mockInventoryService = {
      reserve: jest.fn().mockResolvedValue(undefined)
    };
    
    // 创建被测试实例
    const orderService = new OrderService(
      mockPaymentGateway,
      mockNotificationService,
      mockInventoryService
    );
    
    // 执行测试
    const result = await orderService.processOrder(testOrder);
    
    // 验证行为
    expect(result.success).toBe(true);
    expect(mockInventoryService.reserve).toHaveBeenCalledWith(testOrder.items);
    expect(mockPaymentGateway.charge).toHaveBeenCalledWith(testOrder.total);
    expect(mockNotificationService.sendOrderConfirmation).toHaveBeenCalledWith(testOrder);
  });
});

6. 架构质量度量与改进

6.1 代码质量指标

// 使用 ESLint 插件监控架构质量
module.exports = {
  rules: {
    'max-dependencies': ['error', 10], // 单个模块最大依赖数
    'cyclic-dependency': 'error',       // 禁止循环依赖
    'no-relative-import': 'error',      // 禁止相对导入
    'feature-envy': 'error'             // 禁止特性依恋
  }
};

// package.json 依赖治理
{
  "scripts": {
    "analyze:deps": "madge --image deps-graph.svg src/",
    "analyze:complexity": "complexity-report src/",
    "check:circular": "dpdm --circular src/**/*.ts"
  }
}

7. 结语

好的前端架构不是一蹴而就的,而是随着业务发展和团队成长不断演进的过程。它需要在过度设计与缺乏设计之间找到平衡,在满足当前需求的同时为未来变化留出空间。

架构的终极目标不是构建完美的系统,而是创建能够优雅演进的系统。希望本文的实践经验能够为团队在架构设计方面提供有价值的参考,欢迎大家共同探讨和改进我们的前端架构实践。

8. 团队介绍

智慧家技术平台-应用软件框架开发」主要负责设计工具的研发,包括营销设计工具、家电VR设计和展示、水电暖通前置设计能力,研发并沉淀素材库,构建家居家装素材库,集成户型库、全品类产品库、设计方案库、生产工艺模型,打造基于户型和风格的AI设计能力,快速生成算量和报价;同时研发了门店设计师中心和项目中心,包括设计师管理能力和项目经理管理能力。实现了场景全生命周期管理,同时为水,空气,厨房等产业提供商机管理工具,从而实现了以场景贯穿的B端C端全流程系统。