技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTVUE

Vue 单页面(SPA)和多页面(MPA)的区别

所属馆藏
Vue
文件格式
Markdown
原始路径
Vue/42-vue单页面(SPA)和多页面(MPA)的区别(详细答案)
本文目录13 个章节
  1. 一、什么是 SPA
  2. 二、SPA 的基本原理
  3. 三、SPA 的优点
  4. 四、SPA 的缺点与现代解决方案
  5. 五、什么是 MPA
  6. 六、SPA 与 MPA 对比
  7. 七、SSR、SSG 与混合渲染
  8. 八、History、Hash 与部署
  9. 九、如何选择
  10. 十、SEO 与上线检查清单
  11. 十一、总结
  12. 官方参考
  13. 原文出处

Vue 单页面(SPA)和多页面(MPA)的区别

SPA 和 MPA 描述的主要是页面导航与文档生命周期;CSR、SSR、SSG 描述的是HTML 在什么时候生成。这几个概念经常一起出现,但不能直接画等号。

本文保留原文的入门对比,同时补充 Vue Router 4、Vue SSR、Nuxt 4、History API 和现代 SEO 的说明。

一、什么是 SPA

SPA(Single Page Application,单页面应用)通常指:浏览器第一次打开应用时获得一个应用文档,之后站内导航主要由客户端路由接管,在同一个 Document 内切换视图,而不是每次都进行完整的文档导航。

在 Vue 中,Vue Router 会根据当前 URL 选择组件并更新页面:

用户点击站内链接
      ↓
客户端路由拦截导航
      ↓
更新 URL 和当前路由状态
      ↓
切换 Vue 组件/视图

SPA 常见的体验是首屏加载后,页面之间切换不需要整页刷新。但“SPA 只有一个 HTML 文件”“SPA 只需要一次请求”都只是某些 CSR 部署的简化描述,不是 SPA 的严格定义:

  • 首次访问仍然需要一次文档导航;
  • 还可能加载 JavaScript、CSS、字体、图片、代码分块和接口数据;
  • 路由切换可能加载新的路由 chunk 或请求 API;
  • SPA 也可以使用 SSR/SSG 首次输出 HTML,再在客户端 hydration 后使用 SPA 式导航。

SPA 不等于 CSR

CSR(Client-Side Rendering,客户端渲染)是指主要由浏览器中的 JavaScript 生成页面内容。典型的 Vue SPA 经常采用 CSR,但两者不是同一个维度:

概念关注点
SPA导航是否在同一个文档内由客户端路由更新
MPA不同 URL 是否通常对应不同 HTML 文档
CSRHTML 主要由浏览器 JavaScript 生成
SSRHTML 在请求时由服务端生成
SSGHTML 在构建时预先生成

一个 Nuxt 应用可以首屏 SSR,客户端 hydration 后采用 SPA 式导航;它仍可以拥有 SPA 的导航体验,但不属于“纯 CSR SPA”。

二、SPA 的基本原理

1. Hash 路由

最简单的客户端路由可以监听 URL 片段变化:

window.addEventListener('hashchange', () => {
  console.log(window.location.hash)
})

例如:

https://example.com/#/about
https://example.com/#/products

# 后的片段不会作为 HTTP 请求路径发送给服务器,因此服务器通常只需要返回同一个入口文档。浏览器在片段变化时不会重新加载整个文档,并会触发 hashchange 事件。

这并不是 Vue 特有的能力。hashchange 是浏览器 Window 事件,Vue 可以监听,Vue Router 也提供了更完整的 hash history 实现。

SPA hash 路由示意图(本地化,历史资料)

2. History 路由

History 模式使用 History API 改变正常路径:

import {
  createRouter,
  createWebHistory,
} from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: () => import('./views/Home.vue') },
    { path: '/about', component: () => import('./views/About.vue') },
  ],
})

URL 看起来像普通页面:

https://example.com/about

客户端导航时,Router 使用 pushStatereplaceStatepopstate 管理历史记录。直接刷新 /about 时,浏览器会向服务器请求 /about,所以部署服务器必须将应用路由回退到 index.html,同时不要把真实静态资源和 API 请求无条件改写到入口文件。

Vue Router 4 的模式已经不是 Vue Router 3 的 mode: 'history' 配置,而是:

createWebHistory()
createWebHashHistory()
createMemoryHistory()

3. 原生 History API 的边界

