Menu

如何优化图片和字体

Next.js 提供了自动图片和字体优化功能。本页将指导你如何开始使用它们。

优化图片

Next.js 的 <Image> 组件扩展了 HTML <img> 元素,提供以下功能:

  • 尺寸优化: 自动为每个设备提供正确大小的图片,使用现代图片格式如 WebP。
  • 视觉稳定性: 在图片加载时自动防止布局偏移
  • 更快的页面加载: 使用浏览器原生懒加载功能,仅在图片进入视口时加载,可选模糊占位符。
  • 资源灵活性: 按需调整图片大小,甚至包括存储在远程服务器上的图片。

要开始使用 <Image>,从 next/image 导入它并在你的组件中渲染它。

app/page.tsx
TypeScript
import Image from 'next/image'
 
export default function Page() {
  return <Image src="" alt="" />
}

src 属性可以是本地图片远程图片

本地图片

你可以在根目录下名为 public 的文件夹中存储静态文件,如图片和字体。public 内的文件可以通过从基本 URL(/)开始的代码引用。

显示 app 和 public 文件夹的文件夹结构
app/page.tsx
TypeScript
import Image from 'next/image'
import profilePic from './me.png'
 
export default function Page() {
  return (
    <Image
      src={profilePic}
      alt="作者的照片"
      // width={500} 自动提供
      // height={500} 自动提供
      // blurDataURL="data:..." 自动提供
      // placeholder="blur" // 可选的加载时模糊效果
    />
  )
}

Next.js 将根据导入的文件自动确定图片的固有 widthheight。这些值用于确定图片比例并防止图片加载时的累积布局偏移

远程图片

要使用远程图片,你可以为 src 属性提供一个 URL 字符串。

app/page.tsx
TypeScript
import Image from 'next/image'
 
export default function Page() {
  return (
    <Image
      src="https://s3.amazonaws.com/my-bucket/profile.png"
      alt="作者的照片"
      width={500}
      height={500}
    />
  )
}

由于 Next.js 在构建过程中无法访问远程文件,你需要手动提供 widthheight 和可选的 blurDataURL 属性。widthheight 用于推断图片的正确宽高比并避免图片加载时的布局偏移。

要安全地允许来自远程服务器的图片,你需要在 next.config.js 中定义支持的 URL 模式列表。尽可能具体,以防止恶意使用。例如,以下配置将只允许来自特定 AWS S3 存储桶的图片:

next.config.ts
TypeScript
import { NextConfig } from 'next'
 
const config: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 's3.amazonaws.com',
        port: '',
        pathname: '/my-bucket/**',
        search: '',
      },
    ],
  },
}
 
export default config

优化字体

next/font 模块自动优化你的字体并移除外部网络请求,以提高隐私性和性能。

它包括内置的自托管功能,适用于任何字体文件。这意味着你可以以最佳方式加载网络字体,且没有布局偏移。

要开始使用 next/font,从 next/font/localnext/font/google 导入它,以适当的选项调用它作为函数,并设置你想应用字体的元素的 className。例如:

app/layout.tsx
TypeScript
import { Geist } from 'next/font/google'
 
const geist = Geist({
  subsets: ['latin'],
})
 
export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={geist.className}>
      <body>{children}</body>
    </html>
  )
}

Google 字体

你可以自动自托管任何 Google 字体。字体包含在部署中,并从与你的部署相同的域名提供服务,这意味着当用户访问你的网站时,浏览器不会向 Google 发送请求。

要开始使用 Google 字体,从 next/font/google 导入你选择的字体:

app/layout.tsx
TypeScript
import { Geist } from 'next/font/google'
 
const geist = Geist({
  subsets: ['latin'],
})
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={geist.className}>
      <body>{children}</body>
    </html>
  )
}

我们建议使用可变字体以获得最佳性能和灵活性。但如果你不能使用可变字体,则需要指定字重:

app/layout.tsx
TypeScript
import { Roboto } from 'next/font/google'
 
const roboto = Roboto({
  weight: '400',
  subsets: ['latin'],
})
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={roboto.className}>
      <body>{children}</body>
    </html>
  )
}

本地字体

要使用本地字体,从 next/font/local 导入你的字体,并指定本地字体文件的 src

app/layout.tsx
TypeScript
import localFont from 'next/font/local'
 
const myFont = localFont({
  src: './my-font.woff2',
})
 
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',
    },
  ],
})