Next.js 图片优化:使用 next/image 提升网站性能
作者:码力无边
在构建现代 Web 应用时,我们往往会花费大量精力在优化 JavaScript 包大小、改进数据获取策略上,但常常忽略了一个最常见、也最容易拖慢网站速度的元凶——图片。一张未经优化的巨型图片,其体积可能比你整个应用的所有 JavaScript 代码加起来还要大。
传统的图片处理方式,即简单地使用 <img> 标签,会带来一系列性能噩梦:
- 巨大的文件体积:开发者可能无意中将一张几 MB 大的原始图片直接用于网页,导致用户(尤其是移动端用户)需要消耗大量流量和时间来下载。
- 不合适的图片格式:你可能还在使用 JPG 或 PNG,而现代浏览器早已支持像 WebP 这样压缩效率更高、体积更小的下一代图片格式。
- 布局偏移 (Layout Shift):浏览器在加载图片之前不知道其确切尺寸,当图片最终加载完成时,会把周围的文本“推开”,造成页面内容的跳动。这是谷歌 Core Web Vitals (核心网页指标) 中一项非常糟糕的用户体验指标 (CLS)。
- 加载非必要资源:页面上所有
<img>标签都会在页面加载时立即开始下载,即使是那些用户需要滚动很久才能看到的图片,这严重拖慢了首屏加载速度。
手动解决以上所有问题是一项极其繁琐的工作。你需要使用图像编辑工具压缩图片、转换格式、为不同屏幕尺寸准备多个版本的图片,并手动实现懒加载…
幸运的是,Next.js 提供了一个“核武器”级别的解决方案:<Image> 组件。它是一个内置的、功能强大的 <img> 标签替代品,通过一系列自动化优化,让你无需成为性能专家,也能轻松解决上述所有问题。
next/image 的魔力:它在背后做了什么?
当你使用 <Image> 组件时,Next.js 在背后为你执行了一套复杂的优化流程:
- 按需调整尺寸 (On-demand Resizing):Next.js 会根据你在代码中提供的
width和height属性,在服务器端自动生成一系列优化过的、不同尺寸的图片。它会根据用户的设备(手机、平板、桌面)提供最合适尺寸的版本,而不是将原始大图发送给所有人。 - 现代格式转换 (Modern Formats):在请求时,Next.js 会检测用户的浏览器是否支持 WebP 或 AVIF 等现代格式。如果支持,它会自动提供这些格式的图片,它们的体积通常比 JPG/PNG 小 20-50%,如果不支持,则优雅地降级为原始格式。
- 防止布局偏移:由于你必须提供
width和height,Next.js 可以在图片加载前就在页面上为其预留出准确的空间,从而彻底消除布局偏移。 - 默认懒加载 (Lazy Loading by Default):只有当图片即将滚动到用户的视口 (viewport) 时,它才会被加载。这极大地减少了页面的初始加载负载,提升了 LCP (Largest Contentful Paint) 指标。
- 自动缓存:优化过的图片会被 Next.js 服务器缓存起来。下一次对同样尺寸和格式的图片请求会直接命中缓存,响应极快。
这一切,你几乎是“免费”获得的。
如何使用 next/image
使用 <Image> 组件非常简单,只需从 next/image 导入即可。我们主要关注两种引用图片的方式。
1. 静态导入 (Static Import) - 推荐方式
当你的图片文件就存放在项目代码中时(例如在 public 目录下,或者更推荐的,与组件放在一起),这是最简单、最安全的方式。
文件结构:
my-app/
├── public/
│ └── images/
│ └── profile.jpg
├── pages/
│ └── about.tsx
└── ...
pages/about.tsx
import Image from 'next/image';
// 像导入一个模块一样导入你的图片
import profilePic from '../public/images/profile.jpg';
export default function AboutPage() {
return (
<div>
<h1>关于我</h1>
<Image
src={profilePic}
alt="作者的头像"
// 对于静态导入的图片,width 和 height 会被自动识别
// 但为了代码清晰和类型安全,写上是个好习惯
width={500}
height={500}
// 添加模糊占位图效果,提升体验
placeholder="blur"
/>
<p>...</p>
</div>
);
}
优势:Next.js 在构建时就能分析这张图片,自动获取其尺寸,甚至生成一个极小的 blurDataURL 用于模糊占位图效果,体验极佳。
2. 远程图片 (Remote Images)
当你的图片存放在外部 CDN、Headless CMS 或任何其他服务器上时,你需要直接提供图片的 URL 字符串。
重要:出于安全考虑,为了防止恶意用户滥用你的图片优化服务,你必须在 next.config.js 文件中明确配置允许的远程图片域名。
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.unsplash.com', // 允许来自这个域名的图片
port: '',
pathname: '/**',
},
{
protocol: 'https',
hostname: 'cdn.my-cms.com',
}
],
},
}
module.exports = nextConfig
在组件中使用
import Image from 'next/image';
export default function BlogPost({ post }) {
return (
<article>
<h1>{post.title}</h1>
<Image
src={post.imageUrl} // 这是一个远程 URL
alt={post.title}
// 对于远程图片,你必须手动提供 width 和 height
width={800}
height={600}
/>
<div>{post.content}</div>
</article>
);
}
next/image 的高级属性与技巧
掌握了基础用法后,以下这些属性将让你对图片布局的控制更上一层楼。
priority - 优化首屏关键图片
默认的懒加载非常棒,但不适用于所有情况。对于页面的“首屏”或“折叠之上” (above-the-fold) 的关键图片,例如首页的英雄横幅 (Hero Banner),我们希望它能被尽快加载。
为这张图片添加 priority 属性,会告诉 Next.js:
- 禁用懒加载。
- 在 HTML 头部添加
<link rel="preload">标签,让浏览器优先下载这张图片。
<Image
src={heroBanner}
alt="网站横幅"
width={1920}
height={1080}
priority // 关键!
/>
fill 和 sizes - 构建响应式布局
有时候,我们并不知道图片的确切尺寸,只希望它能“填满”其父容器。这时可以使用 fill 属性。
使用 fill 时:
- 不需要
width和height属性。 - 其直接父元素必须设置
position: relative、position: fixed或position: absolute。 - 通常需要配合
object-fitCSS 属性来控制图片的填充方式。
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
<Image
src="/card-background.jpg"
alt="背景图"
fill
style={{ objectFit: 'cover' }}
/>
</div>
sizes 属性则更进一步,它告诉浏览器在不同的视口宽度下,图片预期会占据多大的宽度。这能帮助 Next.js 更智能地提供最接近尺寸的图片版本,从而节省带宽。
<Image
src="/avatar.jpg"
alt="头像"
width={300}
height={300}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
解读 sizes:
- 当屏幕宽度小于 768px 时,图片宽度为屏幕宽度的 100%。
- 当屏幕宽度在 768px 和 1200px 之间时,图片宽度为屏幕宽度的 50%。
- 其他情况下,图片宽度为屏幕宽度的 33%。
总结
<Image> 组件是 Next.js 性能优化工具箱中最直观、最有效的工具之一。它将前端领域中一个复杂且耗时的话题——图片优化——变成了一个简单的组件调用。
核心要点回顾:
- 始终用
<Image>替代<img>:这是最重要的一条规则。 - 优先使用静态导入:让 Next.js 为你自动处理更多事情。
- 配置远程域名:使用远程图片时,务必在
next.config.js中添加白名单。 - 标记关键图片:为首屏图片添加
priority属性。 - 掌握响应式布局:善用
fill和sizes属性来处理不确定尺寸的图片。
正确地使用 <Image> 组件,能让你的网站在 Core Web Vitals 测试中获得显著的提升,为用户带来更流畅、更快速的浏览体验。
现在,我们的应用不仅功能完备,图片资源也得到了极致优化。在接下来的文章中,我们将继续探索 Next.js 的其他内置优化功能,例如字体和第三方脚本的优化。敬请期待!
593

被折叠的 条评论
为什么被折叠?



