跳转至

前端架构设计

前端架构设计

📚 章节目标

本章节将全面介绍前端架构设计的核心概念和方法,包括架构模式、设计原则、技术选型等,帮助学习者掌握前端架构设计的核心方法。

学习目标

  1. 理解前端架构设计的核心概念
  2. 掌握常见的前端架构模式
  3. 掌握前端架构设计原则
  4. 掌握技术选型策略
  5. 理解前端架构演进
  6. 掌握前端架构最佳实践

🏗️ 前端架构概述

1. 什么是前端架构

JavaScript
// 前端架构定义
// 前端架构是前端系统的结构和组织方式
// 包括技术选型、代码组织、模块划分、通信机制等

// 前端架构的目标
// 1. 可维护性 - 代码易于理解和修改
// 2. 可扩展性 - 系统易于扩展新功能
// 3. 可测试性 - 代码易于测试
// 4. 可复用性 - 组件和模块易于复用
// 5. 性能优化 - 系统性能良好

// 前端架构的要素
// 1. 技术栈选择
// 2. 代码组织
// 3. 模块划分
// 4. 状态管理
// 5. 路由设计
// 6. API设计
// 7. 构建工具
// 8. 部署策略

2. 前端架构演进

JavaScript
// 前端架构演进
// 1. 多页应用 (MPA) - 传统的服务端渲染
// 2. 单页应用 (SPA) - 客户端渲染
// 3. 服务端渲染 (SSR) - 结合服务端和客户端渲染
// 4. 静态站点生成 (SSG) - 预渲染静态页面
// 5. 增量静态再生成 (ISR) - 静态生成 + 按需更新
// 6. 微前端架构 - 拆分大型应用
// 7. 边缘渲染 (Edge Rendering) - 在边缘节点渲染

// 架构演进示例
// MPA -> SPA -> SSR -> SSG -> ISR -> 微前端

🎨 前端架构模式

1. MVC架构

JavaScript
// MVC (Model-View-Controller)
// Model - 数据模型
// View - 视图
// Controller - 控制器

// Model
class UserModel {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  save() {
    // 保存到服务器(显式选择字段,避免序列化整个实例泄露敏感数据)
    return fetch('/api/users', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ name: this.name, email: this.email }),
    });
  }
}

// View
class UserView {
  render(user) {
    return `
      <div>
        <h1>${user.name}</h1>
        <p>${user.email}</p>
      </div>
    `;
  }
}

// Controller
class UserController {
  constructor(model, view) {
    this.model = model;
    this.view = view;
  }

  handleSave() {
    this.model.save();
    const html = this.view.render(this.model);
    document.getElementById('app').innerHTML = html;
  }
}

// 使用
const model = new UserModel('John', 'john@example.com');
const view = new UserView();
const controller = new UserController(model, view);
controller.handleSave();

2. MVVM架构

JavaScript
// MVVM (Model-View-ViewModel)
// Model - 数据模型
// View - 视图
// ViewModel - 视图模型

// Model
class UserModel {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }
}

// ViewModel
class UserViewModel {
  constructor(model) {
    this.model = model;
    this.name = model.name;
    this.email = model.email;
  }

  get formattedEmail() {
    return this.email.toLowerCase();
  }

  save() {
    return this.model.save();
  }
}

// View (React)
function UserView({ viewModel }) {
  return (
    <div>
      <h1>{viewModel.name}</h1>
      <p>{viewModel.formattedEmail}</p>
      <button onClick={() => viewModel.save()}>Save</button>
    </div>
  );
}

// 使用
const model = new UserModel('John', 'john@example.com');
const viewModel = new UserViewModel(model);
<UserView viewModel={viewModel} />;

3. 分层架构

JavaScript
// 分层架构
// 1. 表现层 (Presentation Layer) - UI组件
// 2. 业务逻辑层 (Business Logic Layer) - 业务规则
// 3. 数据访问层 (Data Access Layer) - 数据操作

