跳到内容

3

优化字体和图像

在上一章节中,您学习了如何为 Next.js 应用程序设置样式。让我们继续处理您的主页,添加自定义字体和 hero 图像。

在本章节中...

以下是我们将要涵盖的主题

如何使用 next/font 添加自定义字体。

如何使用 next/image 添加图像。

Next.js 中字体和图像是如何优化的。

为什么要优化字体?

字体在网站设计中起着重要的作用,但是如果在项目中需要获取和加载字体文件,则使用自定义字体可能会影响性能。

累积布局偏移 是 Google 用来评估网站性能和用户体验的指标。对于字体,当浏览器最初以回退字体或系统字体渲染文本,然后在自定义字体加载后将其替换时,会发生布局偏移。这种替换可能会导致文本大小、间距或布局发生变化,从而使其周围的元素发生偏移。

Mock UI showing initial load of a page, followed by a layout shift as the custom font loads.

当您使用 next/font 模块时,Next.js 会自动优化应用程序中的字体。它在构建时下载字体文件,并将它们与您的其他静态资源一起托管。这意味着当用户访问您的应用程序时,不会有额外的字体网络请求,从而影响性能。

添加主要字体

让我们向您的应用程序添加自定义 Google 字体,看看它是如何工作的。

在您的 /app/ui 文件夹中,创建一个名为 fonts.ts 的新文件。您将使用此文件来保存将在整个应用程序中使用的字体。

next/font/google 模块导入 Inter 字体 - 这将是您的主要字体。然后,指定您要加载的 子集。在本例中,为 'latin'

/app/ui/fonts.ts
import { Inter } from 'next/font/google';
 
export const inter = Inter({ subsets: ['latin'] });

最后,将字体添加到 /app/layout.tsx 中的 <body> 元素中

/app/layout.tsx
import '@/app/ui/global.css';
import { inter } from '@/app/ui/fonts';
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={`${inter.className} antialiased`}>{children}</body>
    </html>
  );
}

通过将 Inter 添加到 <body> 元素,字体将应用于您的整个应用程序。在这里,您还添加了 Tailwind antialiased 类,它可以平滑字体。不一定要使用此类,但它可以增加美观度。

导航到您的浏览器,打开开发者工具并选择 body 元素。您应该看到 InterInter_Fallback 现在已应用于样式下。

练习:添加辅助字体

您还可以将字体添加到应用程序的特定元素。

现在轮到您了!在您的 fonts.ts 文件中,导入一个名为 Lusitana 的辅助字体,并将其传递给 /app/page.tsx 文件中的 <p> 元素。除了像之前一样指定子集之外,您还应该指定不同的字体粗细。例如,400(正常)和 700(粗体)。

准备好后,展开下面的代码片段以查看解决方案。

提示

  • 如果您不确定要传递给字体的粗细选项,请检查代码编辑器中的 TypeScript 错误。
  • 访问 Google 字体 网站并搜索 Lusitana 以查看有哪些选项可用。
  • 请参阅 添加多个字体完整选项列表 的文档。

最后,<AcmeLogo /> 组件也使用了 Lusitana。它被注释掉了以防止错误,您现在可以取消注释它

/app/page.tsx
// ...
 
export default function Page() {
  return (
    <main className="flex min-h-screen flex-col p-6">
      <div className="flex h-20 shrink-0 items-end rounded-lg bg-blue-500 p-4 md:h-52">
        <AcmeLogo />
        {/* ... */}
      </div>
    </main>
  );
}

太棒了,您已经向您的应用程序添加了两种自定义字体!接下来,让我们向主页添加 hero 图像。

为什么要优化图像?

Next.js 可以在顶层 /public 文件夹下提供静态资源,例如图像。/public 文件夹内的文件可以在您的应用程序中引用。

使用常规 HTML,您将按如下方式添加图像

<img
  src="/hero.png"
  alt="Screenshots of the dashboard project showing desktop version"
/>

但是,这意味着您必须手动

  • 确保您的图像在不同屏幕尺寸上具有响应性。
  • 为不同的设备指定图像尺寸。
  • 防止图像加载时发生布局偏移。
  • 延迟加载用户视口之外的图像。

图像优化是 Web 开发中的一个重要主题,可以被认为是其自身的专业领域。与其手动实现这些优化,不如使用 next/image 组件来自动优化您的图像。

<Image> 组件

<Image> 组件是 HTML <img> 标签的扩展,并带有自动图像优化功能,例如

  • 在图像加载时自动防止布局偏移。
  • 调整图像大小以避免向视口较小的设备发送大型图像。
  • 默认情况下延迟加载图像(图像在进入视口时加载)。
  • 以现代格式(如 WebPAVIF)提供图像,当浏览器支持时。

添加桌面 hero 图像

让我们使用 <Image> 组件。如果您查看 /public 文件夹内部,您会看到有两个图像:hero-desktop.pnghero-mobile.png。这两个图像完全不同,它们将根据用户的设备是桌面设备还是移动设备来显示。

在您的 /app/page.tsx 文件中,从 next/image 导入组件。然后,在注释下添加图像

/app/page.tsx
import AcmeLogo from '@/app/ui/acme-logo';
import { ArrowRightIcon } from '@heroicons/react/24/outline';
import Link from 'next/link';
import { lusitana } from '@/app/ui/fonts';
import Image from 'next/image';
 
export default function Page() {
  return (
    // ...
    <div className="flex items-center justify-center p-6 md:w-3/5 md:px-28 md:py-12">
      {/* Add Hero Images Here */}
      <Image
        src="/hero-desktop.png"
        width={1000}
        height={760}
        className="hidden md:block"
        alt="Screenshots of the dashboard project showing desktop version"
      />
    </div>
    //...
  );
}

在这里,您将 width 设置为 1000 像素,height 设置为 760 像素。最佳实践是将图像的 widthheight 设置为避免布局偏移,这些值应与源图像的宽高比相同。这些值不是图像渲染的大小,而是用于理解宽高比的实际图像文件的大小。

您还会注意到 hidden 类从移动屏幕上的 DOM 中删除图像,而 md:block 类在桌面屏幕上显示图像。

这是您的主页现在的样子

Styled home page with a custom font and hero image

练习:添加移动 hero 图像

现在轮到您了!在您刚刚添加的图像下方,为 hero-mobile.png 添加另一个 <Image> 组件。

  • 图像应具有 560 像素的 width620 像素的 height
  • 它应该在移动屏幕上显示,在桌面上隐藏 - 您可以使用开发者工具检查桌面和移动图像是否正确交换。

准备好后,展开下面的代码片段以查看解决方案。

太棒了!您的主页现在有了自定义字体和 hero 图像。

关于这些主题还有很多要学习的内容,包括优化远程图像和使用本地字体文件。如果您想更深入地了解字体和图像,请参阅

您已完成章节3

您已经学习了如何使用 Next.js 优化字体和图像。

下一步

4:创建布局和页面

让我们使用嵌套布局和页面创建您的仪表板路由!