Next-js第十三课 - 字体优化

6 阅读3分钟

上节我们学习了图片优化,本节来聊聊字体优化。字体对网页的视觉效果和加载速度都有很大影响,Next.js 提供了优秀的字体优化方案。

字体优化概述

Next.js 13+ 内置 next/font,提供:

  1. 自动字体优化 - 自动托管和优化字体文件
  2. 零布局偏移 - 使用 CSS size-adjust
  3. 隐私友好 - 不向 Google 发送请求
  4. 自动自托管 - 字体文件与构建一起部署

使用 Google Fonts

基本用法

// app/layout.tsx
import { Inter } from 'next/font/google'

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

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="zh-CN" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}

多个字体

import { Inter, Playfair_Display } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
})

const playfair = Playfair_Display({
  subsets: ['latin'],
  variable: '--font-playfair',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="zh-CN">
      <body className={`${inter.variable} ${playfair.variable}`}>
        {children}
      </body>
    </html>
  )
}

使用本地字体

基本 Local Font

import localFont from 'next/font/local'

const myFont = localFont({
  src: './my-font.woff2',
  display: 'swap',
})

export default function Page() {
  return <div className={myFont.className}>内容</div>
}

多字重本地字体

import localFont from 'next/font/local'

const myFont = localFont({
  src: [
    {
      path: './my-font-regular.woff2',
      weight: '400',
      style: 'normal',
    },
    {
      path: './my-font-bold.woff2',
      weight: '700',
      style: 'normal',
    },
  ],
  display: 'swap',
})

字体显示策略

font-display 属性控制字体加载时的行为:

const inter = Inter({
  subsets: ['latin'],
  display: 'swap', // 可选值:auto, block, swap, fallback, optional
})

不同策略的说明:

  • auto - 浏览器默认行为
  • block - 短暂隐藏文本,直到字体加载
  • swap - 立即显示后备字体,字体加载后替换
  • fallback - 短暂隐藏文本,超时后使用后备字体
  • optional - 短暂隐藏文本,超时后使用后备字体(不会替换)

响应式字体

使用 CSS 变量实现响应式字体:

import { Inter } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="zh-CN">
      <body className={inter.variable}>
        {children}
      </body>
    </html>
  )
}
/* globals.css */
body {
  font-family: var(--font-inter), sans-serif;
}

常见字体配置

中英文混排

import { Inter } from 'next/font/google'
import { Noto_Sans_SC } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
})

const notoSansSC = Noto_Sans_SC({
  subsets: ['chinese'],
  variable: '--font-noto-sans-sc',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="zh-CN">
      <body className={`${inter.variable} ${notoSansSC.variable}`}>
        {children}
      </body>
    </html>
  )
}

代码字体

import { Fira_Code } from 'next/font/google'

const firaCode = Fira_Code({
  subsets: ['latin'],
  variable: '--font-fira-code',
})

export default function CodeBlock({ code }) {
  return (
    <pre className={firaCode.variable}>
      <code>{code}</code>
    </pre>
  )
}

字体性能优化

预加载关键字体

const inter = Inter({
  subsets: ['latin'],
  preload: true, // 默认 true
})

限制字重

只加载需要的字重能大幅减少字体文件大小:

// 好:只加载需要的字重
const inter = Inter({
  subsets: ['latin'],
  weight: ['400', '600', '700'],
})

子集优化

只加载需要的字符集:

// 好:只加载简体中文字符
const notoSansSC = Noto_Sans_SC({
  subsets: ['chinese-simplified'],
})

实用建议

这里分享几个在字体优化时特别有用的技巧。

使用 next/font

实际开发中,我发现使用 next/font 比传统方式要好很多:

// 推荐这样做 - 使用 next/font
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })

// 传统方式虽然也可以,但功能不如 next/font
<link href="https://fonts.googleapis.com/css2?family=Inter&display=swap" rel="stylesheet">

限制字体数量

这里有个小建议:使用过多字体会影响性能,建议整个项目只使用 2-3 个字体。

选择合适的显示策略

这个技巧在实际项目中特别有用——根据使用场景选择合适的显示策略:

  • 正文文本建议使用 swap,避免文字不可见
  • Logo/标题可以使用 block,保持设计一致性

总结

本节我们学习了 Next.js 的字体优化功能,包括 Google Fonts、本地字体、字体显示策略等。使用 next/font 能自动优化字体加载,消除布局偏移,提升用户体验。

如果你对本节内容有任何疑问,欢迎在评论区提出来,我们一起学习讨论。

原文地址:blog.uuhb.cn/archives/ne…