图像和多媒体✅
图片优化策略?
答案
图片优化是提升网站性能和用户体验的关键策略,主要从格式选择、压缩处理、加载策略和现代技术四个维度进行。
图片格式选择
格式 | 压缩算法 | 透明度 | 文件大小 | 浏览器支持 | 适用场景 |
---|---|---|---|---|---|
JPEG | 有损压缩 | 不支持 | 小 | 全部 | 照片、复杂图像 |
PNG | 无损压缩 | 支持 | 大 | 全部 | 图标、简单图形 |
WebP | 有损/无损 | 支持 | 最小 | 现代浏览器 | 通用替代方案 |
AVIF | 先进压缩 | 支持 | 极小 | 部分浏览器 | 未来标准 |
压缩与构建优化
// Webpack 图片优化配置
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|webp)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // < 8KB 转 base64
name: '[name].[contenthash].[ext]',
outputPath: 'images/'
}
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: { quality: 80, progressive: true },
pngquant: { quality: [0.65, 0.8] },
webp: { quality: 75 }
}
}
]
}
]
}
}
现代加载策略
<!-- 1. 响应式图片 -->
<picture>
<source media="(min-width: 1200px)" srcset="large.webp" type="image/webp">
<source media="(min-width: 768px)" srcset="medium.webp" type="image/webp">
<img src="small.jpg" alt="响应式图片" loading="lazy">
</picture>
<!-- 2. 懒加载 -->
<img class="lazy" data-src="image.jpg" alt="懒加载图片">
<!-- 3. 预加载关键图片 -->
<link rel="preload" as="image" href="hero-image.jpg">
JavaScript 实现懒加载
// Intersection Observer 懒加载
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target
img.src = img.dataset.src
img.classList.remove('lazy')
observer.unobserve(img)
}
})
})
document.querySelectorAll('.lazy').forEach(img => {
imageObserver.observe(img)
})
// 渐进式加载
function progressiveLoad (placeholder, highRes) {
const img = new Image()
img.onload = () => {
placeholder.src = highRes
placeholder.classList.add('loaded')
}
img.src = highRes
}
现代优化技术
/* CSS 优化 */
.image-container {
/* 内容可见性优化 */
content-visibility: auto;
contain-intrinsic-size: 300px 200px;
}
.lazy-image {
/* 平滑过渡效果 */
opacity: 0;
transition: opacity 0.3s;
}
.lazy-image.loaded {
opacity: 1;
}
/* 响应式图片优化 */
.responsive-image {
width: 100%;
height: auto;
object-fit: cover;
}
实际开发建议
- 格式优先级 WebP > JPEG > PNG,提供 fallback
- 尺寸控制 根据显示尺寸提供合适的图片大小
- CDN 加速 使用 CDN 分发图片资源
- 缓存策略 设置合理的缓存头,启用浏览器缓存
- 监控优化 使用 Core Web Vitals 监控图片加载性能
提示
优化顺序:选择合适格式 > 压缩处理 > 懒加载实现 > 响应式适配 > 性能监控
延伸阅读
- Web.dev: 图片优化 - 现代图片优化最佳实践
- MDN: 响应式图片 - 响应式图片实现指南
- Core Web Vitals: LCP - 最大内容绘制优化
图片懒加载原理?
答案
图片懒加载是一种性能优化技术,通过延迟加载视口外的图片来减少初始页面加载时间和带宽消耗。
核心原理
懒加载的核心思想是将图片的真实URL存储在自定义属性中(如 data-src
),当图片进入或即将进入视口时,再将URL赋值给 src 属性触发加载。
实现方式对比
方式 | 优势 | 劣势 | 适用场景 |
---|---|---|---|
Intersection Observer | 性能优异,异步处理 | 兼容性稍差(IE不支持) | 现代浏览器项目 |
滚动监听 | 兼容性好 | 频繁触发影响性能 | 需要兼容老浏览器 |
原生 loading="lazy" | 零代码实现 | 兼容性有限,功能简单 | 简单场景快速实现 |
Intersection Observer 实现
// 现代化的懒加载实现
class LazyImageLoader {
constructor (options = {}) {
this.options = {
rootMargin: '50px',
threshold: 0.1,
...options
}
this.observer = this.createObserver()
}
createObserver () {
return new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.loadImage(entry.target)
this.observer.unobserve(entry.target)
}
})
}, this.options)
}
loadImage (img) {
const src = img.dataset.src
if (src) {
img.src = src
img.classList.remove('lazy')
img.classList.add('loaded')
}
}
observe (selector = '.lazy') {
document.querySelectorAll(selector).forEach(img => {
this.observer.observe(img)
})
}
}
// 使用示例
const lazyLoader = new LazyImageLoader({
rootMargin: '100px' // 提前100px加载
})
lazyLoader.observe()
滚动监听实现(兼容性方案)
// 防抖优化的滚动监听
function createLazyLoader () {
let timeout
function checkImages () {
const images = document.querySelectorAll('.lazy')
const windowHeight = window.innerHeight
const scrollTop = window.pageYOffset
images.forEach(img => {
const rect = img.getBoundingClientRect()
// 提前200px开始加载
if (rect.top <= windowHeight + 200) {
img.src = img.dataset.src
img.classList.remove('lazy')
}
})
}
function handleScroll () {
if (timeout) clearTimeout(timeout)
timeout = setTimeout(checkImages, 100)
}
window.addEventListener('scroll', handleScroll)
checkImages() // 初始检查
}
createLazyLoader()
HTML 结构优化
<!-- 占位符优化,避免布局抖动 -->
<div class="image-wrapper" style="aspect-ratio: 16/9;">
<img
class="lazy"
data-src="high-quality.jpg"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1'%3E%3C/svg%3E"
alt="图片描述"
loading="lazy"
>
</div>
<!-- 渐进式加载 -->
<img
class="lazy progressive"
data-src="full-resolution.jpg"
src="low-quality-placeholder.jpg"
alt="渐进式加载图片"
>
CSS 增强效果
.lazy {
opacity: 0;
transition: opacity 0.3s;
}
.lazy.loaded {
opacity: 1;
}
/* 加载动画效果 */
.image-wrapper {
position: relative;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: loading 1.5s infinite;
}
@keyframes loading {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
性能优化建议
- 预加载距离 设置合理的
rootMargin
值,平衡用户体验和性能 - 图片优化 结合响应式图片和现代格式(WebP、AVIF)
- 占位符设计 使用固定宽高比避免布局抖动
- 错误处理 添加图片加载失败的降级方案
提示
推荐使用 Intersection Observer API,它在主线程之外异步执行,不会阻塞页面渲染,性能更优。
延伸阅读
- MDN: Intersection Observer API - 详细API文档
- Web.dev: 图片懒加载 - 最佳实践指南
- Can I Use: loading属性 - 原生懒加载兼容性