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 转换为使用现代格式(如 WebP 或 Avif)优化的提供程序 URL
  • 根据 widthheight 自动调整图像大小
  • 提供 sizes 选项时生成响应式 sizes
  • 支持原生 lazy loading 以及其他 <img> 属性

您网站中的图片通常可以按重要性进行分类;那些需要在初始加载时首先交付的(即 Largest Contentful Paint),以及那些可以稍后加载或在特定需要时加载的。为此,我们可以使用以下优化措施

<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 Fonts将自动优化您的字体(包括自定义字体),并消除外部网络请求,以提高隐私和性能。

它包含任何字体文件的内置自动自托管功能,这意味着您可以以减少布局偏移的方式优化加载网络字体,这得益于底层软件包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 Analyze

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

当您在可视化图中看到一个大块时,这通常意味着存在优化机会——无论是将其拆分成更小的部分、实现懒加载,还是用更高效的替代品替换它,特别是对于第三方库而言。

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

Nuxt DevTools

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

它附带了几个可用于衡量 Nuxt 应用性能的功能

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

Chrome 开发者工具

Chrome 开发者工具提供了两个用于衡量性能的实用选项卡:PerformanceLighthouse

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

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

灯塔审计性能、可访问性、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. 理解关键渲染路径