正在悄悄复辟?)
过去这十年SPA单页应用几乎成了前端开发的标配。无论业务场景是什么大家上来就是一套React Router或者Vue Router。但随着现代基建的演进这种盲目的架构崇拜正在被残酷的现实狠狠打脸。仿佛只要你还在写传统的HTML多页跳转你就是一个没见过世面的原始人。我们为了追求所谓的丝滑无刷新体验把路由、鉴权、状态管理甚至把整个后端的业务逻辑模型生硬地搬到了脆弱的浏览器内存里。但在 2026 年的今天当你接手了一个运行了三年、塞满了 500 个页面的巨型SPA项目时你会发现这根本不是什么现代化的工程而是一个无法收拾的垃圾场。SPA曾经横扫前端领域, 而被我们鄙视的MPA多页应用正在现代化的云原生基建下开始浮现。SPA 存在什么问题SPA最大的死结在于它极其漫长的内存生命周期。在一个MPA里用户从 A 页面跳到 B 页面浏览器会执行一次Hard Reload。这意味着 A 页面的所有内存泄漏、所有未清理的定时器、所有混乱的全局状态都会在跳转的那一瞬间被垃圾回收机制GC彻底清空。这是一种物理隔离。而SPA呢用户在你的系统里点了一上午的菜单切换了 50 个路由浏览器的内核根本没有刷新过。你在 A 页面给window绑定的滚动事件没有解绑它就会在 B 页面继续疯狂触发你在 C 页面塞进Redux里的几兆脏数据会一路污染到 D 页面。随着用户停留的时间越来越长页面的内存占用会像滚雪球一样飙升直到浏览器悄无声息地白屏崩溃。为了解决这些原本不该存在的问题前端工程师不得不发明出各种花里胡哨的生命周期钩子、路由守卫和状态清理逻辑强行给原本就不堪重负的客户端又套上一层沉重的枷锁。客户端路由和服务端路由为了实现无刷新跳转我们到底付出了多大的代价在传统SPA里一个极其普通的面相用户的页面跳转和鉴权在代码层面往往会膨胀的很快// 为了一个页面跳转在客户端写了无数的防御和拆包逻辑import{lazy,Suspense}fromreact;import{BrowserRouter,Route,Routes,Navigate}fromreact-router-dom;constDashboardlazy(()import(./pages/Dashboard));// 异步分包functionAppRouter(){// 前端被迫在本地存储里读取 TokenconsttokenlocalStorage.getItem(token);return(BrowserRouter{/* 只要是 SPA你就永远逃不掉这恶心的白屏 Loading 圈 */}Suspensefallback{LoadingSpinner/}RoutesRoutepath/dashboardelement{// 客户端路由守卫先加载组件 - 发现没权限 - 再重定向token?Dashboard/:Navigateto/loginreplace/}//Routes/Suspense/BrowserRouter);}这段代码看似标准实际上充满了妥协首屏需要下载庞大的路由解析器鉴权逻辑暴露在极其不安全的客户端而且每次异步加载分包时用户都必须忍受那个该死的Loading圈。而在 2026 年现代MPA如Astro或原生RSC架构的降维打击下这种逻辑直接回归了 HTTP 协议的最底层// 路由和鉴权彻底回归服务端// 零客户端路由代码零状态污染绝对的安全隔离exportasyncfunctionDashboardPage({request}){// 在服务端/边缘节点直接拦截 Cookieconsttokenrequest.headers.get(Cookie)?.match(/token([^;])/)?.[1];if(!isValidToken(token)){// 最纯正、极其快速的原生 HTTP 302 跳转没有任何客户端闪烁returnResponse.redirect(/login,302);}// 服务端直连获取数据constdataawaitfetchDashboardData(token);// 直接吐出渲染好的纯净 HTML// 浏览器接到后直接绘制没有 JS 包裹没有按需加载的 Loading 圈return(htmlbodyDashboardView data{data}//body/html);}发现了吗当路由回归服务端代码量直接少了一半。你不需要再去处理乱七八糟的异步加载不需要在客户端做脆弱的路由守卫。把最重的东西交回给服务器让浏览器只做最纯粹的渲染。为什么服务端渲染 在 2026 年受欢迎有人可能会反驳MPA每次跳转都要白屏体验太差了这句话在 10 年前是对的但在今天就是彻底的刻舟求剑。随着HTTP/3协议的普及多路复用和连接复用已经极其成熟随着Cloudflare等边缘节点把 HTML 吐给客户端的延迟压缩到了 30 毫秒以内随着现代浏览器引入了bfcache往返缓存和原生的预加载规范Speculation Rules API。今天的一个现代化MPA页面点击跳转的速度甚至比你那个还要去请求JSON、再等待React执行Diff算法的SPA还要快。你肉眼根本察觉不到所谓的页面白屏闪烁。于是像Astro这样的孤岛架构框架应运而生。它们打出的旗号就是默认就是多页应用默认 0 KB 的客户端 JavaScript。只有在页面某个具体的组件比如一个点赞按钮需要交互时才局部注入 JS。什么时候用SPA什么时候用 MPA 如果你的业务是类似于Figma的在线设计工具、或者是极度重度交互的在线表格你依然需要SPA来维持复杂内存状态的高频流转。但如果你的业务是电商独立站、内容博客、甚至是很大一部分由图表和表单组成的 B 端后台管理系统你真的需要把整个站点打包成一个几兆大小的 JS 巨兽吗不要去管理状态因为消灭状态才是最好的状态管理。这一点你们怎么看