渲染模式
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 内容作为经典服务器应用程序传递到浏览器。网络爬虫可以直接索引页面的内容,这使得通用渲染成为您想要快速索引的任何内容的绝佳选择。
服务器端渲染的缺点
- 开发限制: 服务器和浏览器环境不提供相同的 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>
- 允许您定义中间件,该中间件应该或不应该为应用程序的 Vue 应用程序部分中的页面路径运行(即,不是您的 Nitro 路由)
在可能的情况下,路由规则将自动应用于部署平台的原生规则,以获得最佳性能(目前支持 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
环境变量
请注意,在使用带有路由规则的边缘端渲染时,可以使用混合渲染。
您可以探索在上述某些平台上部署的开源示例