全栈项目实战:前端独立开发,不再傻等后端接口

前端开发最痛苦的瞬间是什么?不是样式调不出来,不是状态理不清,而是------后端说"接口明天给",然后你傻等了一天又一天。

好不容易等到接口好了,联调又是噩梦:字段对不上、跨域、数据结构变了......可以说,前后端耦合的等待成本,是拖慢项目进度的隐形杀手

今天这篇实战文章,我会以一个经典的 Todo 全栈项目为例,手把手带你搭建一套前端接口工程,让你可以在后端接口就绪前,独立跑通整个应用。读完你会发现:原来前端开发可以这么爽。

一、先看清全栈项目的"前后端分离"到底是什么

很多同学对"前后端分离"的理解就是:你用 React,我用 Koa,咱们各写各的。实际上,分离远不止技术栈,更核心的是职责分离开发流程解耦

在我们的 Todo 项目中:

  • 前端三驾马车:React(组件) + React-Router(路由) + Zustand(状态管理),负责一切用户可见的界面交互。
  • 后端:Node + Koa + MySQL,负责提供 RESTful API,返回 JSON 数据。

两者唯一的交集是什么?接口请求 。你会发现,如果前端直接死等后端提供 /api/todos 才能写渲染逻辑,那等于是把命脉交给了后端。真正的分离,应该让前端拥有独立完成应用的能力

好的架构不是把东西分开写,而是让它们能独立跑起来。

二、前端独立开发的三驾马车:组件、路由、状态

先搭起我们前端项目的骨架。一个标准的 React SPA 离不开这三样:

  • 组件:页面级组件(Pages)和通用组件(Components),UI 的砖瓦。
  • 路由 :React-Router 接管页面级切换,比如 / 到 Home,/todos 到 Todos。
  • 状态管理:Zustand 或 Hooks 管理响应式数据,相当于前端的"小银行"。

看看我们的路由配置(简版):

javascript 复制代码
// App.jsx
import { Routes, Route, BrowserRouter } from 'react-router-dom';
import Nav from './components/Nav';
const Todos = lazy(() => import('./pages/Todos'));
// ...

<Router>
  <Nav />
  <Routes>
    <Route path="/" element={<Home />} />
    <Route path="/todos" element={<Todos />} />
  </Routes>
</Router>

这时候页面已经能切换了,但是 Todos 页面一旦挂载就要展示数据,数据从哪里来?这就是前端工程化里最容易被忽略的一环------接口层

三、打破耦合:前端为什么需要自己的"假后端"

先看一段典型的"傻等后端"的代码:

scss 复制代码
// 在组件里直接 fetch 真实后端
useEffect(() => {
  fetch('http://localhost:3000/api/todos')
    .then(res => res.json())
    .then(setTodos)
}, []);

这样做有两个致命问题:

  1. 后端没开发好,你连页面都无法渲染,完全阻塞。
  2. 即便后端好了,你可能会因为跨域、代理等问题折腾半天。

解决方案就是引入 Mock 机制 ------给前端自己造一个"假后端"。说白了就是:前端自己拦截请求,按约定的接口格式返回模拟数据 。我们这里用到的是 mockjs 库(配合 Vite 插件 vite-plugin-mock)。

这样,前端开发流程就变成了:

  1. 和后端约定好接口文档(URL、Method、响应结构)。
  2. 前端按文档编写 Mock 数据。
  3. 所有组件、状态、交互全部基于 Mock 接口开发,跑通整个 App。
  4. 后端交付后,一键切换真实接口,几乎零成本联调。

不要让接口成为阻塞你开发的理由,先造轮子再换轮子。

四、设计一个专业的前端接口层(api/ 目录)

我们不再在组件里直接写 fetch,而是统一管理所有请求。来看看项目中的 api 目录结构:

arduino 复制代码
src/
  api/
    config.js   // axios 实例,配置 baseURL、拦截器等
    todos.js    // 具体接口模块

1. 封装 axios 实例,关键就在 baseURL

javascript 复制代码
// api/config.js
import axios from 'axios';

const instance = axios.create({
  baseURL: '/api',          // 开发阶段指向 Mock 服务器
  timeout: 5000,
});

export default instance;