pushState()replaceState() 修改历史记录时不会自动触发 popstate;后退、前进等历史记录遍历才会触发 popstatepushState() 也不会触发 hashchange

如果只是学习原理,可以写一个简单 hash 状态组件:

<script setup lang="ts">
import {
  onMounted,
  onUnmounted,
  ref,
} from 'vue'

const hash = ref('')

function syncHash() {
  hash.value = window.location.hash
}

onMounted(() => {
  syncHash()
  window.addEventListener('hashchange', syncHash)
})

onUnmounted(() => {
  window.removeEventListener('hashchange', syncHash)
})
</script>

<template>
  <p>当前片段:{{ hash }}</p>
</template>

在 Nuxt 或 SSR 环境中,不要在模块顶层直接访问 windowdocument;应放在 onMounted 或客户端专用代码中。实际项目如果已经使用 Vue Router,通常应读取 useRoute(),而不是重复实现一套原生监听器。

原文“Vue 不支持 onhashchange”是错误的。正确说法是:Vue Router 负责封装路由状态,原生 hashchange 仍然属于浏览器 API;使用 Router 时一般不需要自己重复绑定。

三、SPA 的优点

1. 后续导航体验通常较好

首次加载并完成必要的 JavaScript 后,站内导航可以只更新需要变化的视图,而不必重新请求和解析完整 HTML 文档。用户的部分状态也可以继续保留。

但这不是“后续切换完全没有网络请求”:

  • 路由组件可能是懒加载 chunk;
  • 页面数据可能需要重新请求;
  • 图片、字体或第三方资源可能延迟加载;
  • 缓存、Service Worker 和 CDN 可能改变实际网络行为。

2. 交互状态更容易连续保留

例如筛选条件、已打开的弹窗和客户端 Store 可以在视图切换时保留。不过是否保留由应用逻辑决定,路由切换、KeepAlive、Store 和页面卸载都可能改变状态生命周期。

3. 前后端接口边界清晰

前端可以通过 API 获取数据,后端提供认证、数据和业务接口。这个边界适合管理后台、SaaS、在线编辑器等强交互应用,但也需要额外处理鉴权、首屏数据、错误、加载状态和 SEO。

四、SPA 的缺点与现代解决方案

1. 首屏可能较慢

CSR SPA 首次打开通常需要经历:

HTML 文档
  ↓
加载并执行 JS/CSS
  ↓
创建 Vue 应用
  ↓
请求首屏数据
  ↓
生成可交互内容

不能把它固定成“正好两次 HTTP 请求”。一次 HTML 导航会启动资源瀑布,具体请求数量取决于打包、预加载、缓存、API 和部署方式。

可采用:

  • 路由级代码分割;
  • import() 异步加载非首屏模块;
  • 预加载关键 chunk;
  • 图片和字体优化;
  • SSR/SSG/prerender;
  • 合理的首屏数据获取策略;
  • 避免把所有代码都打进首屏入口。

2. SEO 需要额外设计

“搜索引擎完全不认识 JavaScript”已经不是准确的现代表述。Google Search 会经历 crawl、render、index 阶段,并且能够执行 JavaScript,但渲染可能有延迟,也不能代表所有搜索引擎、社交爬虫和站内抓取器。

公开且重要的内容更稳妥的方案是:

  • 使用 SSR、SSG 或 prerender,让正文出现在初始 HTML;
  • 每个内容页面使用稳定、可访问的 URL;
  • 输出唯一的 title、description、canonical 和结构化数据;
  • 使用正常的 <a href> / <NuxtLink> 让爬虫发现页面;
  • 不要把正文完全隐藏在点击、权限或客户端状态之后;
  • 处理真实 404,避免所有未知 URL 都返回应用首页造成 soft 404。

SSR/SSG 能改善首屏 HTML 和抓取可见性,但不是排名保证,也不是自动解决所有性能和 SEO 问题。SSR 还会带来服务端成本、hydration、一致性和浏览器 API 隔离等要求。

五、什么是 MPA

MPA(Multi-Page Application,多页面应用)通常指不同页面 URL 对应不同的 HTML 文档。用户从 /home 导航到 /products 时,浏览器通常执行一次新的文档导航,服务器或静态主机返回另一份页面文档。

MPA 不代表每次导航只有一个 HTTP 请求。HTML 返回后仍可能触发:

  • CSS、JavaScript、字体和图片请求;
  • 接口或服务端数据请求;
  • 第三方脚本请求;
  • 重定向、缓存验证和 CDN 请求。

