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>
    //...
  );
}

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

相关推荐
灰飞肥鱼9 天前
DataGrip 查询TDengine时区问题
全栈
萌萌哒草头将军9 天前
🚀🚀🚀 神了!RedwoodJS 轻松碾压 NextJS,成了我的最爱❤️
前端·react.js·全栈
M1A111 天前
全栈开发必备:Windows安装VS Code全流程
前端·后端·全栈
小厂永远得不到的男人11 天前
基于 Trae 的 WebSocket 聊天室保姆级教程(超详细版)
websocket·全栈·trae
ci0n15 天前
PVE 网卡冗余配置
全栈
不想说话的麋鹿16 天前
「项目实战」从0搭建NestJS后端服务(八):静态资源访问以及文件上传
前端·node.js·全栈
hboot19 天前
rust 全栈应用框架dioxus
前端·rust·全栈
林夕112019 天前
Node.js Web开发进阶:Stream、HTTP模块与文件上传全解析
前端·node.js·全栈
天天扭码20 天前
用一个项目揭开AI全栈的神秘面纱——让AI根据你的项目数据生成回答
openai·ai编程·全栈
Edward-tan20 天前
【玩转全栈】—— Django+vue3+讯飞星火API 实现前端页面实时AI答复
vue3·全栈·django5