Skip to main content

字体优化

next/font 将自动优化您的字体(包括自定义字体),并删除外部网络请求,以提高隐私和性能。

🎥 观看:学习如何使用 next/font → YouTube (6分钟)

next/font 包含内置的字体自托管功能,可用于任何字体文件。 这意味着您可以通过底层的 CSS size-adjust 属性,以零布局移位的方式最优加载Web字体。

这个新的字体系统还允许您方便地在考虑性能和隐私的情况下使用所有 Google 字体。 在构建时下载 CSS 和字体文件,并与其余静态资产一起自托管。浏览器不会向 Google 发送任何请求。

Google 字体

自动自托管任何 Google 字体。字体包含在部署中,并从与您的部署相同的域提供。浏览器不会向 Google 发送任何请求。

next/font/google 中导入您想要使用的字体,作为一个函数开始。我们建议使用可变字体以获得最佳性能和灵活性。

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

// 如果加载可变字体,您不需要指定字体粗细
const inter = Inter({
subsets: ['latin'],
display: 'swap',
})

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

如果不能使用可变字体,您需要指定一个权重

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

const roboto = Roboto({
weight: '400',
subsets: ['latin'],
display: 'swap',
})

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

您可以通过使用数组指定多个权重和/或样式:

app/layout.js
const roboto = Roboto({
weight: ['400', '700'],
style: ['normal', 'italic'],
subsets: ['latin'],
display: 'swap',
})
note

对于具有多个单词的字体名称,请使用下划线 (_)。例如,Roboto Mono 应该被导入为 Roboto_Mono

指定子集

Google 字体会自动进行子集化。这会减小字体文件的大小并提高性能。 您需要定义要预加载的这些子集。在 preloadtrue 时,未指定任何子集会导致警告。

这可以通过将其添加到函数调用中来完成:

app/layout.tsx
const inter = Inter({ subsets: ['latin'] })

查看 Font API 参考 以获取更多信息。

使用多个字体

您可以在应用程序中导入和使用多个字体。有两种方法可以采用。

第一种方法是创建一个实用程序函数,导出一个字体,导入它,并在需要的地方应用其 className。这确保字体仅在渲染时预加载:

app/fonts.ts
import { Inter, Roboto_Mono } from 'next/font/google'

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

export const roboto_mono = Roboto_Mono({
subsets: ['latin'],
display: 'swap',
})
app/layout.tsx
import { inter } from './fonts'

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={inter.className}>
<body>
<div>{children}</div>
</body>
</html>
)
}
app/page.tsx
import { roboto_mono } from './fonts'

export default function Page() {
return (
<>
<h1 className={roboto_mono.className}>My page</h1>
</>
)
}

在上面的示例中,Inter 将全局应用,而 Roboto Mono 可以在需要时导入和应用。

或者,您可以创建一个 CSS 变量,并使用您喜欢的 CSS 解决方案:

app/layout.tsx
import { Inter, Roboto_Mono } from 'next/font/google'
import styles from './global.css'

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

const roboto_mono = Roboto_Mono({
subsets: ['latin'],
variable: '--font-roboto-mono',
display: 'swap',
})

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className={`${inter.variable} ${roboto_mono.variable}`}>
<body>
<h1>My App</h1>
<div>{children}</div>
</body>
</html>
)
}
app/global.css
html {
font-family: var(--font-inter);
}

h1 {
font-family: var(--font-roboto-mono);
}

在上面的示例中,Inter 将全局应用,任何 <h1> 标签都将使用 Roboto Mono 进行样式化。

note

谨慎使用多个字体,因为每个新字体都是客户端必须下载的额外资源。

本地字体

导入 next/font/local 并指定本地字体文件的 src。我们建议使用可变字体以获得最佳性能和灵活性。

app/layout.tsx
import localFont from 'next/font/local'

// 字体文件可以放置在 `app` 中
const myFont = localFont({
src: './my-font.woff2',
display: 'swap',
})

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

如果要为单个字体系列使用多个文件,src 可以是一个数组:

const roboto = localFont({
src: [
{
path: './Roboto-Regular.woff2',
weight: '400',
style: 'normal',
},
{
path: './Roboto-Italic.woff2',
weight: '400',
style: 'italic',
},
{
path: './Roboto-Bold.woff2',
weight: '700',
style: 'normal',
},
{
path: './Roboto-BoldItalic.woff2',
weight: '700',
style: 'italic',
},
],
})

查看 Font API 参考 以获取更多信息。

与 Tailwind CSS 一起使用

通过 CSS 变量,next/font 可以与 Tailwind CSS 一起使用。

在下面的示例中,我们使用了来自 next/font/google 的字体 Inter(您可以使用来自 Google 或本地字体的任何字体)。 使用 variable 选项加载字体以定义您的 CSS 变量名称,并将其分配给 inter。 然后,使用 inter.variable 将 CSS 变量添加到您的 HTML 文档中。

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

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

const roboto_mono = Roboto_Mono({
subsets: ['latin'],
display: 'swap',
variable: '--font-roboto-mono',
})

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

最后,在您的 Tailwind CSS 配置中添加 CSS 变量:

tailwind.config.js
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
'./app/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
fontFamily: {
sans: ['var(--font-inter)'],
mono: ['var(--font-roboto-mono)'],
},
},
},
plugins: [],
}

现在,您可以使用 font-sansfont-mono 实用程序类将字体应用于您的元素。

预加载

当在站点的页面上调用字体函数时,它不会在所有路由上全局可用和预加载。 相反,该字体仅在相关路由上预加载,这取决于它在使用它的文件类型:

  • 如果是唯一的页面,则会在该页面的唯一路由上预加载。
  • 如果是布局,则会在由布局包装的所有路由上预加载。
  • 如果是根布局,则会在所有路由上预加载。

重用字体

每次调用 localFont 或 Google 字体函数时,该字体都作为应用程序中的一个实例进行托管。 因此,如果在多个文件中加载相同的字体函数,则会托管相同字体的多个实例。在这种情况下,建议执行以下操作:

  • 在一个共享文件中调用字体加载器函数
  • 将其导出为常量
  • 在每个要使用此字体的文件中导入该常量