MPA 也不代表页面完全没有客户端渲染。每个页面可以使用 Vue 做局部增强,也可以使用 CSR 组件、局部 hydration 或前端交互。

原文的第二张配图把 MPA 误写成了 “MAP”,且图片属于历史抓取内容,因此不直接嵌入本文;正文以 MPA(Multi-Page Application)为准。

MPA 的优点

  • 每个页面通常都有独立的 HTML、URL、标题和状态码;
  • SSR 或 SSG 内容天然容易被不执行 JavaScript 的爬虫读取;
  • 单个页面的 JavaScript 体积可能较小;
  • 页面之间相互隔离,适合内容站、营销页、传统电商和多团队独立维护;
  • 可以使用成熟的服务端路由、缓存和权限控制。

“MPA 首屏只需要一个 HTTP 请求所以一定更快”并不准确。服务端处理时间、数据库查询、HTML 大小、资源数量和缓存命中都会影响性能。

MPA 的缺点

  • 跨页面导航通常会替换整个文档;
  • 页面级状态需要重新初始化或额外持久化;
  • 过多的全量导航可能造成明显的页面闪烁;
  • 多个页面可能重复加载公共资源;
  • 如果每个页面都重复集成脚本和数据逻辑,维护成本会增加。

现代构建工具可以共享公共 chunk、使用预加载和缓存,因此“MPA 每个页面一定重复加载全部 JS/CSS”也是过度绝对化的说法。

六、SPA 与 MPA 对比

原文的第三张对比图包含“MPA 不共用资源”“每页都要重新加载全部资源”“MPA 无法实现转场动画”等过时的绝对表述,已不直接嵌入;现代缓存、公共 chunk 和渐进增强请以本文对比表为准。

对比项SPAMPA
文档导航首次访问是真实文档导航,之后通常由客户端路由软导航不同页面通常进行新的文档导航
页面更新在同一文档内更新组件/视图获取并替换新的 HTML 文档
首屏方式可以 CSR,也可以 SSR/SSG 后 hydration可以 SSR、SSG,也可以包含 CSR 局部组件
请求数量首次需要 HTML、资源和可能的 API;软导航仍可能请求 chunk/API每次文档导航会获取 HTML,并可能触发多个子资源请求
状态客户端状态较容易跨视图保留页面切换时通常重新初始化
SEOCSR 需要额外处理;SSR/SSG 更容易提供初始 HTML独立 HTML 页面通常更直接,但仍需正确 metadata/状态码
部署History 模式需要 fallback;Hash 模式部署简单但 SEO 较弱服务端/静态主机按页面路径提供对应文档
典型场景后台、SaaS、在线编辑器、复杂交互应用博客、文档、营销页、内容站、传统电商

关键结论: SSG 生成多个 HTML 文件并不自动等于 MPA;如果 hydration 后使用客户端路由,仍然可以拥有 SPA 式导航。反过来,MPA 也可以在每个页面内使用 Vue 和客户端渲染。

七、SSR、SSG 与混合渲染

1. SSR

Vue SSR 会在服务端生成 HTML,浏览器收到 HTML 后再进行 hydration,重新绑定事件并变成可交互的 Vue 应用:

请求页面
  ↓
服务端执行组件并生成 HTML
  ↓
浏览器先显示 HTML
  ↓
下载 JS 并 hydration
  ↓
页面获得交互能力

SSR 可以改善首屏内容可见性和抓取稳定性,但要注意:

  • 服务端不能直接使用 windowdocument 等浏览器 API;
  • 服务端和客户端的初始渲染结果应保持一致;
  • hydration mismatch 会导致警告或额外修复;
  • 每次请求都可能产生服务端计算和数据访问成本;
  • 缓存策略、流式渲染和错误页面需要单独设计。

参考:Vue SSR

2. SSG / prerender

SSG 在构建阶段生成 HTML,部署时由 CDN 或静态主机直接提供。适合文章、文档、营销页等变化频率较低的内容。

SSG 也不决定导航形式:

  • 生成多个页面并使用普通链接,可呈现 MPA 导航;
  • 生成多个页面并在 hydration 后使用客户端 Router,也可呈现 SPA 式导航;
  • 动态路由需要确保在构建阶段被发现或显式加入 prerender 配置。

3. Nuxt 4 的情况

