路由进化史:从后端独舞到前后端共舞

92 阅读7分钟

路由进化史:从后端独舞到前后端共舞

在Web开发的舞台上,路由就像一个指挥家,引导着用户和数据的流动。今天,让我们一起穿越时空,探索路由从后端独舞到前后端共舞的奇妙进化之旅!

一、远古时代:只有后端路由的日子

在Web开发的早期,后端路由是绝对的统治者。那时的开发模式被称为MVC(Model-View-Controller),让我们拆解这个经典模式:

  • 🧠 Model(模型):数据的守护者,负责与数据库交互
  • 🎨 View(视图):展示数据的艺术家,生成HTML页面
  • 🕹️ Controller(控制器):指挥中心,接收请求并协调Model和View

MVC的工作流程

  1. 用户在视图(View)上进行操作(如点击按钮、输入内容等),触发视图的相关事件;

  2. 视图感知到事件后,将用户的操作信息传递给控制器(Controller);

  3. 控制器接收请求后,根据业务逻辑调用模型(Model)的方法,对数据进行处理或更新(如修改数据库记录、计算数值等);

  4. 模型完成数据操作后,将数据变化的结果反馈给控制器,或直接通知视图数据已更新;

  5. 视图获取到更新后的数据,重新渲染界面,将最新状态展示给用户。。 image.png

// 典型的Node.js后端路由示例
const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer((req, res) => {
  // 处理首页请求
  if (req.method === 'GET' && (req.url === '/' || req.url === '/index.html')) {
    fs.readFile(path.join(__dirname, 'public', 'index.html'), (err, content) => {
      if (err) {
        res.writeHead(500);
        res.end('Server Error');
        return;
      }
      res.writeHead(200, { 'Content-Type': 'text/html' });
      res.end(content);
    });
  }
  // 处理CSS请求
  else if (req.method === 'GET' && req.url === '/style.css') {
    // ...类似读取CSS文件
  }
  // 处理登录请求
  else if (req.method === 'POST' && req.url === '/login') {
    // 验证用户名密码...
    res.writeHead(200, {
      'Set-Cookie': 'username=admin;',
      'Content-Type': 'application/json'
    });
    res.end(JSON.stringify({ success: true, msg: "登录成功" }));
  }
});

server.listen(8080);

在这个时代,每次页面跳转都需要向服务器发送请求,服务器返回完整的HTML页面。这种模式简单直接,但也存在明显缺点:

Suggestion.gif

  1. 前后端高度耦合:后端程序员既要写业务逻辑,又要操心页面渲染
  2. 用户体验割裂:每次跳转都是全页面刷新,等待时间长
  3. 开发效率低下:前后端开发进度互相依赖,沟通成本高

二、文艺复兴:前后端分离时代到来

随着AJAX技术的成熟和前端框架的兴起,我们迎来了前后端分离的新纪元。这种模式下,后端只提供API接口,前端负责所有展示和交互逻辑。

MVVM模式:前端的华丽蜕变

在前端框架(特别是React)中,MVVM模式成为主流:

  • 📦 Model:数据层,通过fetchaxios获取
  • 🖼️ View:视图层,在React中体现为JSX
  • 🧩 ViewModel:视图模型层,如useStateuseEffect等Hook

工作流程

  1. 用户与视图(View)交互(如输入内容、点击操作等),视图会将用户行为绑定到 ViewModel 中的对应命令或属性;
  2. ViewModel 接收并处理这些交互逻辑,根据业务需求调用数据模型(Model)的接口,对数据进行查询、修改等操作;
  3. Model 完成数据处理后,将更新后的数据反馈给 ViewModel;
  4. ViewModel 中的数据发生变化时,由于视图与 ViewModel 存在双向数据绑定,变化会自动同步到 View;
  5. View 根据同步过来的最新数据,自动更新界面展示,无需手动操作。 image.png
// React中的MVVM模式示例
import { useState, useEffect } from 'react';

function UserProfile() {
  // ViewModel:状态管理
  const [user, setUser] = useState(null);
  
  // Model:数据获取
  useEffect(() => {
    fetch('/api/user/123')
      .then(response => response.json())
      .then(data => setUser(data));
  }, []);
  
  // View:UI渲染
  return (
    <div>
      {user ? (
        <h1>你好,{user.name}!</h1>
      ) : (
        <p>加载中...</p>
      )}
    </div>
  );
}

前端路由的崛起:react-router-dom登场

在前后端分离的架构下,前端路由应运而生。React生态中,react-router-dom成为路由管理的事实标准:

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        {/* 动态路由 */}
        <Route path="/user/:id" element={<UserProfile />} />
        {/* 嵌套路由 */}
        <Route path="/products" element={<Products />}>
          <Route path=":productId" element={<ProductDetails />} />
          <Route path="new" element={<NewProduct />} />
        </Route>
      </Routes>
    </Router>
  );
}

image.png

页面级别的组件

在 React 中,页面级别组件(Page-level Components)(放在pages目录下,一个页面,一个文件夹)是与路由直接绑定、负责渲染完整页面的顶层组件。它们通常:

  1. 关联路由:对应特定 URL 路径,如/home对应Home组件。
  2. 获取数据:负责从 API 等数据源获取页面所需数据。
  3. 管理布局:决定页面整体结构,包含页眉、页脚等通用组件。
  4. 处理状态:管理页面级状态(如加载状态、表单数据)。

