Next14 最佳实践系列【来自官方标准】-第3章 优化字体和图像

  1. 一二章传送门:Next14 最佳实践系列文章-第一、二章
  2. 切记:只要能坚持下来,对前端领域的认知会有一个质的飞跃。现在是基础阶段,之所谓万丈高楼平地起,地基很重要。
  3. 有点小伙伴问为啥要这么创建文件目录结构,跟我原来学的不一样。有这个疑问是好的,请带着这个疑问,跟着教程走,学完自己体会。我也在最后做详解。

这一章节,可以学到:

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

为什么要字体优化?

字体在网站设计中发挥着重要作用,但如果需要获取和加载字体文件,在项目中使用自定义字体可能会影响性能。字体优化是必然的,现有框架中做的最好的也就是Next.js

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

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


添加主要字体

添加自定义Google字体。在/app/ui文件夹中,创建一个名为fonts.ts的新文件。此文件用来保留程序中所使用的字体。

next/font/google模块中导入Inter字体-这个将是程序的主要字体。相应的,指定对应的哪个子集即可,如'latin':

javascript 复制代码
import { Inter } from 'next/font/google';
 
export const inter = Inter({ subsets: ['latin'] });

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

javascript 复制代码
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。加了这个类增加观感度,增强用户体验。读者可运行后自行体验。


练习:增加另一个辅助字体

可以将字体添加到指定的元素。现在增加一个Lusitana的辅助字体到 /app/page.tsx文件中的<p> 元素。除了指定子集之外,还需要指定字体的粗细。

注:先自己实现,然后看答案。跟着思路练习,不要眼高手低。感觉看会了,自己写不出来。编程就是这样,是一门理论加实践的学科,贵在练习。

点击查看解决方案

javascript 复制代码
import { Inter, Lusitana } from 'next/font/google';

export const inter = Inter({ subsets: ['latin'] });

export const lusitana = Lusitana({
  weight: ['400', '700'],
  subsets: ['latin'],
});
javascript 复制代码
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。可以将代码注释去调。

javascript 复制代码
// ...
 
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中添加/public中的静态资源-图像:

ini 复制代码
<img
  src="/hero.png"
  alt="Screenshots of the dashboard project showing desktop version"
/>

但是,这意味着必须手动处理:

  • 图像在不同屏幕上是响应式的
  • 指定不同设备的图像尺寸
  • 防止图像加载时布局发生变化
  • 延迟加载用户视口之外的图像

图像优化是Web开发中的一个大的主题,其本身就是一个专业领域。如此,next/image组件提供极致的自动优化功能,而我们不用自己费劲巴拉的自己实现这些优化。


组件

<Image>组件是HTML元素<img>标签的扩展,并且具有自动图像优化功能,如:

  • 加载图像时自动防止布局移动
  • 调整图像大小从而避免不适配不同设备视口
  • 默认情况下延迟加载图像(图像在进入视口时加载)
  • 当浏览器支持时,提供现代格式图像,如 WebP 和 AVIF

添加图像到桌面

先在让我们使用一下<Image>组件。查看/public文件夹,里面有两个图像:hero-desktop.pnghero-mobile.png。分别是移动端还有PC端。

/app/page.tsx文件夹中,从 next/image导入组件:

javascript 复制代码
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>
    //...
  );
}

代码中,宽度设置为1000px,高度设置为760px。最好设置图像的宽度和高度以避免布局移位,并且宽高比应该与源图像相同。

你可能还注意到隐藏类hidden 用于在移动端不展示此DOM元素,以及类md:block用于在桌面上展示。这些事Tailwind语法,可以看下官网大致了解一下。

现在主页的样子应如下图:


练习:添加移动端的主图

练习一下,将移动端的图片加入进来:

  • 该图像为宽560px,高620px
  • 在移动端展示,桌面端隐藏

点击查看答案

javascript 复制代码
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>
    //...
  );
}

现在已经完成了字体与图像的模块学习。

相关推荐
柳叶寒2 天前
医院信息化与智能化系统(17)
java·nacos·gateway·全栈·项目
柳叶寒6 天前
医院信息化与智能化系统(15)
java·数据库·全栈·项目
kevinyan8 天前
Go项目Error的统一规划管理和处理策略
前端·go·全栈
柳叶寒13 天前
医院信息化与智能化系统(8)
java·数据库·全栈·项目
柳叶寒15 天前
医院信息化与智能化系统(6)
java·全栈·项目
余生H15 天前
前端全栈混合之路Deno篇:Deno2.0如何快速创建http一个 restfulapi/静态文件托管应用及oak框架介绍
javascript·http·restful·全栈·deno
kevinyan16 天前
Go日志门面的设计与实现-自动注入追踪ID标记代码位置、简化日志操作
vue.js·go·全栈
柳叶寒17 天前
医院信息化与智能化系统(5)
java·数据库·全栈
余生H21 天前
大模型进阶微调篇(一):以定制化3B模型为例,各种微调方法对比-选LoRA还是PPO,所需显存内存资源为多少?
人工智能·深度学习·机器学习·全栈·模型微调
前端斌少21 天前
Meteor:全栈JavaScript开发框架的先驱
前端·全栈