前后端分离实战:用 Mock 让前端不再“等“后端

📅 2026/8/13 5:07:05
前后端分离实战:用 Mock 让前端不再“等“后端
文章目录一、前后端职责分离1.1 前端三驾马车React React Router Zustand1.2 后端Node Koa MySQL二、前后端协作2.1 唯一的耦合点API 接口2.2 解耦的关键Mock 数据模拟三、前端接口工程化3.1 为什么需要 api/ 目录3.2 axios 实例化统一配置集中管理3.3 接口模块化一个模块一个文件四、前后端联调4.1 前端独立完成整个 App4.2 路由体系页面路由 vs 接口路由五、MockJS 配置详解5.1 安装与配置5.2 编写 Mock 数据5.3 数据流向全景图六、完整开发流程实战步骤全文总结核心知识点复盘常见问题 / 避坑指南本文以 React Koa 全栈 Todos 项目为实战案例从前后端职责分离讲起深入前端接口工程化与Mock 数据模拟完整呈现一个独立、解耦、可落地的全栈开发工作流。一、前后端职责分离前后端分离不是一句口号而是一套明确的职责划分。在这个 Todos 项目中前端和后端各司其职项目结构如下todos-fullstack/ ├── frontend/todos/ ← React 前端项目独立开发、独立运行 └── backend/ ← Koa 后端项目提供 API 接口1.1 前端三驾马车React React Router Zustand前端项目由三个核心技术组成称为三驾马车技术职责类比React组件化 UI、响应式渲染建筑物的外观和房间React Router页面路由、URL 与组件的映射楼层平面图指引用户走到哪个房间Zustand状态管理跨组件共享数据类似数据中心银行——所有组件从这里取数据、存数据关键理解前端是一个独立的应用。它有自己的路由系统、状态管理系统、组件体系不依赖后端也能完整运行。这就是前后端分离的基础认知——前端不是后端的附属品。1.2 后端Node Koa MySQL后端的职责很纯粹——提供 API 接口返回 JSON 数据。例如GET /api/todos → [{ id: 1, title: 学习React, completed: false }, ...]后端只关心三件事接收请求 → 处理业务逻辑 → 返回数据。它不关心前端用什么技术、怎么渲染、路由怎么跳转。原理理解前后端通过 HTTP 协议 JSON 格式进行通信这是唯一的耦合点。除此之外前后端是完全独立的两个系统。二、前后端协作2.1 唯一的耦合点API 接口前后端分离得彻底吗答案是——API 接口是唯一的耦合点。传统开发流程中前端开发者往往要傻等后端把接口写完才能开始联调数据和渲染页面。这种串行开发模式严重拖慢开发效率❌ 传统模式后端写接口 → 后端完成 → 前端开始 → 联调 ✅ 理想模式前端 后端并行开发 → 前端用 Mock 数据 → 后端完成后一键切换2.2 解耦的关键Mock 数据模拟怎么才能不等后端答案是用 Mock 数据——前端在开发阶段自己模拟后端接口的返回数据先把页面和交互逻辑全部跑通。等后端真正写好 API再把请求切过去只需要改一行配置。前端开发Mock 模拟数据完成页面和交互后端开发真实 API 完成切换 baseURL联调测试核心思想前端不需要等待后端。Mock 让前后端从串行变成并行——这就是前后端分离工程化的真正价值。三、前端接口工程化3.1 为什么需要api/目录很多前端新手会把接口请求直接写在组件里// ❌ 不推荐接口代码散落在组件中functionTodos(){useEffect((){fetch(http://localhost:3000/api/todos).then(resres.json()).then(datasetTodos(data));},[]);}这样做的问题很明显问题后果接口 URL 散落在各处后端地址一换要改 N 个文件没有统一的错误处理每个请求都要重复写 try/catch无法快速切换 Mock/真实接口开发和生产环境切换全靠手动改代码复用性差同一个接口可能在多处被重复定义解决方案就是——前端接口层API 工程。在项目中建立api/目录统一管理所有的 HTTP 请求。3.2 axios 实例化统一配置集中管理项目中使用axios比原生的fetch功能更强、API 更简洁创建统一的请求实例// src/api/config.jsimportaxiosfromaxios;// 创建 axios 实例 —— 所有请求共享同一套配置constinstanceaxios.create({baseURL:/api,// 开发阶段走 Vite 代理或 Mock// baseURL: http://localhost:3000, // 联调阶段只需取消注释这一行timeout:5000,// 超时时间 5 秒});exportdefaultinstance;关键设计baseURL一键切换开发阶段baseURL: /api→ 请求发到http://localhost:5173/api/todos由 Vite 的 Mock 插件拦截联调阶段baseURL: http://localhost:3000→ 请求发到真实后端 Koa 服务器只需要改一行代码整个项目的接口地址全部切换。3.3 接口模块化一个模块一个文件将每个数据实体封装为一个独立的 API 模块// src/api/todos.jsimportaxiosfrom./config;/** * 获取 Todos 列表 * * 注意这里不直接写后端地址而是写相对路径 /todos * 实际请求地址 baseURL /todos * 开发阶段/api /todos /api/todos → Mock 拦截 * 联调阶段http://localhost:3000 /todos http://localhost:3000/todos → 真实后端 */exportconstgetTodosasync(){constresawaitaxios.get(/todos);returnres.data;};页面组件中调用时代码非常简洁// src/pages/Todos.jsximport{getTodos}from../api/todos;import{useEffect,useState}fromreact;exportdefaultfunctionTodos(){const[todos,setTodos]useState([]);useEffect((){// IIFE立即执行函数表达式在 useEffect 中使用 async/await(async(){constdataawaitgetTodos();setTodos(data);})();},[]);return(h2Todos 列表/h2ul{todos.map(todo(li key{todo.id}span{todo.title}/spanspan{todo.completed?✅:❌}/span/li))}/ul/);}代码思路解析useEffect(() {}, [])—— 空依赖数组意味着组件挂载后只执行一次适合做数据初始化IIFE(async () { ... })()——useEffect的回调不能直接是 async 函数所以用 IIFE 包裹异步逻辑组件不关心数据从哪来——它只知道调用getTodos()就能获取数据接口来源对组件透明四、前后端联调4.1 前端独立完成整个 App有了 API 工程和 Mock 机制前端开发者可以做到前端开发周期完全不依赖后端 ├── 第1步搭建项目结构、配置路由 ├── 第2步建立 api/ 目录封装 axios 实例 ├── 第3步配置 Mock 数据模拟后端返回 ├── 第4步开发页面和组件对接 API 模块 └── 第5步后端完成后切换到真实接口 → 联调4.2 路由体系页面路由 vs 接口路由这里有一个容易被混淆的概念——项目中存在两种路由由不同机制处理路由类型示例路径处理方作用页面路由/、/todosReact Router控制浏览器 URL切换页面组件接口路由/api/todosVite Mock 插件 / 后端 Koa返回 JSON 数据// src/App.jsx —— 页面路由React Router 管理import{lazy,Suspense}fromreact;import{Routes,Route,BrowserRouterasRouter}fromreact-router-dom;importNavfrom./components/Nav;constHomelazy(()import(./pages/Home));constTodoslazy(()import(./pages/Todos));exportdefaultfunctionApp(){return(RouterNav/RoutesRoute path/element{Home/}/Route path/todoselement{Todos/}//Routes/Router);}重点区分用户在浏览器输入/todos→ React Router 渲染Todos /组件页面路由组件内部调用getTodos()→ 发送 GET/api/todos→ Mock 或后端返回数据接口路由两者互不干扰各管各的五、MockJS 配置详解5.1 安装与配置项目使用vite-plugin-mock插件来拦截 HTTP 请求并返回模拟数据npminstallvite-plugin-mock然后在 Vite 配置中启用// vite.config.jsimport{defineConfig}fromvite;importreactfromvitejs/plugin-react;import{viteMockServe}fromvite-plugin-mock;exportdefaultdefineConfig({plugins:[react(),viteMockServe({mockPath:mock,// Mock 数据文件的存放目录localEnabled:true,// 开发模式下启用 Mock}),],});5.2 编写 Mock 数据在mock/目录下创建文件导出 Mock 规则对象// mock/todos.jsexportdefault{url:/api/todos,// 拦截的接口路径method:GET,// 拦截的请求方法timeout:2000,// 模拟网络延迟 2000ms方便测试 Loading 状态response:(req,res){// 返回的数据结构与真实后端完全一致return{code:0,// 业务状态码0 成功todos:[{id:1,title:学习 React,completed:false,},{id:2,title:学习 Vue,completed:false,},],};},};Mock 配置四要素字段含义注意点url拦截的接口路径必须和前端请求的路径完全一致method请求方法支持 GET、POST、PUT、DELETE 等timeout模拟响应延迟建议设置方便测试加载态和超时处理response返回的模拟数据结构必须和后端约定好的接口格式一致5.3 数据流向全景图整个请求链路如下┌─────────────────────────────────────────────────────┐ │ React 组件 (Todos.jsx) │ │ 调用 getTodos() │ │ │ │ │ ▼ │ │ api/todos.js: axios.get(/todos) │ │ │ │ │ ▼ │ │ api/config.js: baseURL /api │ │ 实际请求: GET /api/todos │ │ │ │ │ ▼ │ │ ┌─────────────┐ ┌──────────────────┐ │ │ │ Mock 拦截 │ OR │ 真实后端 Koa │ │ │ │ (开发阶段) │ │ (联调/生产阶段) │ │ │ │ 返回 mock │ │ 返回数据库数据 │ │ │ │ /todos.js │ │ │ │ │ └─────────────┘ └──────────────────┘ │ │ │ │ │ ▼ │ │ React 组件拿到数据 → setTodos() → 重新渲染页面 │ └─────────────────────────────────────────────────────┘两种环境的 URL 对比环境请求地址数据来源纯前端开发http://localhost:5173/api/todosMock 插件拦截并返回前后端联调http://localhost:8080/api/todosKoa 后端从 MySQL 查询六、完整开发流程实战步骤理顺整个项目从零到一的搭建流程全文总结本文通过一个完整的 Todos 全栈项目讲解了前端工程化中最重要的一个概念——前端接口层的独立与解耦。核心流程可以浓缩为三句话前后端职责分离前端三驾马车React React Router Zustand构建独立应用后端 Koa 专注提供 API前端接口工程化通过api/目录集中管理 axios 配置实现接口的模块化封装和baseURL一键切换Mock 数据模拟用vite-plugin-mock拦截开发阶段的 HTTP 请求让前端彻底脱离后端独立开发核心知识点复盘序号知识点一句话总结1前后端分离的本质两个独立应用仅通过 HTTP JSON 通信2前端三驾马车路由去哪、组件看什么、状态管理数据在哪3API 工程用api/目录统一管理所有接口一处改、处处生效4axios 实例通过axios.create()集中配置 baseURL、timeout、拦截器等5baseURL 切换开发用/apiMock联调用完整后端地址一行代码完成切换6Mock 机制vite-plugin-mock拦截匹配的请求直接返回模拟 JSON 数据7IIFE 异步模式(async () { ... })()解决 useEffect 不能直接接收 async 函数的问题8两种路由页面路由React Router 管 UI接口路由Mock/后端 管数据9懒加载React.lazy()Suspense实现组件按需加载优化首屏性能常见问题 / 避坑指南Q1: Mock 数据不生效请求还是发到了后端排查步骤确认vite.config.js中localEnabled: true已设置检查mockPath: mock指向的目录是否正确确认 Mock 文件中的url字段和前端请求路径完全一致包括/api前缀重启 Vite 开发服务器Mock 配置修改后需要重启Q2: baseURL 切换后页面报 404/CORS 错误404 错误检查后端路由是否正确注册、后端服务是否启动CORS 跨域错误后端需要配置 CORS 中间件Koa 项目中使用koa/cors// 后端 (Koa) 配置 CORS 示例constcorsrequire(koa/cors);app.use(cors());// 允许所有来源的跨域请求Q3: 为什么不在组件里直接用 fetchfetch是浏览器原生 API功能基础。使用axios的好处拦截器可以在请求/响应阶段统一处理如添加 Token、统一错误提示自动 JSON 转换fetch需要手动res.json()axios自动处理超时配置fetch不支持原生超时axios一行timeout搞定请求取消axios支持CancelTokenfetch需要AbortControllerQ4: Mock 数据和真实接口返回格式不一致怎么办这是联调时最常见的坑。核心原则Mock 数据的结构必须和前后端约定的接口文档保持一致。建议团队在开发前先定好接口规范字段名、数据类型、状态码等Mock 严格遵循这个规范编写。Q5:useEffect里为什么用 IIFE 而不是直接 async// ❌ 错误useEffect 不能直接接收 async 函数useEffect(async(){constdataawaitgetTodos();},[]);// ✅ 正确用 IIFE 包装useEffect((){(async(){constdataawaitgetTodos();})();},[]);原因useEffect的回调函数如果需要清理return 一个函数那它不能返回 Promise。而async函数始终返回 Promise所以 React 不允许。用 IIFE 在内部定义并立即执行 async 函数避免了这个问题。本文项目源码结构复现路径按照第六节完整开发流程的步骤操作即可从零搭建本项目的完整结构。前端独立开发阶段 Mock 先行后端完成后一行配置切换实现真正的前后端并行开发。