baseURL: '/api' 是精髓!因为我们的 Mock 会拦截所有 /api/* 的请求,而真实后端很可能也是 /api 前缀。将来只需把 baseURL 改成 'http://localhost:3000' 就能切换到真实接口,一处修改,全局生效

2. 按业务模块拆接口

javascript 复制代码
// api/todos.js
import axios from './config';

export const getTodos = async () => {
  const res = await axios.get('/todos');   // 最终请求 /api/todos
  return res.data;   // 直接返回业务数据
};

这样组件里调用就非常干净:

ini 复制代码
const data = await getTodos();
setTodos(data.todos);

3. Mock 数据长什么样?

我们用 vite-plugin-mock,在 mock/ 目录下创建文件,它会自动拦截匹配的请求:

yaml 复制代码
// mock/todos.js
export default [
  {
    url: '/api/todos',
    method: 'get',
    timeout: 500,    // 可选模拟网络延迟
    response: () => {
      return {
        code: 0,
        todos: [
          { id: 1, title: '学习前端接口工程', completed: true },
          { id: 2, title: '看龙餐馆', completed: false },
        ]
      };
    }
  }
]

注意字段结构要和你跟后端约定的一致 ,比如我们统一用 code: 0 表示成功,数据放在 todos 里。这样前端解析逻辑就是固定的,未来切后端时完全不用改代码。

五、在 Vite 中集成 Mock 能力

安装依赖:

css 复制代码
npm i mockjs vite-plugin-mock -D

vite.config.js 中引入插件:

javascript 复制代码
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { viteMockServe } from 'vite-plugin-mock';

export default defineConfig({
  plugins: [
    react(),
    viteMockServe({
      mockPath: 'mock',   // mock 文件所在目录
      enable: true,       // 开发环境开启
    }),
  ],
});

重启项目后,访问 http://localhost:5173/api/todos(你前端的端口),你会发现返回的就是 Mock 数据!因为 Vite 服务器已经把请求代理到了 mock 处理逻辑中。

此时,你的前端 App 已经完全脱离后端运行了,而且对真实 API 的调用方式一模一样。

六、实战串联:Todo 页面独立跑起来

我们用 Hooks 状态管理(也可以用 Zustand)简单实现一下:

javascript 复制代码
// pages/Todos.jsx  (注:原笔记文件名有误,应为 Todos.jsx)
import { useState, useEffect } from 'react';
import { getTodos } from '../api/todos';

function Todos() {
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    (async () => {
      const data = await getTodos();
      setTodos(data.todos || []);
    })();
  }, []);

  return (
    <div>
      <h2>Todos</h2>
      <ul>
        {todos.map(todo => (
          <li key={todo.id} style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>
            {todo.title}
          </li>
        ))}
      </ul>
    </div>
  );
}

这时候你打开 /todos 路由,完美展示两条 Mock 数据。整个流程和后端完全解耦。

七、联调切换,只需一行改动

等后端同事终于把接口调通了,你只需要做一件事:

打开 api/config.js,把 baseURL 改为真实后端地址:

arduino 复制代码
baseURL: 'http://localhost:3000',  // 指向真实 Koa 服务

然后确认后端的 /api/todos 返回结构包含 { code: 0, todos: [...] },OK,一切照旧,完美运行。Mock 到真实的切换,做到了零侵入

如果你想更优雅,可以通过环境变量区分:

arduino 复制代码
baseURL: import.meta.env.VITE_API_BASE_URL || '/api',

并在 .env.development.env.production 中设置不同的地址,连手动改代码都省了。

八、总结与思考

通过这次 Todo 全栈实践,我们完成了前端工程化的一个重要拼图------前端接口层。它带来几个显著的收益:

  • ✅ 前后端开发完全并行,不再互相等待。
  • ✅ 前端自闭环,任意页面和交互都可提前验收。
  • ✅ 联调时的切换成本几乎为零,减少扯皮。
  • ✅ 统一的 axios 实例,方便后期加拦截器、错误处理等。

这套模式不仅适用于小型 Todo 项目,在复杂的企业级中台、BFF 层也同样有效。很多大厂的前端团队甚至会在本地 Mock 的基础上加入接口文档自动生成 Mock 数据的能力(如 Apifox、YApi),进一步提高效率。

最后分享一句我一直奉行的开发哲学: "不要让你的代码被任何外部依赖牵着鼻子走,能自己掌控的,就牢牢握在手里。"

希望这篇文章能帮你告别傻等后端的痛苦,下次再遇到"接口还没好"时,你可以淡定地说一句:"没关系,我先把整个 App 跑起来。"

相关推荐
李剑一1 小时前
Anthropic将在AI生成文本中嵌入水印!难道是用我之前写的这个技术?
前端·aigc·ai编程
Asize1 小时前
前端接口工程:axios + mock,前端不再傻等后端
前端·javascript
结网的兔子1 小时前
【前端开发】UniApp 项目地图选型与Web-APP跨端迁移方案
前端·uni-app
张元清1 小时前
React useElementSize Hook:用 ResizeObserver 实时追踪元素宽高 (2026)
javascript·react.js
Canace1 小时前
给 Claude 一个链接,它真的读了原文吗
前端·人工智能·ai编程
爱丶不疚1 小时前
Electron net 模块你可以没用过,但不能不知道
前端·electron
cidy_981 小时前
React + Ant Design 通用企业数据统计模块实战
前端
渣波1 小时前
React 性能优化与状态管理双雄:useMemo 与 useReducer 深度解析
前端·javascript
Maxkim1 小时前
把智能体塞进浏览器侧边栏:我在 MV3 里踩的 5 个坑
前端·后端