Vue3四种渲染模式全面解读:CSR、SSR、SSG与预渲染选择指南
客户端渲染首屏需下载JS,SEO差。预渲染在构建阶段生成静态HTML,适合路由少的固定内容站点。静态站点生成全站构建为静态文件,首屏极快但构建时间长。服务端渲染动态生成HTML,SEO完美且支持实时数据,但服务器压力大且工程复杂。
客户端渲染(CSR)详解
使用 npm create vue@latest 或 npm create vite@latest 创建一个 Vue3 项目时,默认获得的便是典型的客户端渲染模式。在此模式下,服务器返回的 HTML 文件内容极为精简,核心结构仅为一个 与多个 标签。浏览器需要先完整下载所有 JavaScript 文件,再解析并执行代码,之后 Vue 才会在浏览器中动态构建 DOM 树,最终将页面内容呈现出来。

这种方案的优势较为显著:前后端实现完全解耦,开发体验直观流畅,页面切换无需刷新,交互感受接近原生应用;同时服务器负载极低,仅需托管静态文件即可。
然而其代价同样不容忽视。首屏加载时间成为明显短板——用户必须等待 JS 下载、解析并执行完毕才能看到页面内容;搜索引擎爬虫通常不会执行 JavaScript,导致 SEO 表现很不理想;此外还需额外处理 meta 标签(标题、描述等),增加了工作量。
预渲染技术实现方案
预渲染的核心思路是在构建阶段发力。它会启动一个无头浏览器(如 Puppeteer),依次访问指定的路由,让 Vue 代码真实运行一次,然后将渲染完成的完整 HTML 直接保存为静态文件。当用户请求这些路由时,服务器直接返回这份现成的 HTML,客户端无需再次执行 Vue 逻辑。
这种方式保留了客户端渲染的开发体验,同时有效解决了首屏白屏问题,并改善了 SEO 表现。部署也十分便捷,交给 Nginx 或 CDN 即可。对于页面数量不多、内容相对固定的站点而言,这是一个非常合适的选择。
但缺点也相当明确:如果路由数量达到成百上千,构建时间会呈指数级增长,带来巨大困扰。另外 HTML 在构建时已经固化,无法处理动态数据——例如用户评论、实时价格等场景,显得力不从心。更麻烦的是参数化路由,比如 /user/:id 这种形式,必须在构建时穷举所有可能的 ID,这在很多实际场景中几乎无法实现。
实践示例
常用的插件为 @seresweb/vite-plugin-seo-prerender。
vue3-mananger-prerender/vite.config.ts
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
// import VueDevTools from 'vite-plugin-vue-devtools'
import seoPrerender from "@seresweb/vite-plugin-seo-prerender";
// import { createMpaPlugin } from "vite-plugin-virtual-mpa";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
// @ts-ignore
import prerenderFallback from "./plugin/vite-plugin-prerender-fallback.js";// 预渲染路由列表(从 router 中提取需要预渲染的静态路由)
// const prerenderRoutes = ["/", "/home", "/dashboard", "/about", "/404"];
//
export default defineConfig(({ command }) => {
// const isBuild = command === "build"; return {
plugins: [
vue(),
vueJsx(),
AutoImport({
resolvers: [ElementPlusResolver()],
// 推荐:生成类型声明文件,提升 TypeScript 支持
dts: "src/auto-imports.d.ts",
}),
Components({
resolvers: [ElementPlusResolver()],
// 推荐:生成组件类型声明文件,提升 TypeScript 支持
dts: "src/components.d.ts",
}),
// VueDevTools(), prerenderFallback({
distDir: "dist", // 可选,默认就是 'dist'
}),
seoPrerender({
routes: ["/yoy/dashboard"],
headless: "new",
executablePath: undefined,
}),
],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
build: {
outDir: "dist",
target: "es2015",
minify: true,
},
};
});
此外还需要一个自定义插件来处理 fallback 逻辑:当导航栏路径变化时,先尝试请求对应目录下的 index.html 文件,若找不到则走默认回退。
vue3-mananger-prerender/plugin/vite-plugin-prerender-fallback.js
// vite-plugin-prerender-fallback.js
import fs from 'node:fs';
import path from 'node:path';/**
* Vite 插件:为预览服务器添加预渲染目录回退 + SPA fallback
* @param {Object} options
* @param {string} options.distDir - 构建输出目录,默认 'dist'
*/
export default function prerenderFallback(options = {}) {
const { distDir = 'dist' } = options;
const distPath = path.resolve(process.cwd(), distDir); return {
name: 'vite-plugin-prerender-fallback',
apply: 'serve', // 仅在预览/开发服务器时生效(预览模式也是 serve)
configurePreviewServer(server) {
server.middlewares.use((req, res, next) => {
// 1. 跳过根路径、带扩展名的文件请求、API 等
const url = req.url;
if (
url === '/' ||
path.extname(url) !== '' ||
url.startsWith('/@') ||
url.startsWith('/node_modules/')
) {
return next();
}
// 2. 构造预渲染 HTML 的完整路径:dist + url + /index.html
const htmlPath = path.join(distPath, url, 'index.html');
// 3. 同步检查文件是否存在
if (fs.existsSync(htmlPath)) {
// 存在预渲染文件,修改请求路径指向该文件
req.url = path.posix.join(url, 'index.html');
return next();
}
// 4. 不存在预渲染文件,最终会 fallback 到根 index.html
return next();
});
},
};
}
以上只是一个测试 demo,实际项目需要根据需求做更精细的调整。
静态站点生成(SSG)全面解析
SSG 本质上可视为预渲染的全面升级版。它不再局限于少数路由,而是在构建阶段将整个站点完整转换为静态 HTML。它支持动态路由(通过 getStaticPaths 枚举所有可能的参数),还能在构建时从 API 或本地文件拉取数据(getStaticProps)。生成的每个页面都是完全独立的、包含全部内容的静态 HTML 文件。
毫无疑问,首屏速度达到极致,搜索引擎优化效果完美——爬虫直接获取完整内容,无需任何执行。同时开发体验仍是熟悉的 Vue 组件模式,部署成本低,CDN 即可轻松搞定。
但代价体现在构建时间上:页面数量越多,构建时间越长,百万级的大型站点几乎难以承受。另外每次内容更新都需要全站重新构建,灵活性不足。如果需要处理用户个性化内容(如登录状态、推荐列表),它也无法直接实现,必须配合客户端的 JavaScript 二次请求数据才行。
服务端渲染(SSR)深度介绍
SSR 的逻辑是:当用户请求页面时,服务器动态运行 Vue 组件,在服务端生成完整的 HTML 字符串,并直接返回给浏览器。客户端拿到这份 HTML 后可以立即展示内容,随后通过“激活”(Hydration)让 Vue 组件恢复交互能力。由于每次请求都重新渲染,展示的数据始终保持最新状态。
SSR 带来的好处非常扎实:搜索引擎完美收录——任何爬虫看到的都是完整内容;首屏速度快,用户无需等待 JS 执行即可看到页面内容;同时天然支持实时数据——用户登录态、实时评论、个性化推荐等场景都能直接满足。
但其代价也相当显著。服务器压力实实在在——每次请求都需要消耗 CPU 去渲染组件。工程复杂度也大幅提升:需要处理 Node.js 运行环境问题、内存泄漏、缓存策略,还要时刻防范客户端与服务端状态不一致。首字节时间(TTFB)也会比直接返回静态文件高出一截。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
如何用拖放在Flask看板应用中更新数据库状态
在Flask看板应用中,通过HTML5拖放API结合前端fetch异步POST请求,将拖拽任务的task_id和target_state发送至后端路由;后端接收JSON后更新数据库并提交事务,实现跨列拖拽时实时更新状态。需注意将事件绑定到容器而非子元素,并在ondragover中阻止默认行为以确保drop触发。
如何用CSS :has()选择器快速实现悬停span显示相邻div
利用CSS的:has()伪类选择器,通过` bar:has(> baz:hover)+ qux`实现悬停内联元素时显示相邻块级容器,解决了传统相邻兄弟选择器无法跨层级匹配的局限,可用于悬停图标显示详情框等交互场景。需注意浏览器兼容性和性能优化,避免过度使用影响渲染效率。
display:block居中段落文本的响应式实现方法
通过`display:block`与`max-width`限制宽度,配合`margin:auto`使段落块水平居中并实现响应式布局;同时用CSS统一控制段落间距,避免脱离文档流,提升可读性与维护性。
JavaScript代码去重:高效避免重复编写的技巧
将重复代码中的变化点提取为参数,利用ES6模板字符串动态生成选择器,可消除重复、保持一致性。注意参数安全性,必要时进行白名单校验;批量化场景可扩展为数组形式;现代框架中更推荐数据驱动或组件化封装替代手动选择器。
使用容器查询单位cqw实现表单输入框相对于祖父容器百分比宽度
利用CSS容器查询单位cqw,表单输入框宽度可直接基于祖父容器计算,绕过中间包装器尺寸干扰,实现简洁响应式布局,无需硬编码或JavaScript,显著降低维护成本,提升嵌套结构下的布局灵活性。
- 热门数据榜
相关攻略
2026-07-09 07:01
2026-07-09 07:01
2026-07-09 07:01
2026-07-09 07:00
2026-07-09 07:00
2026-07-09 07:00
2026-07-09 07:00
2026-07-09 07:00
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

