Nuxt Nation 大会即将到来。加入我们,时间为 11 月 12-13 日。

渲染模式

了解 Nuxt 中可用的不同渲染模式。

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 文档中,因此爬虫可以在没有任何开销的情况下对其进行索引。

Users can access the static content when the HTML document is loaded. Hydration then allows page's interactivity

哪些内容是服务器渲染的,哪些内容是客户端渲染的?

在通用渲染模式下,询问 Vue 文件的哪些部分在服务器和/或客户端运行是很正常的。

app.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 代码的更多示例,请参阅Vue 文档
在导入依赖于浏览器 API 并具有副作用的库时,请确保导入它的组件仅在客户端调用。打包器不会对包含副作用的模块的导入进行树状抖动。

客户端渲染

开箱即用,传统的 Vue.js 应用程序在浏览器(或**客户端**)中渲染。然后,Vue.js 在浏览器下载并解析包含创建当前界面的指令的所有 JavaScript 代码后生成 HTML 元素。

Users have to wait for the browser to download, parse and execute the JavaScript before seeing the page's content

客户端渲染的优势

  • **开发速度**: 当完全在客户端工作时,我们不必担心代码的服务器兼容性,例如,通过使用仅限浏览器的 API(如 window 对象)。
  • **更便宜**: 运行服务器会增加基础设施成本,因为您需要在支持 JavaScript 的平台上运行。我们可以在任何带有 HTML、CSS 和 JavaScript 文件的静态服务器上托管仅客户端的应用程序。
  • **离线**: 因为代码完全在浏览器中运行,所以它可以在互联网不可用时很好地继续工作。

客户端渲染的缺点

  • **性能**: 用户必须等待浏览器下载、解析和运行 JavaScript 文件。根据下载部分的网络和解析和执行的用户设备,这可能需要一些时间并影响用户体验。

  • 搜索引擎优化:通过客户端渲染传递的内容的索引和更新比服务器渲染的 HTML 文档需要更多时间。这与我们讨论的性能缺陷有关,因为搜索引擎爬虫在第一次尝试索引页面时不会等待界面完全渲染。使用纯客户端渲染,您的内容将在搜索结果页面中花费更多时间显示和更新。

对于不需要索引或用户频繁访问的交互性很强的Web 应用,客户端渲染是一个不错的选择。它可以利用浏览器缓存来跳过后续访问的下载阶段,例如SaaS、后台应用或在线游戏

您可以在 nuxt.config.ts 中使用 Nuxt 启用仅客户端渲染。

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false
})
如果您确实使用了 ssr: false,您还应该在 ~/app/spa-loading-template.html 中放置一个 HTML 文件,其中包含一些您想用于渲染加载屏幕的 HTML 代码,这些代码将在您的应用水合之前渲染。
SPA 加载模板 中了解更多信息。
观看 Alexander Lichter 关于使用 Nuxt 构建一个简单的 SPA!? 的视频。

部署静态客户端渲染应用

如果您使用 静态托管nuxi generatenuxi build --prerender 命令部署您的应用,那么默认情况下,Nuxt 会将每个页面渲染为一个单独的静态 HTML 文件。

如果您正在使用纯客户端渲染,那么这可能是不必要的。您可能只需要一个 index.html 文件,加上 200.html404.html 备用文件,您可以告诉您的静态 Web 主机为所有请求提供这些文件。

为了实现这一点,我们可以更改路由的预渲染方式。只需将此添加到 您的钩子 中的 nuxt.config.ts 中。

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.html404.html 可能对您使用的托管提供商有用。

混合渲染

混合渲染允许使用路由规则为每个路由设置不同的缓存规则,并决定服务器如何响应给定 URL 的新请求。

以前,Nuxt 应用和服务器的每个路由/页面都必须使用相同的渲染模式,即通用或客户端。在各种情况下,某些页面可以在构建时生成,而其他页面应该使用客户端渲染。例如,考虑一个具有管理部分的内容网站。每个内容页面都应该主要为静态页面并生成一次,但管理部分需要注册并且更像是一个动态应用。

Nuxt 包括路由规则和混合渲染支持。使用路由规则,您可以为一组 Nuxt 路由定义规则,更改渲染模式或根据路由分配缓存策略!

Nuxt 服务器将使用 Nitro 缓存层 自动注册相应的中间件并使用缓存处理程序包装路由。

nuxt.config.ts
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 时,混合渲染不可用。

示例

Nuxt Vercel ISR

部署在 Vercel 上的具有混合渲染的 Nuxt 应用示例。

边缘侧渲染

边缘侧渲染 (ESR) 是 Nuxt 中引入的一项强大功能,它允许通过内容交付网络 (CDN) 的边缘服务器将您的 Nuxt 应用渲染得更靠近您的用户。通过利用 ESR,您可以确保提高性能并减少延迟,从而提供增强的用户体验。

使用 ESR,渲染过程被推送到网络的“边缘”——CDN 的边缘服务器。请注意,ESR 更像是一个部署目标,而不是一种实际的渲染模式。

当发出页面请求时,它不会一直到达原始服务器,而是会被最近的边缘服务器拦截。此服务器生成页面的 HTML 并将其发送回用户。此过程最大限度地减少了数据需要传输的物理距离,从而减少延迟并更快地加载页面

边缘侧渲染得益于 Nitro,这是为 Nuxt 3 提供动力的 服务器引擎。它提供对 Node.js、Deno、Cloudflare Workers 等的跨平台支持。

您可以利用 ESR 的当前平台为

请注意,使用边缘侧渲染和路由规则时,可以使用混合渲染

您可以探索部署在上面提到的某些平台上的开源示例

Nuxt Todos Edge

一个具有用户身份验证、SSR 和 SQLite 的待办事项应用。

Atinotes

基于 Cloudflare KV 的通用渲染可编辑网站。