Nuxt 性能

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

Nuxt 内置了旨在提高应用程序性能并有助于改善核心 Web 指标的功能。还有多个 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 前缀即可。当组件并非总是需要时,这非常有用。

<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 包大小。

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

懒惰水合

并非总是需要在初始加载时水合(或使交互式)网站的所有组件。通过使用懒惰水合,您可以控制组件何时加载其代码,这可以改善应用程序的首次交互时间指标。Nuxt 允许您通过懒惰水合(在 Nuxt v3.16 中添加)控制组件何时变得交互式。

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

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

懒惰水合中阅读更多内容。

数据获取

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

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

核心 Nuxt 模块

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

图片

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

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

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

  • 使用内置提供商优化本地和远程图像
  • src 转换为提供商优化的 URL,支持 WebP 或 Avif 等现代格式
  • 根据 widthheight 自动调整图像大小
  • 提供尺寸选项时生成响应式 sizes
  • 支持原生 lazy loading 以及其他 <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 字体将自动优化您的字体(包括自定义字体),并消除外部网络请求,从而改善隐私和性能。

它包含了任何字体文件的内置自动自托管功能,这意味着您可以通过底层软件包实现最优的 Web 字体加载,并减少布局偏移,这得益于底层软件包fontaine.

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

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

它支持多种提供商,这些提供商被设计为可插拔和可扩展的,因此无论您的设置如何,您都应该能够使用现有提供商或编写自己的提供商。

脚本

第三方资源,如分析工具、视频嵌入、地图和社交媒体集成,可以增强网站功能,但也可能显著降低用户体验,并对下次绘制交互 (INP)和最大内容绘制 (LCP) 分数产生负面影响。

Nuxt Scripts让您以更好的性能、隐私、安全性和开发体验加载第三方脚本。

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中阅读更多内容。

分析工具

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

Nuxi 分析

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

当您在可视化中看到一个大块时,这通常预示着优化的机会——无论是将其拆分为更小的部分、实现懒加载,还是用更高效的替代方案替换它,尤其是对于第三方库。

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

Nuxt DevTools

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

它附带了我们可以用来衡量 Nuxt 应用程序性能的几个功能

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

Chrome 开发者工具

Chrome DevTools 带有两个用于衡量性能的有用选项卡;PerformanceLighthouse

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

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

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

每个审计都有一个参考文档,解释了审计的重要性以及如何修复它。

PageSpeed Insights

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

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

网页测试

WebPageTest是一款网络性能工具,提供有关页面在各种条件下性能表现的深度诊断信息。

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

常见问题

在构建更复杂的 Nuxt 应用程序时,您可能会遇到以下一些问题。理解并解决这些问题将有助于您提高网站性能。

过度使用插件

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

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

未使用的代码/依赖项

问题:随着项目的开发,可能会出现一些未使用的代码或依赖项。这些额外的功能可能没有被使用或需要,但会增加我们项目的打包大小。

解决方案:检查您的 package.json 中是否存在未使用的依赖项,并分析您的代码中是否存在未使用的实用程序/组合/函数。

不使用 Vue 性能技巧

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

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

不遵循模式

问题:目前参与项目的人越多,维护稳定的代码库就越困难。开发人员倾向于引入他们在其他项目中见过的新概念,这可能导致冲突和性能问题。

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

试图同时加载所有内容

问题:当页面加载时,如果未能正确指示元素加载顺序,将导致所有内容同时获取——这可能很慢并导致糟糕的用户体验。

解决方案:使用渐进式增强等概念,即首先设置核心网页内容,然后随着浏览器/互联网连接的允许,在其之上添加更精细和技术上更严格的呈现和功能层。

有用资源

要了解更多关于提高性能的各种技术,请查看以下资源

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