在项目目录中,典型的页面级别组件有:

  • Home/index.jsx:应用首页,展示核心内容。
  • Products/index.jsx:产品列表页,处理筛选、分页。
  • ProductDetails.jsx:产品详情页,展示特定产品信息。
  • UserProfile/index.jsx:用户个人资料页,管理用户信息。

它们通过 props 向子组件传递数据,并处理子组件的回调事件,是构建 React 应用的核心骨架。

前端路由带来了革命性的变化:

  • 🌟 无缝导航:页面切换无需刷新
  • 极致体验:局部更新,响应迅速
  • 🧩 组件化开发:每个路由对应一个组件

前后端分离总架构图

image.png

三、API设计的艺术:RESTful规范

在前后端分离的架构中,后端API的设计至关重要。RESTful成为广泛采用的API设计规范:

动态路由

url:juejin.cn/users/123?a…

协议(https://),域名(juejin.cn),端口(80省略),路径(/users),params(id 123),queryString(查询参数),hash

HTTP方法URL动作
GET/posts获取文章列表
POST/posts创建新文章
GET/posts/:id获取单篇文章
PUT/posts/:id更新整篇文章
PATCH/posts/:id更新文章部分内容
DELETE/posts/:id删除文章

PUT vs PATCH:局部更新的艺术

put在更换头像之类的需要将整个资源全部换掉时使用

// PUT请求 - 替换整个资源
fetch('/user/123', {
  method: 'PUT',
  body: JSON.stringify({
    name: '张三',
    age: 30,
    avatar: 'new-avatar.jpg'
  })
})

// PATCH请求 - 只更新部分字段
fetch('/user/123', {
  method: 'PATCH',
  body: JSON.stringify({
    avatar: 'updated-avatar.jpg'
  })
})

设计原则

  • 资源导向:URL代表资源(名词),而非动作
  • HTTP方法明确操作类型
  • 状态码准确反映操作结果

四、React的哲学:为什么路由需要独立库?

React的核心团队有一个重要理念:"做一件事并把它做好"。这就是为什么路由功能没有内置在React核心中:

1. 保持核心精简

graph LR
A[React核心] --> B[组件系统]
A --> C[状态管理]
A --> D[生命周期]
A -- 不包含 --> E[路由功能]

React核心只关注UI构建的基本能力,体积小巧(仅约6KB gzip后),让开发者可以按需选择路由方案。

2. 灵活性和可扩展性

react-router-dom提供丰富的路由功能:

  • 动态路由匹配
  • 嵌套路由
  • 路由守卫
  • 代码分割
  • 历史记录管理

3. 版本策略:稳定与创新的平衡

react-router-dom采用语义化版本控制:

  • 主版本(如v6):重大变更,可能不向后兼容
  • 次版本(如v6.4):新增功能,向下兼容
  • 修订版本(如v6.4.1):Bug修复和安全补丁

五、现代路由实战:前后端协作的完美舞步

前端路由:声明式导航

// 动态路由参数获取
import { useParams } from 'react-router-dom';

function UserProfile() {
  const { id } = useParams();
  
  useEffect(() => {
    fetch(`/api/user/${id}`)
      .then(/* ... */)
  }, [id]);
  
  return <div>用户ID: {id}</div>;
}

后端路由:RESTful API设计

// Express.js中的RESTful路由
const express = require('express');
const app = express();

app.get('/api/user/:id', (req, res) => {
  const userId = req.params.id;
  // 从数据库获取用户数据
  const user = db.getUser(userId);
  res.json(user);
});

app.post('/api/user', (req, res) => {
  const newUser = req.body;
  // 创建新用户
  const createdUser = db.createUser(newUser);
  res.status(201).json(createdUser);
});

前后端协作流程

sequenceDiagram
    participant 用户
    participant 前端 as 前端(React)
    participant 路由 as 前端路由(react-router-dom)
    participant 后端 as 后端API
    
    用户->>前端: 访问 /user/123
    前端->>路由: 匹配路由
    路由->>前端: 渲染<UserProfile>
    前端->>后端: GET /api/user/123
    后端->>前端: JSON数据
    前端->>用户: 展示用户信息

六、未来展望:路由的进化永不止步

路由技术仍在不断进化:

  • 智能路由:基于用户行为的预测性路由
  • 微前端路由:跨应用的无缝导航
  • 服务端组件:React Server Components带来的新路由模式
  • 边缘计算路由:CDN边缘节点的路由处理

结语:路由的进化,开发的革命

从后端路由的MVC时代,到前后端分离的MVVM模式,路由的进化映射了Web开发的整个发展历程:

  1. 职责分离:前后端各司其职,专业分工
  2. 体验升级:无缝导航带来流畅用户体验
  3. 开发效率:组件化开发加速产品迭代
  4. 标准化:RESTful规范统一API设计语言

路由的进化就像一场精心编排的舞蹈——从后端的独舞,到前后端的完美双人舞。在这个不断变化的舞台上,React和react-router-dom这对搭档,正在为我们演绎着Web开发的未来之舞。

路由的旅程永无止境,而我们的探索也刚刚开始... 🚀