Nuxt 性能

提高 Nuxt 应用性能的最佳实践。

Nuxt 内置了旨在提高应用程序性能并有助于改善核心网页指标 (Core Web Vitals)的功能。还有多个 Nuxt 核心模块有助于在特定领域提高性能。本指南概述了优化 Nuxt 应用程序性能的最佳实践。

内置功能

Nuxt 提供了一些内置功能,可帮助您优化网站的性能。了解这些功能的工作原理对于实现极快的性能至关重要。

<NuxtLink> 是 Vue Router 的 <RouterLink> 组件和 HTML 的 <a> 标签的直接替代品。它智能地确定链接是内部链接还是外部链接,并相应地以可用优化(预取、默认属性等)进行渲染。

<template>
  <NuxtLink to="/about">About page</NuxtLink>
</template>

<!-- Which will render to with Vue Router & Smart Prefetching -->
<a href="/about">About page</a>

Nuxt 会自动包含智能预取。这意味着它会检测链接何时可见(默认情况下),无论是位于视口内还是滚动时,并预取这些页面的 JavaScript,以便在用户单击链接时它们已准备就绪。

您也可以选择在交互时预取

export default defineNuxtConfig({
  experimental: {
    defaults: {
      nuxtLink: {
        prefetchOn: 'interaction',
      },
    },
  },
})
NuxtLink 中阅读更多内容。

混合渲染

在更复杂的应用程序中,我们可能需要对应用程序的渲染方式进行完全控制,以支持某些页面可以在构建时生成,而其他页面应在客户端渲染的情况

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

export default defineNuxtConfig({
  routeRules: {
    '/': {
      prerender: true,
    },
    '/products/**': {
      swr: 3600,
    },
    '/blog': {
      isr: 3600,
    },
    '/admin/**': {
      ssr: false,
    },
  },
})

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

混合渲染 中阅读更多内容。

组件的延迟加载 (Lazy Loading Components)

要动态导入组件(也称为延迟加载组件),您需要做的就是在组件名称前添加 Lazy 前缀。如果并非总是需要该组件,这会很有用。

<script setup lang="ts">
const show = ref(false)
</script>

<template>
  <div>
    <h1>Mountains</h1>
    <LazyMountainsList v-if="show" />
    <button v-if="!show" @click="show = true">Show List</button>
  </div>
</template>

通过使用 Lazy 前缀,您可以将组件代码的加载推迟到正确的时刻,这有助于优化您的 JavaScript 包大小。

延迟加载组件 中阅读更多内容。

延迟水合 (Lazy Hydration)

并非总需要在初始加载时水合(或使交互化)您网站上的所有组件。使用延迟水合,您可以控制组件代码的加载时间,这可以提高您应用的交互时间指标。Nuxt 允许您使用延迟水合来控制组件何时变得可交互(Nuxt v3.16 中添加)。

<template>
  <div>
    <LazyMyComponent hydrate-on-visible />
  </div>
</template>

要优化您的应用,您可能希望将某些组件的延迟水合推迟到它们可见时,或者推迟到浏览器完成更重要的任务时。

延迟水合 中阅读更多内容。

数据获取

为避免重复获取相同数据(服务器上一次,客户端上一次),Nuxt 提供了 useFetchuseAsyncData。它们确保如果在服务器上进行了 API 调用,数据将在有效载荷中转发到客户端,而不是再次获取。

数据获取 中阅读更多内容。

核心 Nuxt 模块

除了 Nuxt 的内置功能外,还有 Nuxt 团队维护的核心模块,有助于进一步提高性能。这些模块有助于处理图像、自定义字体或第三方脚本等资产。

图片

未优化的图像会对您的网站性能产生重大的负面影响,特别是最大内容绘制 (Largest Contentful Paint - LCP)得分。

在 Nuxt 中,我们可以使用Vercel 上使用 Nuxt Image模块,它是 Nuxt 应用的即插即用图像优化。它允许使用内置优化器或您最喜欢的图像 CDN 调整图像大小和转换图像。

