文章目录一、什么是 SSR二、Nuxt SSR 流程三、服务端渲染过程1. 路由匹配2. 执行 asyncData3. 渲染组件4. 生成完整页面四、Hydration 是什么Hydration 过程Hydration 不匹配错误五、数据传递机制六、只在客户端执行七、只在服务端执行八、服务端上下文九、SSR 的代价十、调试 SSR总结面试经常被问“说说 SSR 的原理”。很多人只能答出在服务端渲染页面但具体怎么渲染、数据怎么传递、hydration 是什么……一问三不知。今天我们来彻底搞懂 SSR。一、什么是 SSRSSRServer-Side Rendering服务端渲染。简单说页面在服务器生成 HTML浏览器直接显示。对比 CSRClient-Side RenderingCSR 流程 1. 浏览器请求页面 2. 服务器返回空 HTML JS 3. 浏览器下载执行 JS 4. JS 请求数据 5. JS 渲染页面 SSR 流程 1. 浏览器请求页面 2. 服务器执行 JS 获取数据 3. 服务器渲染 HTML 4. 返回完整 HTML 5. 浏览器直接显示SSR 的好处首屏快不需要等 JS 执行SEO 友好爬虫能直接看到内容社交分享能正确抓取 meta 信息二、Nuxt SSR 流程Nuxt 的 SSR 流程更复杂一些┌─────────────┐ │ Browser │ └──────┬──────┘ │ 1. 请求页面 ▼ ┌─────────────┐ │ Nuxt Server │ ── 2. 匹配路由 │ (Nitro) │ ── 3. 执行中间件 └──────┬──────┘ ── 4. 执行 asyncData │ 5. 渲染 Vue 组件 │ 6. 返回 HTML ▼ ┌─────────────┐ │ Browser │ ── 7. 显示 HTML └──────┬──────┘ ── 8. 加载 JS │ 9. Hydration ▼ ┌─────────────┐ │ Interactive │ ── 10. 页面可交互 └─────────────┘三、服务端渲染过程当用户访问/article/123时1. 路由匹配Nuxt 根据请求路径匹配对应的页面组件// 请求 /article/123// 匹配 pages/article/[id].vue2. 执行 asyncData在服务端执行数据获取script setup langts const route useRoute() const { data: article } await useFetch(/api/articles/${route.params.id}) /scriptuseFetch在服务端会真实发起请求获取数据。3. 渲染组件Vue 将组件渲染成 HTML 字符串articleh1文章标题/h1p文章内容.../p/article4. 生成完整页面Nuxt 将组件 HTML 和数据打包成完整页面!DOCTYPEhtmlhtmlheadtitle文章详情/title!-- 样式、脚本 --/headbodydivid__nuxtarticleh1文章标题/h1p文章内容.../p/article/div!-- 关键数据注入 --scriptwindow.__NUXT__{data:{article:{id:123,title:文章标题,...}}}/script/body/html四、Hydration 是什么Hydration水合是 SSR 的关键步骤服务端返回的是静态 HTML没有事件绑定 Hydration 做的是给静态 HTML 注水让它变成可交互的 Vue 应用Hydration 过程浏览器加载 Vue 运行时Vue 根据window.__NUXT__恢复状态Vue 将事件绑定到已有 DOM 上页面变得可交互template !-- 服务端渲染时生成静态 HTML -- button clickcount{{ count }}/button !-- Hydration 后点击事件生效 -- /templateHydration 不匹配错误如果服务端渲染的 HTML 和客户端预期的不一样会报错[Vue warn]: Hydration node mismatch常见原因script setup langts // ❌ 服务端和客户端时间不同 const time new Date().toLocaleString() // ❌ 服务端没有 localStorage const theme localStorage.getItem(theme) // ❌ 随机值每次不同 const random Math.random() /script解决方法script setup langts // ✅ 用 onMounted 处理客户端特有逻辑 const time ref() onMounted(() { time.value new Date().toLocaleString() }) // ✅ 判断环境 const theme ref(light) if (import.meta.client) { theme.value localStorage.getItem(theme) || light } /script五、数据传递机制服务端获取的数据如何传给客户端Nuxt 使用window.__NUXT__对象!-- 服务端注入的数据 --scriptwindow.__NUXT__{serverRendered:true,data:{// useFetch 获取的数据/api/articles/123:{id:123,title:...}},state:{// useState 的状态user:{id:1,name:...}}}/script客户端初始化时直接使用这些数据不再重复请求。六、只在客户端执行有些代码不需要在服务端执行script setup langts // 方式一onMounted onMounted(() { console.log(只在客户端执行) }) // 方式二判断环境 if (import.meta.client) { console.log(只在客户端执行) } // 方式三ClientOnly 组件模板中 /script template ClientOnly div这部分不会在服务端渲染/div /ClientOnly /template七、只在服务端执行有些代码只需要在服务端执行script setup langts if (import.meta.server) { // 访问数据库、读取文件系统等 const event useRequestEvent() const headers getHeaders(event) console.log(请求头:, headers) } /script八、服务端上下文在服务端可以访问请求信息script setup langts if (import.meta.server) { const event useRequestEvent() // 请求 URL const url getRequestURL(event) // 请求头 const headers getHeaders(event) // Cookie const cookies parseCookies(event) // 客户端 IP const ip getRequestIP(event) // 请求方法 const method getMethod(event) } /script九、SSR 的代价SSR 不是银弹有代价优点缺点首屏快服务器压力大SEO 友好开发复杂度高社交分享需要处理 Hydration不能用浏览器特有的 API选择建议内容网站、博客、电商 → SSR后台管理、工具应用 → CSR两者结合 → 部分页面 SSR十、调试 SSR查看服务端渲染结果// 在页面中console.log(服务端渲染:,import.meta.server)console.log(客户端渲染:,import.meta.client)在终端看到的就是服务端输出在浏览器控制台看到的是客户端输出。总结SSR 核心概念概念说明服务端渲染在服务器生成 HTMLHydration给静态 HTML 绑定事件__NUXT__数据传递载体import.meta.server判断服务端环境import.meta.client判断客户端环境理解 SSR 原理才能写出正确的代码避免 Hydration 错误。下一篇聊聊渲染模式选择。相关文章入门篇三Nuxt4组件自动导入写代码少敲一半字入门篇二Nuxt 4路由自动生成告别手动配置路由的日子延伸阅读nuxt4完整系列持续更新中。。欢迎来逛逛内容有帮助点赞、收藏、关注三连评论区等你