优化字体和图像 3个月前

编程语言
923
优化字体和图像

在上一章中,学习了如何为 Next.js 应用程序添加样式。接下来,我们将继续改进主页,添加自定义字体和主图。

在本章中...

以下是我们将要介绍的主题:

  • 如何使用 next/font 添加自定义字体。
  • 如何使用 next/image 添加图像。
  • Next.js 中如何优化字体和图像。

为什么要优化字体?

字体在网站设计中扮演了重要角色,但在项目中使用自定义字体可能会影响性能,因为需要加载和获取字体文件。

Cumulative Layout Shift, CLS 是 Google 用来评估网站性能和用户体验的一个指标。在使用字体时,当浏览器初次渲染文本时使用的是回退或系统字体,随后在自定义字体加载后进行替换,这种替换可能导致文本大小、间距或布局的变化,从而引起布局的偏移。

image

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

是时候进行测验了!

Next.js 如何优化字体?

A. 它导致额外的网络请求,从而提高性能。 B. 它禁用所有自定义字体。 C. 它在运行时预加载所有字体。 D. 它将字体文件与其他静态资源一起托管,因此不需要额外的网络请求。

检查答案

添加主要字体

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

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

next/font/google 模块中导入 Inter 字体——这将是你的主要字体。然后,指定要加载的 字符子集(subset),在本例中是 '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> 元素。除了像之前一样指定字符子集外,你还需要指定字体 **粗细(weight)**。

当你准备好后,展开以下代码段查看解决方案。

提示:

  • 如果你不确定应该为字体传递哪些粗细选项,可以检查代码编辑器中的 TypeScript 错误。
  • 访问 Google Fonts 网站,搜索 Lusitana 以查看可用选项。
  • 查看有关添加多种字体的文档以及完整的选项列表

建议先自己动手试一试进行实现, 之后再看解决方案

解决方案

// /app/ui/fonts.ts
import { Inter, Lusitana } from 'next/font/google';
 
export const inter = Inter({ subsets: ['latin'] });
 
export const lusitana = Lusitana({
  weight: ['400', '700'],
  subsets: ['latin'],
});
// /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';
 
export default function Page() {
  return (
    // ...
    <p
      className={`${lusitana.className} text-xl text-gray-800 md:text-3xl md:leading-normal`}
    >
      <strong>Welcome to Acme.</strong> This is the example for the{' '}
      <a href="https://nextjs.org/learn/" className="text-blue-500">
        Next.js Learn Course
      </a>
      , brought to you by Vercel.
    </p>
    // ...
  );
}

最后,<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>
  );
}

好的,你已经为应用程序添加了两种自定义字体!接下来,让我们为主页添加一个主图。

为什么要优化图像?

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

使用常规 HTML 时,你可以如下添加图像:

<img src="/hero.png" alt="显示桌面版本仪表板项目的屏幕截图"/>

然而,这意味着你必须手动:

  • 确保图像在不同屏幕尺寸下具有响应性。
  • 为不同设备指定图像尺寸。
  • 防止图像加载时出现布局偏移。
  • 对视口外的图像进行延迟加载。

图像优化是 Web 开发中的一个重要话题,甚至可以被视为一种专门化的领域。你可以使用 next/image 组件来自动优化图像,而不是手动实现这些优化。

<Image> 组件

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

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

添加桌面主图

让我们使用 <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">
      {/* 在此处添加主图 */}
      <Image
        src="/hero-desktop.png"
        width={1000}
        height={760}
        className="hidden md:block"
        alt="显示桌面版本仪表板项目的屏幕截图"
      />
    </div>
    // ...
  );
}

在这里,你将图像的 width 设置为 1000 像素,height 设置为 760 像素。为了避免布局偏移,最好为图像设置宽度和高度,并确保这些比例与源图像的宽高比 相同

你还会注意到 hidden 类将图像从移动屏幕的 DOM 中移除,而 md:block 类在桌

面屏幕上显示图像。

你的主页现在应该如下所示:

image

练习: 添加移动端主图

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

  • 该图像的 width 应为 560 像素,height620 像素。
  • 它应在移动屏幕上显示,在桌面上隐藏——你可以使用开发者工具检查桌面和移动图像是否正确切换。

当你准备好后,再看以下代码段查看解决方案。

// /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"
      />
      <Image
        src="/hero-mobile.png"
        width={560}
        height={620}
        className="block md:hidden"
        alt="Screenshot of the dashboard project showing mobile version"
      />
    </div>
    //...
  );
}

很好!你的主页现在有了自定义字体和主图。

是时候进行测验了!

测试一下刚刚学到的内容。

True or False: 没有指定尺寸的图像和 Web 字体是导致布局偏移的常见原因。

A. True B. False

检查答案

推荐阅读

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

image
EchoEcho官方
无论前方如何,请不要后悔与我相遇。
1377
发布数
439
关注者
2223120
累计阅读

热门教程文档

Python
76小节
MySQL
34小节
Golang
23小节
React Native
40小节
Javascript
24小节