<NuxtImg> 是原生 <img> 标签的直接替代品,具有以下增强功能

  • 使用内置提供程序优化本地和远程图像
  • src 转换为提供程序优化后的 URL,使用 WebP 或 Avif 等现代格式
  • 根据 widthheight 自动调整图像大小
  • 提供 sizes 选项时生成响应式 sizes
  • 支持原生 延迟加载 以及其他 <img> 属性

网站中的图像通常可以根据重要性进行划分:在初始加载时需要首先交付的图像(即 最大内容绘制),以及可以稍后加载或在特定需要时加载的图像。为此,我们可以使用以下优化

<template>
  <!-- 🚨 Needs to be loaded ASAP -->
  <NuxtImg
    src="/hero-banner.jpg"
    format="webp"
    preload
    loading="eager"
    fetch-priority="high"
    width="200"
    height="100"
  />

  <!-- 🐌 Can be loaded later -->
  <NuxtImg
    src="/facebook-logo.jpg"
    format="webp"
    loading="lazy"
    fetch-priority="low"
    width="200"
    height="100"
  />
</template>
Nuxt Image 中阅读更多内容。

字体

Nuxt 字体 (Nuxt Fonts)将自动优化您的字体(包括自定义字体)并移除外部网络请求,以提高隐私和性能。

它包含内置的自动自托管功能,用于任何字体文件,这意味着您可以以最佳方式加载网络字体,从而减少布局偏移,这得益于底层包fontaine.

Nuxt Fonts 会处理您的所有 CSS,并在遇到 font-family 声明时自动执行以下操作。

  1. 解析字体 – 在 public/ 中查找字体文件,然后检查 Google、Bunny 和 Fontshare 等网络提供商。
  2. 生成 @font-face 规则 – 注入 CSS 规则以从正确的源加载字体。
  3. 代理和缓存字体 – 将 URL 重写为 /_fonts,在本地下载和缓存字体。
  4. 创建回退指标 – 调整本地系统字体以匹配网络字体,减少布局偏移(CLS).
  5. 包含字体到构建中 – 将字体与项目捆绑在一起,哈希文件名并设置长期缓存标头。

它支持多种旨在可插拔和可扩展的提供程序,因此无论您的设置如何,您都应该能够使用现有的提供程序或编写自己的提供程序。

脚本 (Scripts)

第三方资源,如分析工具、视频嵌入、地图和社交媒体集成,增强了网站功能,但会严重影响用户体验并对下一次绘制的交互 (Interaction to Next Paint - INP)和最大内容绘制 (LCP) 分数产生负面影响。

Nuxt Scripts允许您以更好的性能、隐私、安全和 DX 加载第三方脚本。

Nuxt Scripts 在第三方脚本之上提供了一个抽象层,提供 SSR 支持和类型安全,同时仍然让您可以完全低级别地控制脚本的加载方式。

const { onLoaded, proxy } = useScriptGoogleAnalytics(
  {
    id: 'G-1234567',
    scriptOptions: {
      trigger: 'manual',
    },
  },
)
// queue events to be sent when ga loads
proxy.gtag('config', 'UA-123456789-1')
// or wait until ga is loaded
onLoaded((gtag) => {
  // script loaded
})
Nuxt Scripts 中阅读更多内容。

分析工具 (Profiling Tools)

要提高性能,我们首先需要知道如何衡量它,从在开发期间——在本地环境中衡量性能开始,然后转向审计部署在生产环境中的应用程序。

Nuxi 分析 (Nuxi Analyze)

nuxi 命令允许分析生产包或您的 Nuxt 应用程序。它利用 vite-bundle-visualizer(类似于 webpack-bundle-analyzer)生成应用程序包的视觉表示,从而更容易识别哪些组件占用了最大的空间。

当您在可视化中看到一个大块时,它通常预示着一个优化机会——无论是将其分成更小的部分、实施延迟加载,还是用更高效的替代品替换它,特别是对于第三方库。

包含多个元素的大块通常可以通过仅导入必要的组件而不是整个模块来减小,而大的独立块可能更适合延迟加载而不是包含在主包中。