Nuxt 4 默认采用 universal rendering:首个请求通常由服务端渲染,客户端 hydration 后,后续页面导航使用客户端路由。也可以根据路由选择:

  • ssr: false:纯客户端渲染,适合部分后台或 SaaS 场景;
  • prerender:构建时生成静态页面;
  • SSR:请求时生成 HTML;
  • route rules:对不同路由混合使用 prerender、SSR、SWR/ISR 和客户端渲染。

因此,现代 Vue/Nuxt 项目往往不是简单二选一,而是按页面目标混合选择。

八、History、Hash 与部署

History 模式

Vue Router 4:

import {
  createRouter,
  createWebHistory,
} from 'vue-router'

export const router = createRouter({
  history: createWebHistory(),
  routes,
})

静态主机通常需要类似以下回退逻辑:

如果请求的是已有文件或真实 API:正常返回
否则把前端路由请求回退到 index.html

以 Nginx 为例,常见思路是:

location / {
  try_files $uri $uri/ /index.html;
}

实际配置还要排除 API、静态资源,并处理真实的 404。不能把所有未知路径都无条件返回 200,否则可能形成 soft 404。

Hash 模式

import { createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),
  routes,
})

Hash 后的内容不发送到服务器,所以不需要配置 History fallback,适合无法控制服务器重写规则的场景。但 /#/products 不如正常路径适合公开内容的 SEO,公开站点通常优先考虑 History + SSR/SSG/prerender。

九、如何选择

适合 SPA 或 SPA 式导航的场景

  • 管理后台;
  • SaaS 和工作台;
  • 在线编辑器、绘图和协作工具;
  • 需要大量局部状态和复杂交互的应用;
  • 登录后使用、无需公开搜索的业务系统。

适合 MPA、SSR 或 SSG 的场景

  • 博客、技术文档和新闻站;
  • 营销落地页;
  • 商品详情和公开内容页;
  • 需要稳定初始 HTML、状态码和社交分享预览的页面;
  • 多个独立团队维护的页面集合。

混合方案

一个真实项目可以同时包含:

  • 首页和文章页使用 SSG/SSR;
  • 登录后的控制台使用客户端渲染;
  • 商品列表使用 SSR,筛选结果通过客户端请求更新;
  • 某些路由使用 History,特殊嵌入页面使用独立文档。

不要先争论“SPA 还是 MPA 一定更好”,应先看页面的首屏、SEO、交互、数据新鲜度、部署能力和团队维护成本。

十、SEO 与上线检查清单

  • 每个需要索引的页面都有稳定 URL;
  • 页面有唯一 title、description 和 canonical;
  • 重要正文在初始 HTML 或稳定的 SSR/SSG 结果中可见;
  • 使用可发现的 <a href> / <NuxtLink>,不要只依赖点击事件;
  • 不要阻断必要的 JavaScript、CSS 和数据资源;
  • 直接打开和刷新深层 URL 不应 404;
  • 真正不存在的页面返回真实 404,不要全部重定向到首页;
  • 客户端导航后同步更新标题和结构化信息;
  • 检查 hydration mismatch、JS 错误和 API 超时;
  • 使用浏览器禁用 JS、冷缓存、移动网络和真实深层 URL 测试;
  • 使用搜索引擎提供的 URL Inspection 或渲染工具查看最终 DOM。

十一、总结

  • SPA 关注同一文档内的客户端导航,MPA 关注不同 URL 对应不同文档;
  • SPA 不等于 CSR,MPA 也不等于完全没有客户端渲染;
  • SPA 首屏不一定只有两次请求,MPA 导航也不一定只有一次 HTTP 请求;
  • 搜索引擎可以执行部分 JavaScript,但公开内容仍建议使用 SSR、SSG 或 prerender 提供稳定 HTML;
  • Vue Router 4 使用 createWebHistorycreateWebHashHistory 等 API,History 模式需要服务器 fallback;
  • hashchange 是浏览器原生事件,Vue 和 Vue Router 都可以使用它;
  • Vue/Nuxt 4 支持按路由混合 SSR、SSG、CSR 和客户端导航,不必把项目限制在单一模式中。

官方参考

原文出处

作者:佑子呀

来源:稀土掘金

本文保留原文 SPA/MPA 对比和路由原理,并补充 CSR、SSR、SSG、Vue Router 4、Nuxt 4 与 SEO 的现代说明。

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS