Next.js 图像优化
概述
Next.js 提供了强大的图像优化功能,通过内置的 Image 组件自动优化图像,提升网站性能和用户体验。
🎯 为什么需要图像优化?
图像对性能的影响
javascript
// 传统 HTML 图像标签的问题
<img src="/large-image.jpg" alt="大图" />
// ❌ 不会自动优化
// ❌ 不会响应式调整
// ❌ 可能导致布局偏移
// ❌ 加载速度慢Next.js Image 组件的优势
- 自动优化:自动转换为现代格式(WebP、AVIF)
- 响应式:根据设备自动调整大小
- 懒加载:视口外的图像延迟加载
- 防止布局偏移:预留空间避免 CLS
- 按需优化:首次请求时优化,然后缓存
📦 Image 组件基础
基本使用
jsx
import Image from 'next/image';
export default function ProfilePage() {
return (
<div>
<h1>用户资料</h1>
{/* 本地图像 */}
<Image
src="/profile.jpg"
alt="用户头像"
width={500}
height={500}
/>
{/* 远程图像 */}
<Image
src="https://example.com/photo.jpg"
alt="照片"
width={800}
height={600}
/>
</div>
);
}必需属性
jsx
function ImageExample() {
return (
<Image
src="/image.jpg" // 图像路径(必需)
alt="描述文本" // 替代文本(必需)
width={800} // 宽度(必需,除非 fill)
height={600} // 高度(必需,除非 fill)
/>
);
}🖼️ 本地图像
导入本地图像
jsx
import Image from 'next/image';
import profilePic from '../public/profile.jpg';
export default function Profile() {
return (
<div>
{/* 自动获取宽高 */}
<Image
src={profilePic}
alt="用户头像"
placeholder="blur" // 自动模糊占位符
/>
</div>
);
}静态导入的优势
jsx
import heroImage from '@/public/hero.jpg';
// ✅ 自动获取尺寸
// ✅ 自动生成模糊占位符
// ✅ 防止布局偏移
export default function Hero() {
return (
<Image
src={heroImage}
alt="英雄图"
priority // 优先加载
/>
);
}🌐 远程图像
配置远程图像域名
javascript
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
port: '',
pathname: '/images/**',
},
{
protocol: 'https',
hostname: 'cdn.example.com',
},
],
},
};使用远程图像
jsx
import Image from 'next/image';
export default function Gallery() {
const images = [
'https://example.com/images/photo1.jpg',
'https://example.com/images/photo2.jpg',
'https://example.com/images/photo3.jpg',
];
return (
<div className="gallery">
{images.map((src, index) => (
<Image
key={index}
src={src}
alt={`照片 ${index + 1}`}
width={400}
height={300}
/>
))}
</div>
);
}🎨 响应式图像
使用 fill 属性
jsx
import Image from 'next/image';
export default function ResponsiveImage() {
return (
<div style={{ position: 'relative', width: '100%', height: '400px' }}>
<Image
src="/banner.jpg"
alt="横幅"
fill
style={{ objectFit: 'cover' }}
/>
</div>
);
}sizes 属性优化
jsx
export default function ResponsiveGallery() {
return (
<div className="container">
<Image
src="/photo.jpg"
alt="照片"
width={800}
height={600}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</div>
);
}⚡ 性能优化
优先加载关键图像
jsx
export default function HomePage() {
return (
<div>
{/* 首屏图像 - 优先加载 */}
<Image
src="/hero.jpg"
alt="英雄图"
width={1200}
height={600}
priority
/>
{/* 其他图像 - 懒加载 */}
<Image
src="/content.jpg"
alt="内容图"
width={800}
height={400}
/>
</div>
);
}占位符策略
jsx
import Image from 'next/image';
export default function PlaceholderExamples() {
return (
<div>
{/* 模糊占位符 */}
<Image
src="/photo1.jpg"
alt="照片1"
width={500}
height={500}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
/>
{/* 空占位符 */}
<Image
src="/photo2.jpg"
alt="照片2"
width={500}
height={500}
placeholder="empty"
/>
</div>
);
}质量控制
jsx
export default function QualityControl() {
return (
<div>
{/* 高质量(默认 75) */}
<Image
src="/high-quality.jpg"
alt="高质量"
width={800}
height={600}
quality={90}
/>
{/* 缩略图 - 较低质量 */}
<Image
src="/thumbnail.jpg"
alt="缩略图"
width={200}
height={150}
quality={60}
/>
</div>
);
}🔧 高级配置
自定义加载器
javascript
// next.config.js
module.exports = {
images: {
loader: 'custom',
loaderFile: './my-loader.js',
},
};javascript
// my-loader.js
export default function myImageLoader({ src, width, quality }) {
return `https://cdn.example.com/${src}?w=${width}&q=${quality || 75}`;
}图像格式配置
javascript
// next.config.js
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
};🎯 实战示例
图片画廊
jsx
'use client';
import { useState } from 'react';
import Image from 'next/image';
export default function ImageGallery() {
const [selectedImage, setSelectedImage] = useState(null);
const images = [
{ id: 1, src: '/gallery/1.jpg', alt: '图片1' },
{ id: 2, src: '/gallery/2.jpg', alt: '图片2' },
{ id: 3, src: '/gallery/3.jpg', alt: '图片3' },
];
return (
<div>
<div className="grid grid-cols-3 gap-4">
{images.map((image) => (
<div
key={image.id}
className="cursor-pointer"
onClick={() => setSelectedImage(image)}
>
<Image
src={image.src}
alt={image.alt}
width={300}
height={200}
className="rounded-lg hover:opacity-80"
/>
</div>
))}
</div>
{selectedImage && (
<div className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center">
<div className="relative w-full max-w-4xl">
<Image
src={selectedImage.src}
alt={selectedImage.alt}
width={1200}
height={800}
className="rounded-lg"
/>
<button
onClick={() => setSelectedImage(null)}
className="absolute top-4 right-4 text-white"
>
关闭
</button>
</div>
</div>
)}
</div>
);
}背景图像
jsx
import Image from 'next/image';
export default function HeroSection() {
return (
<div className="relative h-screen">
<Image
src="/hero-bg.jpg"
alt="背景"
fill
style={{ objectFit: 'cover' }}
priority
/>
<div className="relative z-10 flex items-center justify-center h-full">
<h1 className="text-white text-6xl font-bold">
欢迎来到我们的网站
</h1>
</div>
</div>
);
}📝 最佳实践
1. 始终提供 alt 文本
jsx
// ✅ 好的做法
<Image src="/photo.jpg" alt="日落时的海滩" width={800} height={600} />
// ❌ 不好的做法
<Image src="/photo.jpg" alt="" width={800} height={600} />2. 为首屏图像设置 priority
jsx
export default function HomePage() {
return (
<div>
<Image
src="/hero.jpg"
alt="英雄图"
width={1200}
height={600}
priority // 首屏图像
/>
</div>
);
}3. 使用适当的尺寸
jsx
// ✅ 根据实际显示尺寸设置
<Image src="/thumb.jpg" alt="缩略图" width={200} height={150} />
// ❌ 避免过大的尺寸
<Image src="/thumb.jpg" alt="缩略图" width={2000} height={1500} />4. 配置远程图像域名
javascript
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: '**.example.com', // 支持子域名
},
],
},
};📊 性能监控
使用 Next.js Analytics
jsx
// app/layout.js
import { Analytics } from '@vercel/analytics/react';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics />
</body>
</html>
);
}📝 本章小结
Next.js 的图像优化功能通过 Image 组件提供了强大的性能优化能力,包括自动格式转换、响应式调整、懒加载等特性。
关键要点
- ✅ 使用 Image 组件替代 img 标签
- ✅ 为远程图像配置域名白名单
- ✅ 首屏图像使用 priority 属性
- ✅ 使用 fill 属性实现响应式布局
- ✅ 提供有意义的 alt 文本
- ✅ 根据实际需求调整质量参数
下一步
在下一章中,我们将学习 Next.js 的字体优化功能。
继续学习:下一章 - Next.js 字体优化