Nuxt DevTools

用于格式化的Nuxt DevTools为您提供有关您的 Nuxt App 的见解和透明度,以识别性能差距并无缝管理您的应用配置。

它具有我们可以用来衡量 Nuxt 应用性能的几项功能

  1. 时间线 (Timeline) – 跟踪在渲染、更新和初始化组件上花费的时间,以识别性能瓶颈。
  2. 资源 (Assets) – 显示文件大小(例如图像),不进行转换。
  3. 渲染树 (Render Tree) – 显示 Vue 组件、脚本和样式之间的连接,以优化动态加载。
  4. 检查 (Inspect) – 列出 Vue 应用中使用的所有文件及其大小和评估时间。

Chrome 开发者工具 (Chrome DevTools)

Chrome 开发者工具带有两个用于衡量性能的有用的选项卡:PerformanceLighthouse

当您打开性能面板时,它会立即显示您的本地最大内容绘制 (LCP)累积布局偏移 (CLS) 分数(好、需要改进或差)。

如果您与页面交互,它还会捕获下一次绘制的交互 (INP),根据您的设备和网络,为您提供核心网页指标的完整视图。

Lighthouse审计性能、可访问性、SEO、渐进式 Web 应用和最佳实践。它对您的页面运行测试并生成报告。使用不通过的审计作为改进您网站的指南。

每个审计都有一个参考文档,解释为什么该审计很重要,以及如何修复它。

PageSpeed Insights

PageSpeed Insights (PSI)报告页面在移动和桌面设备上的用户体验,并提供有关如何改进该页面的建议。

它提供关于页面的实验室数据和现场数据。实验室数据对于调试问题很有用,因为它是在受控环境中收集的,而现场数据对于捕获真实、现实世界中的用户体验很有用。

Web 性能测试 (Web Page Test)

WebPageTest是一个 Web 性能工具,提供有关页面在各种条件下如何运行的深入诊断信息。

每次测试都可以从世界各地不同的位置,在真实浏览器上,通过任意数量的可自定义网络条件运行。

常见问题

在构建更复杂的 Nuxt 应用程序时,您可能会遇到下面列出的一些问题。了解和修复这些问题将有助于提高您网站的性能。

过度使用插件

问题:大量的插件可能会导致性能问题,特别是如果它们需要昂贵的计算或初始化时间过长。由于插件在水合阶段运行,低效的设置可能会阻止渲染并降低用户体验。

解决方案:检查您的插件,看看其中一些是否可以作为组合函数或实用函数来实现。

未使用的代码/依赖项

问题:随着项目的开发,可能会出现一些未使用的代码或依赖项。此附加功能可能未被使用或不需要,但它会增加我们项目的包大小。

解决方案:检查您的 package.json 中未使用的依赖项,并分析您的代码中未使用的工具/组合函数/函数。

未遵循 Vue 性能提示

问题: Vue 文档列出了我们也可以在 Nuxt 项目中使用的几项性能改进,但由于它们是 Vue 文档的一部分,开发人员往往会忘记它们,而只关注 Nuxt 特定的改进——尽管 Nuxt 应用程序仍然是一个 Vue 项目。

解决方案:使用 shallowRefv-memov-once 等概念来提高性能。

未遵循模式

问题:目前在项目上工作的人越多,维护稳定代码库就越困难。开发人员倾向于引入他们在另一个项目中看到的新概念,这可能会导致与性能冲突和问题。

解决方案:在项目中建立规则和模式,例如Vue 组合函数的最佳实践和设计模式

尝试同时加载所有内容

问题:当页面加载且未正确指示元素的加载顺序时,会导致所有元素同时获取——这可能很慢并导致不良的用户体验。

解决方案:使用渐进增强等概念,其中核心网页内容首先设置,然后根据浏览器/互联网连接的允许情况,在顶部添加更细致和技术上更严格的表示和功能层。

有用资源

要了解有关提高性能的各种技术的更多信息,请参阅以下资源

  1. 使用 PRPL 模式实现即时加载
  2. 感知性能
  3. 理解关键渲染路径