跪拜 Guibai
← All articles
Frontend · React.js · Vite

A React+Vite Stack That Ships Frontends Before the Backend Exists

By YIAN ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Server-level mock tooling that shows real HTTP traffic in DevTools removes the biggest friction in frontend-backend parallel work. A team can ship a fully interactive UI, validate state management and routing, and merge to real endpoints later by toggling one config boolean — no dead-data cleanup, no last-minute rewiring.

Summary

Frontend teams routinely stall waiting for backend APIs. A standard React 18 + Vite stack eliminates that dependency by combining Axios API layering, server-level mock interception via vite-plugin-mock, and Zustand for global state. The mock plugin operates inside Vite’s Node dev server, so requests appear in the Network tab exactly like real calls — unlike browser-side Mock.js, which hides them.

The workflow is straightforward: wrap Axios with a shared baseURL and timeout, organize API functions by business module, then define mock arrays that match those exact URL paths. Flipping a single `enable` flag in vite.config.js switches the entire app from mock data to live backend endpoints with no code changes.

Routing gets a pragmatic treatment too. HashRouter deploys anywhere without server config and never 404s on refresh; BrowserRouter gives clean URLs but demands Nginx `try_files` or equivalent. Zustand replaces the Context+useReducer combo for global state, subscribing components only to the slices they consume and avoiding the re-render tax of Provider trees.

Takeaways
vite-plugin-mock intercepts requests in Vite’s Node dev server, so the browser Network tab shows complete request-response pairs — unlike Mock.js, which swallows them at the XHR level.
A single `enable: true/false` in vite.config.js switches the entire application between mock and real backends; no business code changes are needed.
Axios instances with a shared `baseURL` and timeout let every API module import the same configured client, keeping endpoint URLs centralized.
Organizing API functions by business domain (e.g., `api/todos.js`) means components import a named function and never touch URLs, headers, or error handling directly.
HashRouter requires zero server configuration and survives page refreshes without 404s, making it the pragmatic choice for static deploys and prototypes.
Zustand stores live outside the React tree, so components subscribe to specific state slices and skip the full-tree re-renders that Context+useReducer triggers.
Async calls inside `useEffect` must be wrapped in an IIFE because the effect cleanup expects a function, not a Promise.
Conclusions

The mock-at-dev-server pattern (vite-plugin-mock) is a distinct upgrade over browser-side interception: it keeps the Network tab honest, which matters more for debugging velocity than most teams admit.

The architecture’s real payoff is the one-config switch from mock to production. That single boolean eliminates an entire class of integration bugs caused by manually replacing stubbed data across components.

Zustand’s selector-based subscriptions solve the Context performance problem without introducing the ceremony of Redux. For global state in React, the Context+useReducer pattern is now a legacy fallback, not a default.

HashRouter remains underrated in professional circles. For any app served from a CDN or static host without server config access, it is the only routing mode that won’t break on refresh.

Concepts & terms
vite-plugin-mock
A Vite plugin that intercepts HTTP requests inside the dev server’s Node process and returns preset JSON. Because interception happens server-side, browser DevTools show real network entries, unlike browser-level mock libraries.
BFF (Backend For Frontend)
A dedicated backend layer that sits between the frontend and downstream services. It can aggregate, transform, or stub data specifically for one frontend client, and typically runs in production — distinct from dev-only mock tools.
Zustand
A lightweight React state management library where stores are plain JavaScript objects outside the component tree. Components subscribe to specific slices via selectors, avoiding the Provider wrapping and full-tree re-renders of Context.
IIFE (Immediately Invoked Function Expression)
A JavaScript pattern — `(async () => { ... })()` — that defines and immediately executes a function. Required inside React’s `useEffect` for async work because the effect must return a cleanup function, not a Promise.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