渲染模式
Nuxt 支持不同的渲染模式,包括通用渲染、客户端渲染,还提供了混合渲染以及在CDN 边缘服务器上渲染应用程序的可能性。
浏览器和服务器都可以解释 JavaScript 代码,将 Vue.js 组件转换为 HTML 元素。此步骤称为**渲染**。Nuxt 支持**通用**和**客户端**渲染。这两种方法都有优点和缺点,我们将对此进行介绍。
默认情况下,Nuxt 使用**通用渲染**来提供更好的用户体验、性能并优化搜索引擎索引,但您可以在一行配置中切换渲染模式。
通用渲染
此步骤类似于 PHP 或 Ruby 应用程序执行的传统**服务器端渲染**。当浏览器请求启用了通用渲染的 URL 时,Nuxt 会在服务器环境中运行 JavaScript(Vue.js)代码,并将完全渲染的 HTML 页面返回到浏览器。如果页面已预先生成,Nuxt 也可以从缓存中返回完全渲染的 HTML 页面。与客户端渲染相反,用户会立即获得应用程序初始内容的全部内容。
下载 HTML 文档后,浏览器会对其进行解释,然后 Vue.js 会接管文档。曾经在服务器上运行的相同 JavaScript 代码现在会在客户端(浏览器)的后台**再次**运行,通过将其监听器绑定到 HTML 来启用交互性(因此称为**通用渲染**)。这称为**水合**。水合完成后,页面可以享受动态界面和页面过渡等优势。
通用渲染允许 Nuxt 应用程序在保留客户端渲染优势的同时提供快速的页面加载时间。此外,由于内容已存在于 HTML 文档中,因此爬虫可以在没有任何开销的情况下对其进行索引。
哪些内容是服务器渲染的,哪些内容是客户端渲染的?
在通用渲染模式下,询问 Vue 文件的哪些部分在服务器和/或客户端运行是很正常的。
<script setup lang="ts">
const counter = ref(0); // executes in server and client environments
const handleClick = () => {
counter.value++; // executes only in a client environment
};
</script>
<template>
<div>
<p>Count: {{ counter }}</p>
<button @click="handleClick">Increment</button>
</div>
</template>
在初始请求中,counter
ref 在服务器中初始化,因为它是在 <p>
标签内渲染的。handleClick
的内容在此处从未执行。在浏览器中的水合过程中,counter
ref 会重新初始化。handleClick
最终将其自身绑定到按钮;因此,可以合理地推断 handleClick
的主体将始终在浏览器环境中运行。
中间件 和 页面 在服务器和客户端的水合过程中运行。插件 可以在服务器或客户端或两者上渲染。组件 也可以强制仅在客户端运行。组合式函数 和 实用程序 基于其使用上下文进行渲染。
服务器端渲染的优势
- **性能**: 用户可以立即访问页面的内容,因为浏览器可以比 JavaScript 生成的内容更快地显示静态内容。同时,Nuxt 在水合过程中保留了 Web 应用程序的交互性。
- **搜索引擎优化**: 通用渲染将页面的整个 HTML 内容传递到浏览器,就像一个经典的服务器应用程序一样。Web 爬虫可以直接索引页面的内容,这使得通用渲染成为您希望快速索引任何内容的绝佳选择。
服务器端渲染的缺点
- **开发限制**: 服务器和浏览器环境不提供相同的 API,编写可以在两侧无缝运行的代码可能很棘手。幸运的是,Nuxt 提供了指南和特定变量来帮助您确定代码段在何处执行。
- **成本**: 需要运行服务器才能动态渲染页面。这会像任何传统服务器一样增加每月成本。但是,由于通用渲染和浏览器在客户端导航中接管,服务器调用大大减少。通过利用边缘侧渲染,可以降低成本。
通用渲染非常通用,可以适应几乎任何用例,尤其适用于任何内容导向的网站:**博客、营销网站、作品集、电子商务网站和市场**。
客户端渲染
开箱即用,传统的 Vue.js 应用程序在浏览器(或**客户端**)中渲染。然后,Vue.js 在浏览器下载并解析包含创建当前界面的指令的所有 JavaScript 代码后生成 HTML 元素。
客户端渲染的优势
- **开发速度**: 当完全在客户端工作时,我们不必担心代码的服务器兼容性,例如,通过使用仅限浏览器的 API(如
window
对象)。 - **更便宜**: 运行服务器会增加基础设施成本,因为您需要在支持 JavaScript 的平台上运行。我们可以在任何带有 HTML、CSS 和 JavaScript 文件的静态服务器上托管仅客户端的应用程序。
- **离线**: 因为代码完全在浏览器中运行,所以它可以在互联网不可用时很好地继续工作。
客户端渲染的缺点
- **性能**: 用户必须等待浏览器下载、解析和运行 JavaScript 文件。根据下载部分的网络和解析和执行的用户设备,这可能需要一些时间并影响用户体验。
- 搜索引擎优化:通过客户端渲染传递的内容的索引和更新比服务器渲染的 HTML 文档需要更多时间。这与我们讨论的性能缺陷有关,因为搜索引擎爬虫在第一次尝试索引页面时不会等待界面完全渲染。使用纯客户端渲染,您的内容将在搜索结果页面中花费更多时间显示和更新。
对于不需要索引或用户频繁访问的交互性很强的Web 应用,客户端渲染是一个不错的选择。它可以利用浏览器缓存来跳过后续访问的下载阶段,例如SaaS、后台应用或在线游戏。
您可以在 nuxt.config.ts
中使用 Nuxt 启用仅客户端渲染。
export default defineNuxtConfig({
ssr: false
})
ssr: false
,您还应该在 ~/app/spa-loading-template.html
中放置一个 HTML 文件,其中包含一些您想用于渲染加载屏幕的 HTML 代码,这些代码将在您的应用水合之前渲染。部署静态客户端渲染应用
如果您使用 静态托管 和 nuxi generate
或 nuxi build --prerender
命令部署您的应用,那么默认情况下,Nuxt 会将每个页面渲染为一个单独的静态 HTML 文件。
如果您正在使用纯客户端渲染,那么这可能是不必要的。您可能只需要一个 index.html
文件,加上 200.html
和 404.html
备用文件,您可以告诉您的静态 Web 主机为所有请求提供这些文件。
为了实现这一点,我们可以更改路由的预渲染方式。只需将此添加到 您的钩子 中的 nuxt.config.ts
中。
export default defineNuxtConfig({
hooks: {
'prerender:routes' ({ routes }) {
routes.clear() // Do not generate any routes (except the defaults)
}
},
})
这将生成三个文件
index.html
200.html
404.html
200.html
和 404.html
可能对您使用的托管提供商有用。
混合渲染
混合渲染允许使用路由规则为每个路由设置不同的缓存规则,并决定服务器如何响应给定 URL 的新请求。
以前,Nuxt 应用和服务器的每个路由/页面都必须使用相同的渲染模式,即通用或客户端。在各种情况下,某些页面可以在构建时生成,而其他页面应该使用客户端渲染。例如,考虑一个具有管理部分的内容网站。每个内容页面都应该主要为静态页面并生成一次,但管理部分需要注册并且更像是一个动态应用。
Nuxt 包括路由规则和混合渲染支持。使用路由规则,您可以为一组 Nuxt 路由定义规则,更改渲染模式或根据路由分配缓存策略!
Nuxt 服务器将使用 Nitro 缓存层 自动注册相应的中间件并使用缓存处理程序包装路由。
export default defineNuxtConfig({
routeRules: {
// Homepage pre-rendered at build time
'/': { prerender: true },
// Products page generated on demand, revalidates in background, cached until API response changes
'/products': { swr: true },
// Product pages generated on demand, revalidates in background, cached for 1 hour (3600 seconds)
'/products/**': { swr: 3600 },
// Blog posts page generated on demand, revalidates in background, cached on CDN for 1 hour (3600 seconds)
'/blog': { isr: 3600 },
// Blog post page generated on demand once until next deployment, cached on CDN
'/blog/**': { isr: true },
// Admin dashboard renders only on client-side
'/admin/**': { ssr: false },
// Add cors headers on API routes
'/api/**': { cors: true },
// Redirects legacy urls
'/old-page': { redirect: '/new-page' }
}
})
路由规则
您可以使用的不同属性如下
redirect: string
- 定义服务器端重定向。ssr: boolean
- 禁用应用部分 HTML 的服务器端渲染,并使其仅在浏览器中使用ssr: false
渲染。cors: boolean
- 使用cors: true
自动添加 cors 标头 - 您可以通过覆盖headers
来自定义输出。headers: object
- 为网站的部分添加特定标头 - 例如,您的资产。swr: number | boolean
- 为服务器响应添加缓存标头,并在服务器或反向代理上缓存它,以获得可配置的 TTL(生存时间)。Nitro 的node-server
预设能够缓存完整的响应。当 TTL 过期时,将发送缓存的响应,同时将在后台重新生成页面。如果使用 true,则会添加stale-while-revalidate
标头,但没有 MaxAge。isr: number | boolean
- 行为与swr
相同,除了我们能够将响应添加到支持此功能的平台(目前为 Netlify 或 Vercel)上的 CDN 缓存中。如果使用true
,则内容会保留在 CDN 中,直到下一次部署。prerender: boolean
- 在构建时预渲染路由,并将它们作为静态资产包含在您的构建中。experimentalNoScripts: boolean
- 禁用网站部分的 Nuxt 脚本和 JS 资源提示的渲染。appMiddleware: string | string[] | Record<string, boolean>
- 允许您定义应用部分(即,不是您的 Nitro 路由)的 Vue 应用部分的页面路径应该或不应该运行的中间件。
只要有可能,路由规则将自动应用于部署平台的原生规则,以获得最佳性能(目前支持 Netlify 和 Vercel)。
nuxt generate
时,混合渲染不可用。示例
边缘侧渲染
边缘侧渲染 (ESR) 是 Nuxt 中引入的一项强大功能,它允许通过内容交付网络 (CDN) 的边缘服务器将您的 Nuxt 应用渲染得更靠近您的用户。通过利用 ESR,您可以确保提高性能并减少延迟,从而提供增强的用户体验。
使用 ESR,渲染过程被推送到网络的“边缘”——CDN 的边缘服务器。请注意,ESR 更像是一个部署目标,而不是一种实际的渲染模式。
当发出页面请求时,它不会一直到达原始服务器,而是会被最近的边缘服务器拦截。此服务器生成页面的 HTML 并将其发送回用户。此过程最大限度地减少了数据需要传输的物理距离,从而减少延迟并更快地加载页面。
边缘侧渲染得益于 Nitro,这是为 Nuxt 3 提供动力的 服务器引擎。它提供对 Node.js、Deno、Cloudflare Workers 等的跨平台支持。
您可以利用 ESR 的当前平台为
- Cloudflare Pages 使用 git 集成和
nuxt build
命令进行零配置。 - Vercel Edge Functions 使用
nuxt build
命令和NITRO_PRESET=vercel-edge
环境变量。 - Netlify Edge Functions 使用
nuxt build
命令和NITRO_PRESET=netlify-edge
环境变量。
请注意,使用边缘侧渲染和路由规则时,可以使用混合渲染。
您可以探索部署在上面提到的某些平台上的开源示例