// 表现层
function UserList() {
  const { users, loading, error } = useUsers();  // 解构赋值:从对象/数组提取值

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <ul>
      {users.map(user => (  // map转换每个元素;filter筛选;reduce累积
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

// 业务逻辑层
class UserService {
  constructor(userRepository) {
    this.userRepository = userRepository;
  }

  async getUsers() {
    const users = await this.userRepository.findAll();  // await等待异步操作完成
    return users.filter(user => user.active);
  }

  async createUser(userData) {
    // 验证数据
    if (!userData.name || !userData.email) {
      throw new Error('Invalid user data');
    }

    return this.userRepository.create(userData);
  }
}

// 数据访问层
class UserRepository {
  constructor(apiClient) {
    this.apiClient = apiClient;
  }

  async findAll() {
    const response = await this.apiClient.get('/users');
    return response.data;
  }

  async create(userData) {
    const response = await this.apiClient.post('/users', userData);
    return response.data;
  }
}

4. 微前端架构

JavaScript
// 微前端架构
// 将大型应用拆分成多个小型应用
// 每个应用可以独立开发、部署、运行

// 主应用
import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'react-app',
    entry: '//localhost:7100',
    container: '#subapp-viewport',
    activeRule: '/react',
  },
  {
    name: 'vue-app',
    entry: '//localhost:7200',
    container: '#subapp-viewport',
    activeRule: '/vue',
  },
]);

start();

// 子应用
// React应用
export async function bootstrap() {}  // async定义异步函数;await等待Promise完成
export async function mount(props) {}
export async function unmount(props) {}

// Vue应用
export async function bootstrap() {}
export async function mount(props) {}
export async function unmount(props) {}

📐 前端架构设计原则

1. SOLID原则

JavaScript
// S - Single Responsibility Principle (单一职责原则)
// 每个类/函数应该只有一个职责

// 不好的做法
class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }

  save() {
    // 保存用户
  }

  sendEmail() {
    // 发送邮件
  }

  validate() {
    // 验证数据
  }
}

// 好的做法
class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }
}

class UserRepository {
  save(user) {
    // 保存用户
  }
}

class EmailService {
  sendEmail(to, subject, body) {
    // 发送邮件
  }
}

class UserValidator {
  validate(user) {
    // 验证数据
  }
}

// O - Open/Closed Principle (开闭原则)
// 对扩展开放,对修改关闭

// 不好的做法
class DiscountCalculator {
  calculate(price, type) {
    if (type === 'student') {
      return price * 0.9;
    } else if (type === 'senior') {
      return price * 0.8;
    }
    // 每次添加新类型都需要修改
  }
}

// 好的做法
class DiscountStrategy {
  calculate(price) {
    throw new Error('Must implement calculate method');
  }
}

class StudentDiscount extends DiscountStrategy {
  calculate(price) {
    return price * 0.9;
  }
}

class SeniorDiscount extends DiscountStrategy {
  calculate(price) {
    return price * 0.8;
  }
}

class DiscountCalculator {
  calculate(price, strategy) {
    return strategy.calculate(price);
  }
}

// L - Liskov Substitution Principle (里氏替换原则)
// 子类应该可以替换父类

// I - Interface Segregation Principle (接口隔离原则)
// 不应该强迫依赖不使用的方法

// D - Dependency Inversion Principle (依赖倒置原则)
// 依赖抽象而不是具体实现

// 不好的做法
class UserComponent {
  constructor() {
    this.userService = new UserService();
  }
}

// 好的做法
class UserComponent {
  constructor(userService) {
    this.userService = userService;
  }
}

2. DRY原则

JavaScript
// DRY (Don't Repeat Yourself) - 不要重复自己

// 不好的做法 - 重复代码
function formatDate1(date) {
  return new Date(date).toLocaleDateString();
}

function formatDate2(date) {
  return new Date(date).toLocaleDateString();
}

function formatDate3(date) {
  return new Date(date).toLocaleDateString();
}

// 好的做法 - 提取公共函数
function formatDate(date) {
  return new Date(date).toLocaleDateString();
}

// 不好的做法 - 重复逻辑
function validateEmail1(email) {
  const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
  return regex.test(email);
}

function validateEmail2(email) {
  const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
  return regex.test(email);
}

// 好的做法 - 提取公共逻辑
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

function validateEmail(email) {
  return emailRegex.test(email);
}

3. KISS原则

JavaScript
// KISS (Keep It Simple, Stupid) - 保持简单

// 不好的做法 - 复杂的实现
function calculatePrice(items) {
  let total = 0;
  for (let i = 0; i < items.length; i++) {
    const item = items[i];
    if (item.discount) {
      if (item.discount.type === 'percentage') {
        total += item.price * (1 - item.discount.value / 100);
      } else if (item.discount.type === 'fixed') {
        total += item.price - item.discount.value;
      }
    } else {
      total += item.price;
    }
  }
  return total;
}

// 好的做法 - 简单的实现
function calculatePrice(items) {
  return items.reduce((total, item) => {  // 箭头函数:简洁的函数语法
    const price = item.discount
      ? applyDiscount(item.price, item.discount)
      : item.price;
    return total + price;
  }, 0);
}

function applyDiscount(price, discount) {
  return discount.type === 'percentage'
    ? price * (1 - discount.value / 100)
    : price - discount.value;
}

