如何在 Next.js 中使用静态资源(图片、字体等)?
在 Next.js 中处理静态资源(如图片、字体、图标等)主要有两种方式:使用 public 文件夹 和 通过模块导入(Import)。
为了获得最佳的性能(如自动压缩、防止布局偏移),Next.js 推荐尽可能使用其内置的优化组件(如 next/image 和 next/font)。
以下是详细的指南:
1. 使用 public 文件夹 (最基础的方式)
Next.js 在根目录下有一个 public 文件夹。放在这里的任何文件都可以通过根 URL 直接访问。
- 适用场景:
robots.txt、favicon.ico、不需要优化的静态图片、或者需要在 HTML<head>中引用的脚本。 - 路径规则: 代码中引用时,不需要 写
/public,直接从/开始。
示例:
假设文件结构为 public/logo.png。
import Image from 'next/image';
export default function Page() {
return (
<div>
{/* 使用标准 HTML img 标签 (不推荐用于大图,无优化) */}
<img src="/logo.png" alt="Logo" />
{/* 使用 Next.js Image 组件 (推荐) */}
<Image
src="/logo.png"
alt="Logo"
width={100}
height={100}
/>
</div>
);
}
2. 图片优化:使用 next/image
Next.js 提供了 <Image /> 组件来替代标准的 <img> 标签。它会自动处理图片压缩、格式转换(如转为 WebP/AVIF)、懒加载(Lazy Loading)和防止布局偏移(CLS)。
A. 导入本地图片 (推荐)
将图片放在 app 或 src 目录下的组件文件夹中,直接 import。
- 优点: Next.js 会自动确定图片的
width和height,防止布局偏移。
// 1. 导入图片文件
import profilePic from './profile.jpg';
import Image from 'next/image';
export default function Profile() {
return (
<Image
src={profilePic} // 2. 直接传入导入的对象
alt="作者头像"
// placeholder="blur" // 可选:加载时显示模糊占位符
/>
);
}
B. 使用远程图片 (URL)
如果图片来自外部服务器(如 AWS S3、Cloudinary),你需要手动指定宽高,并在配置文件中允许该域名。
代码中使用:
import Image from 'next/image';
export default function Page() {
return (
<Image
src="https://example.com/my-image.jpg"
alt="远程图片"
width={500}
height={300}
/>
);
}
配置 (next.config.js):
为了安全起见,必须在配置中添加允许的图片域名:
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
},
],
},
};
3. 字体优化:使用 next/font
Next.js 13+ 引入了 next/font,它会在构建时下载字体并将其托管在你的服务器上(即使是 Google Fonts),从而消除向 Google 发送请求的隐私问题和网络延迟。
A. 使用 Google Fonts
// app/layout.js (或 .tsx)
import { Inter } from 'next/font/google';
// 配置字体 (subsets 必填,减少文件体积)
const inter = Inter({ subsets: ['latin'] });
export default function RootLayout({ children }) {
return (
<html lang="en">
{/* 将字体类名应用到 body */}
<body className={inter.className}>{children}</body>
</html>
);
}
B. 使用本地字体文件
如果你的字体文件(.woff2, .ttf)在本地:
// app/layout.js
import localFont from 'next/font/local';
// 配置本地字体路径
const myFont = localFont({
src: './fonts/my-custom-font.woff2',
display: 'swap',
});
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={myFont.className}>{children}</body>
</html>
);
}
4. 特殊元数据文件 (App Router)
在 Next.js 的 App Router (app/ 目录) 中,你可以通过放置特定命名的文件来自动处理静态资源,而无需手动在 <head> 中编写代码。
将以下文件直接放在 app/ 根目录下:
favicon.ico,icon.png: 网站图标。opengraph-image.png: 社交媒体分享时的预览图。robots.txt: 搜索引擎爬虫规则。sitemap.xml: 站点地图。
Next.js 会自动识别这些文件并生成相应的 <link> 或 <meta> 标签。
总结:最佳实践
| 资源类型 | 推荐方式 | 理由 |
|---|---|---|
| 图片 (本地) | import + next/image |
自动宽高检测、压缩、模糊占位符。 |
| 图片 (远程) | URL + next/image |
自动优化格式和尺寸,需配置域名。 |
| 字体 | next/font |
零布局偏移,自动托管,无外部请求。 |
| Favicon/OG图 | 放入 app/ 目录 |
利用 App Router 的文件约定自动生成元数据。 |
| 通用静态文件 | public/ 文件夹 |
用于 robots.txt 或不需要处理的原始文件。 |