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 的主体将始终在浏览器环境中运行。
中间件和页面在服务器和客户端水合期间运行。插件可以在服务器、客户端或两者上渲染。组件也可以强制只在客户端运行。组合式函数和工具函数根据其使用上下文进行渲染。
服务器端渲染的优点
服务器端渲染的缺点
通用渲染用途广泛,几乎适用于所有用例,尤其适用于任何面向内容的网站:博客、营销网站、作品集、电子商务网站和市场。
开箱即用,传统的 Vue.js 应用程序在浏览器(或客户端)中渲染。然后,在浏览器下载并解析包含用于创建当前界面的指令的所有 JavaScript 代码后,Vue.js 生成 HTML 元素。
客户端渲染的优点
window 对象。客户端渲染的缺点
客户端渲染是需要大量交互的Web 应用程序的不错选择,这些应用程序不需要索引或用户经常访问。它可以利用浏览器缓存来跳过后续访问的下载阶段,例如 SaaS、后台应用程序或在线游戏。
您可以在 nuxt.config.ts 中为 Nuxt 启用纯客户端渲染。
export default defineNuxtConfig({
ssr: false,
})
ssr: false,您还应该在 ~/spa-loading-template.html 中放置一个 HTML 文件,其中包含您希望在应用程序水合之前用于渲染加载屏幕的一些 HTML。如果您使用 nuxt generate 或 nuxt build --prerender 命令将您的应用程序部署到静态托管,那么默认情况下,Nuxt 会将每个页面渲染为单独的静态 HTML 文件。
nuxt generate 或 nuxt build --prerender 命令预渲染您的应用程序,那么您将无法使用任何服务器端点,因为您的输出文件夹中将不包含服务器。如果您需要服务器功能,请改用 nuxt build。如果您纯粹使用客户端渲染,那么这可能是不必要的。您可能只需要一个 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.html200.html404.html200.html 和 404.html 可能对您使用的托管服务提供商有用。
预渲染客户端渲染应用时,Nuxt 默认会生成 index.html、200.html 和 404.html 文件。但是,如果您需要阻止在构建中生成这些文件中的任何一个(或全部),您可以使用来自 Nitro 的 'prerender:generate' 钩子。
export default defineNuxtConfig({
ssr: false,
nitro: {
hooks: {
'prerender:generate' (route) {
const routesToSkip = ['/index.html', '/200.html', '/404.html']
if (routesToSkip.includes(route.route)) {
route.skip = true
}
},
},
},
})
混合渲染允许使用路由规则为每个路由设置不同的缓存规则,并决定服务器如何响应给定 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 - 在构建时预渲染路由并将其作为静态资产包含在构建中。noScripts: boolean - 禁用 Nuxt 脚本和 JS 资源提示的渲染,用于您网站的某些部分。appMiddleware: string | string[] | Record<string, boolean> - 允许您定义应或不应在应用程序的 Vue 应用部分(即非 Nitro 路由)中为页面路径运行的中间件。在可能的情况下,路由规则将自动应用于部署平台的原生规则以获得最佳性能(目前支持 Netlify 和 Vercel)。
nuxt generate 时无法使用混合渲染。示例
边缘侧渲染(ESR)是 Nuxt 中引入的一项强大功能,它允许您的 Nuxt 应用程序通过内容分发网络(CDN)的边缘服务器更接近用户进行渲染。通过利用 ESR,您可以确保提高性能并减少延迟,从而提供增强的用户体验。
ESR 将渲染过程推到网络的“边缘”——CDN 的边缘服务器。请注意,ESR 更像是一个部署目标,而不是一种实际的渲染模式。
当请求页面时,它不会一直发送到原始服务器,而是被最近的边缘服务器拦截。该服务器生成页面的 HTML 并将其发送回用户。这个过程最大限度地减少了数据传输的物理距离,从而减少了延迟并加快了页面加载速度。
边缘侧渲染之所以可能,要归功于Nitro,为 Nuxt 提供动力的服务器引擎。它为 Node.js、Deno、Cloudflare Workers 等提供跨平台支持。
您可以利用 ESR 的当前平台是
nuxt build 命令实现零配置。nuxt build 命令和 NITRO_PRESET=vercel-edge 环境变量。nuxt build 命令和 NITRO_PRESET=netlify-edge 环境变量请注意,当使用边缘侧渲染与路由规则时,可以使用混合渲染。
您可以探索部署在上述某些平台上的开源示例。