🔧 技术选型

1. 框架选型

JavaScript
// 框架选型决策树
function selectFramework(requirements) {
  if (requirements.teamExperience === 'react') {
    return 'React';
  } else if (requirements.teamExperience === 'vue') {
    return 'Vue';
  } else if (requirements.projectType === 'enterprise') {
    return 'Angular';
  } else if (requirements.learningCurve === 'low') {
    return 'Vue';
  } else {
    return 'React';
  }
}

// 框架对比
const frameworks = {
  React: {
    learningCurve: 'medium',
    ecosystem: 'excellent',
    performance: 'excellent',
    flexibility: 'excellent',
  },
  Vue: {
    learningCurve: 'low',
    ecosystem: 'good',
    performance: 'excellent',
    flexibility: 'good',
  },
  Angular: {
    learningCurve: 'high',
    ecosystem: 'good',
    performance: 'good',
    flexibility: 'medium',
  },
};

2. 状态管理选型

JavaScript
// 状态管理选型决策树
function selectStateManagement(requirements) {
  if (requirements.complexity === 'simple') {
    return 'Context API';
  } else if (requirements.complexity === 'medium') {
    return 'Zustand';
  } else if (requirements.complexity === 'high') {
    return 'Redux Toolkit';
  } else if (requirements.reactive === true) {
    return 'MobX';
  } else {
    return 'Redux Toolkit';
  }
}

// 状态管理对比
const stateManagement = {
  'Context API': {
    learningCurve: 'low',
    performance: 'medium',
    ecosystem: 'native',
  },
  Zustand: {
    learningCurve: 'low',
    performance: 'excellent',
    ecosystem: 'good',
  },
  'Redux Toolkit': {
    learningCurve: 'medium',
    performance: 'excellent',
    ecosystem: 'excellent',
  },
  MobX: {
    learningCurve: 'medium',
    performance: 'excellent',
    ecosystem: 'good',
  },
};

3. 构建工具选型

JavaScript
// 构建工具选型决策树
function selectBuildTool(requirements) {
  if (requirements.projectType === 'legacy') {
    return 'Webpack';
  } else if (requirements.devExperience === 'fast') {
    return 'Vite';
  } else if (requirements.library === true) {
    return 'Rollup';
  } else {
    return 'Vite';
  }
}

// 构建工具对比
const buildTools = {  // const不可重新赋值;let块级作用域变量
  Webpack: {
    learningCurve: 'high',
    performance: 'good',
    ecosystem: 'excellent',
    flexibility: 'excellent',
  },
  Vite: {
    learningCurve: 'low',
    performance: 'excellent',
    ecosystem: 'good',
    flexibility: 'good',
  },
  Rollup: {
    learningCurve: 'medium',
    performance: 'excellent',
    ecosystem: 'good',
    flexibility: 'good',
  },
};

📝 练习题

1. 基础题

题目1:实现MVC架构

JavaScript
// 实现MVC架构
class Model {
  // 实现Model
}

class View {
  // 实现View
}

class Controller {
  // 实现Controller
}

2. 进阶题

题目2:实现分层架构

JavaScript
// 实现分层架构
class UserRepository {
  // 实现数据访问层
}

class UserService {
  // 实现业务逻辑层
}

function UserList() {
  // 实现表现层
}

3. 面试题

题目3:解释SOLID原则

JavaScript
// 答案要点:
// S - Single Responsibility Principle (单一职责原则)
// - 每个类/函数应该只有一个职责
// - 提高代码的可维护性和可测试性

// O - Open/Closed Principle (开闭原则)
// - 对扩展开放,对修改关闭
// - 使用抽象和多态实现

// L - Liskov Substitution Principle (里氏替换原则)
// - 子类应该可以替换父类
// - 保证继承的正确性

// I - Interface Segregation Principle (接口隔离原则)
// - 不应该强迫依赖不使用的方法
// - 使用小而专一的接口

// D - Dependency Inversion Principle (依赖倒置原则)
// - 依赖抽象而不是具体实现
// - 使用依赖注入

🎯 本章总结

本章节全面介绍了前端架构设计的核心概念和方法,包括架构模式、设计原则、技术选型等。关键要点:

  1. 架构概念:理解前端架构的定义和目标
  2. 架构模式:掌握MVC、MVVM、分层架构、微前端架构
  3. 设计原则:掌握SOLID、DRY、KISS等设计原则
  4. 技术选型:掌握框架、状态管理、构建工具的选型策略
  5. 架构演进:理解前端架构的演进过程
  6. 最佳实践:掌握前端架构设计的最佳实践

下一步将深入学习前端最佳实践。