Nuxt 客户端导航:解析 ssr false 与服务器请求
2024-12-21 09:45:31
Nuxt 客户端组件导航与服务器请求
使用 Nuxt 构建的应用程序进行客户端组件间导航时,是否会触发对服务器的请求? 这是一个常见问题,也是性能优化的关键。理解 Nuxt 的运行机制可以帮助开发者构建更加高效流畅的Web 应用。
Nuxt 路由与渲染模式
Nuxt 提供了灵活的路由配置,并支持多种渲染模式。针对不同的页面,开发者可配置 routeRules
选项控制其渲染方式,包括:
prerender
: 预渲染。页面在构建阶段生成静态 HTML 文件。ssr
: 服务器端渲染 (Server-Side Rendering)。默认配置下是开启的。请求到达时,服务器端渲染每个页面。ssr: false
: 关闭服务器端渲染,并完全在客户端生成。
根据提供的 routeRules
示例:
export default defineNuxtConfig({
routeRules: {
// Landing page
'/': { prerender: true },
//dashboard
'/app/**': { ssr: false }
}
})
/
首页在构建时预渲染成静态 HTML。/app/**
下的所有页面 (如/app/users
和/app/products
) 都关闭了服务器端渲染,所有页面的渲染任务将会在浏览器端完成。
导航行为分析
对 /app/users
与 /app/products
之间的导航而言,问题的关键点是客户端组件的导航行为,要判断以下两点:
- 在初始页面加载完成后 ,路由间的跳转导航行为 是触发了服务端请求,还是仅仅是在客户端进行。
- 在本地测试和线上环境是否存在不一样的行为。
以下是一个判断方式。
判断条件为页面是否完全通过 script
在客户端上进行渲染:
页面在浏览器第一次访问时,服务器仅仅传输回去了html的基本页面框架,并未提供有用的数据信息。
由于 /app/**
设置了 ssr: false
,这意味着/app/users
与/app/products
,或者/app/**
下的所有页面,在初次访问时仅会发送一个基础的 HTML 文件到浏览器,真正的页面内容构建和逻辑全部交由客户端 JavaScript 完成。
如果存在服务器请求: 这种情况下,浏览器与服务器之间的通信包括:获取组件代码,获取数据进行预渲染或者填充到对应的组件内,如果路由页面所需的所有组件代码都已经在客户端存在 ,那么这种通信只会出现在首次页面加载的时候。但是,如果缺少某些代码或者代码更新时,Nuxt 可能会发送请求到服务器获取资源。 比如Nuxt 使用了组件懒加载的功能时,在切换路由时,就会向服务器发送资源请求。
场景解释
考虑以下几种具体场景:
-
首次访问
/app/users
:浏览器会从服务器获取一个几乎空白的 HTML 文件,然后下载并执行 JavaScript 代码。这段代码将负责获取数据、生成页面内容,并将其渲染到浏览器中。之后客户端与服务端的通讯将通过
fetch
函数等来控制。 -
从
/app/users
导航到/app/products
:如果 Nuxt 应用正确实现了客户端路由,并且
/app/products
的所有组件代码已经存在于浏览器缓存中或已被下载。从用户视角来看,在这种配置下(ssr: false
),从/app/users
导航到/app/products
应该完全在客户端进行,无需向服务器发送任何页面内容相关的请求。这也就保证了流畅的用户体验。
如何确认及调试?
要判断一个页面是在客户端还是服务端生成,可以执行下列的操作步骤进行验证:
步骤一 :查看页面的源码。如果存在服务端渲染或者预渲染时,则查看页面源代码能看到有实际价值的html页面和信息,即除了script脚本外,其它内容基本都可以直接查看源码并访问。反之,如果看到的只有div 元素和大量script
标签以及内容很少时,大概率是一个客户端渲染页面。
步骤二 :使用浏览器控制台来判断是否有额外的服务器请求。打开浏览器的开发者工具(通常是按 F12 键),切换到“网络”(Network) 标签。然后从 /app/users
导航到 /app/products
。
观察网络请求列表,重点关注文档类型以及XHR类型资源的请求情况:
-
仅有一个文档类型的 HTML 文件,其他请求为JS或者JSON 。如果观察到有一个针对于 HTML 文件主页面的文档类型请求,并且其他请求都是 JavaScript 或 JSON 资源的请求,那就很明显这个主页是在客户端进行页面生成操作的。
如果出现两个及以上的 HTML 请求,需要注意以下几点:
-
如果是同一个页面的 HTML,可能是预加载机制引起的,这种情况不需要担心。
-
如果在
/app/users
页面也请求到了app/products
的 HTML 页面资源。 极有可能是应用设置了路由预加载策略 :Prefetch
、Preload
。 当检测到当前页面有跳转至该路由的可能性较大时,便开始下载并缓存后续页面可能会用到的资源,使得下一次路由跳转的时候能够更快速地切换到新的路由页面中去。当然这些资源的加载时通过在<link>
标签上增加rel
属性来实现的,它们不阻塞首屏的加载。 如果出现的是Preload
策略,则意味着可能会有一些潜在的问题。 建议替换为Prefetch
。
-
-
出现 JSON 文件等XHR类型的请求 。如果你的页面还需要通过ajax等方法去向服务端请求数据并构建页面,那么在页面进行跳转时就可能会发出xhr类型的请求。 这个是受程序自身代码所控制,属于正常请求。
开发环境与生产环境
上述的网络分析结论和页面首次请求判断结论在开发环境和生产环境中保持一致。 两种环境的差异更多地体现在资源的构建和优化方面 :
- 开发环境: 使用的是未压缩的代码、热重载机制、提供开发调试工具等等。
- 生产环境: 代码会被压缩、分块。 会启用各种优化措施,比如利用缓存提高用户二次访问时的速度。 代码通过优化,使得部署后应用程序更加高效、加载更快,拥有良好的性能。
通过执行 npm run build
或 yarn build
命令构建的正是可以进行部署到生产环境的版本。在本地机器模拟生产环境的话,在执行完build之后执行npm run preview
来构建本地预览。 再次通过查看页面源码或者查看浏览器控制台的形式可以判断在不同路由之间跳转是否会发送对服务端请求。 值得指出的是,对于 /app/
下的这些页面,即便用户首次访问的是其他页面,一旦其在之后通过浏览器导航到如 /app/users
或 /app/products
这些设置为 ssr: false
的路由时,这种完全在客户端生成页面内容的机制依然保持不变。
生产环境中开启客户端渲染是一个普遍的选择。 通过减少服务端负载与渲染时间,提供更快的响应速度。 特别是在服务器压力较大或者用户遍布在全球各个时区或者全球不同区域的情况下,这个方案能让应用的运行更为稳定。 这对大型Web应用非常有益处。 当然在生产环境时要确保正确处理缓存,安全和错误情况, 以此保证用户能持续不断地使用和访问系统功能。