项目里很多图片和视频,怎么优化
2026-08-27
2302 字约 8 分钟
...图片视频优化分四层:网络层(CDN/格式)、加载层(懒加载/预加载)、渲染层(解码/缓存)、业务层(按需/降级)。面试要把这四层都讲到位才算有体系。
四层优化模型
用户看到一张图的链路:
请求 → DNS → TLS → CDN → 服务器 → 下载 → 解码 → 上屏 → 渲染
↓ ↓ ↓ ↓ ↓ ↓ ↓
网络层 网络层 加载层 渲染层
←──────────────── 业务层(按需/降级)────────────────→
第 1 层:网络层(省钱、省时间)
核心目标:让资源体积小、让用户拿到资源快
| 手段 | 作用 | 关键点 |
|---|---|---|
| 图片格式 | WebP/AVIF 比 JPEG 小 25-50% | 兼容 fallback <picture> |
| 视频格式 | H.265/AV1 比 H.264 小 40%+ | Safari 旧版不支持 AV1 |
| CDN | 就近分发 + 缓存 | 静态资源全部走 CDN,不走后端 |
| HTTP/2 / HTTP/3 | 多路复用、低延迟 | 服务器/Nginx 启用 |
| gzip / brotli 压缩 | 文本资源再压一次 | brotli 比 gzip 多 15-20% |
| 雪碧图 / iconfont / SVG | 减少请求数 | 小图标别用 PNG |
面试装逼句:“我们项目用 AV1 替换 H.264,首帧体积降了 40%,但要兼容 Safari 14-,所以 fallback 到 H.264”
第 2 层:加载层(控制请求时机)
核心目标:用户要时再要,要了就一次成功
| 手段 | 场景 | 实现 |
|---|---|---|
| 懒加载 | 首屏外的图/视频 | IntersectionObserver 或 loading="lazy" |
| 预加载 | 大概率会看的下一屏 | <link rel="preload">、<link rel="prefetch"> |
| 骨架屏 | 数据没回来时不白屏 | CSS/SVG 骨架占位 |
| 占位图 | 图没下载完有兜底 | LQIP(低质量缩略图)/ BlurHash |
| 分页/分批 | 长列表一次不传全部 | 虚拟滚动、滚动加载 |
| 缩略图 + 懒点开 | 大图用小图预览 | 双图:thumb + 原图 |
重要细节:
loading="lazy"原生属性,但 Safari 15.4 才支持,旧设备用 IntersectionObserver- 视频要加
preload="metadata"而非preload="auto",否则移动端一进页面就下完整个视频 <link rel="preload">优先级最高,用来抢首屏关键资源
第 3 层:渲染层(让浏览器更省力)
核心目标:解码快、绘制快、不抖动
| 手段 | 作用 |
|---|---|
<img decoding="async"> | 不阻塞主线程解码 |
CSS will-change: transform | 触发 GPU 合成层 |
| 避免重排重绘 | 动画用 transform/opacity,别用 top/left |
| 图片尺寸固定 | width/height 属性先占位,避免布局抖动 CLS |
srcset + sizes | 移动端给 1x/2x/3x 适配 |
| 视频替代 GIF | 视频体积是 GIF 的 1/10 |
| WebP/AVIF | 浏览器解码比 PNG/JPEG 更快(GPU 支持) |
| Canvas/WebGL 离屏 | 大批量图片绘制用 OffscreenCanvas |
| requestIdleCallback | 不急的渲染任务丢到空闲期 |
CLS(Cumulative Layout Shift)是 LCP 之外的另一关键指标——图片不写 width/height 就布局抖动。
第 4 层:业务层(最容易被忽视)
核心目标:能不传就不传、能降级就降级
| 场景 | 策略 |
|---|---|
| 用户没看就退出页面 | abort 掉未完成的请求 |
| 弱网/2G/3G | 降级到缩略图/纯文本 |
| 节省用户流量 | 移动端默认低画质 |
| 节省服务器成本 | 缩略图、视频转码用云函数异步处理 |
| 列表页 vs 详情页 | 列表用缩略图、详情再请求原图 |
| 重复内容 | 浏览器缓存(强缓存 + 协商缓存) |
| 大文件上传 | 分片上传、断点续传、秒传(hash 去重) |
视频专项优化(面试加分项)
1. 视频比图复杂得多——一个 1080p 视频没优化可能几百 MB。
2. 必做的三件事:
- 转码多份:服务端用 ffmpeg 转 360p/720p/1080p 多档,移动端按网速选
- 切片 HLS/DASH:把视频切成 5-10s 的
.ts小文件,可以边下边播 - 首屏秒开:前 1-2 秒单独放一个 GZIP 文件,首帧独立加载
3. 播放器层面:
- 离开视口自动暂停(
IntersectionObserver) - 静音自动播放(移动端策略限制)
- 不用
<video autoplay>—— 会触发下载整个视频 - 视频封面用
<video poster="">,不要把封面图当成一个额外资源
高频面试追问
Q1:图片懒加载怎么实现?
// 现代方案
<img loading="lazy" src="..." />
// 兼容方案
const obs = new IntersectionObserver((entries) => {
entries.forEach(e => {
if (e.isIntersecting) {
e.target.src = e.target.dataset.src
obs.unobserve(e.target)
}
})
}, { rootMargin: '200px' })
document.querySelectorAll('img[data-src]').forEach(img => obs.observe(img))
Q2:首屏白屏怎么优化?
- 关键 CSS 内联(critical CSS)
- 字体 subset + font-display: swap
- 服务端渲染(SSR)/ 静态生成(SSG)
- 骨架屏(Skeleton)
Q3:移动端图片适配怎么做?
<img
src="img-1x.jpg"
srcset="img-1x.jpg 1x, img-2x.jpg 2x, img-3x.jpg 3x"
sizes="(max-width: 600px) 100vw, 50vw"
/>
Q4:CDN 缓存策略?
- HTML:
no-cache,每次回源 - 静态资源(JS/CSS/图片,带 hash):
max-age=31536000, immutable,永不过期 - 接口:
no-store或短缓存
一句话答题模板
项目里图片视频优化我分四层做:网络层(WebP/AVIF、CDN、HTTP/2)解决"传得小传得快";加载层(懒加载、预加载、骨架屏)解决"按需加载";渲染层(GPU 加速、固定尺寸、防抖)解决"画得快不抖动";业务层(缩略图、降级、abort、缓存策略)解决"不浪费"。视频额外做转码多档、HLS 切片、首屏秒开。
延伸阅读
图片性能优化:了解JPEG、GIF、PNG、WebP、Base64的优缺点:图片格式选型图片懒加载的实现方法:懒加载代码细节懒加载:让网页像优雅的绅士:懒加载原理深挖全面横评 6 大前端视频播放器:视频播放器选型使用 WebCodec 在浏览器解码视频、抓帧截图、转GIF:WebCodec 进阶揭秘 Next.js 的图像魔法:框架级图片处理懒加载图片在同一个 Item 中逐个出现的原因与解决方案:实战踩坑
如果您觉得这篇文章有帮助,请点个赞吧~
相关文章
更多文章 →八股文2026-08-27
定时器按顺序播放多个音频,切后台音频会乱
本身不会补触发,但 它会被系统级冻结 ——iOS Safari 后台完全停止计时,切回前台后 只补执行一次 (不是不补,而是"缺失的中间状态补不上")。间隔短的不会出大问题, 间隔长的会出现"音频流被压缩" ——切回来后本该播 5 分钟的间隙,实际只过了 3 分钟,结果整段对不上。 核心原则 :定时器只能用来"提醒一次", 真正决定"该不该播"的是绝对时间戳 。 setTimeout 在后台会发生什么(按平台) | 平台 | 后台行为...
面试
八股文2026-08-27
线上项目白屏的原因
白屏的本质是 渲染管线某一环断了 ——可能是资源、JS、接口、路由、样式、兼容性任一环节出问题。排查按"控制台 → 网络 → DOM → 环境"四步定位。 本质(前端类比) 把网页想成一栋楼: 白屏 ≠ 一定是同一种原因——这是面试想听的层次。 六大类原因(按出现频率) | 类别 | 典型表现 | 真实案例 | | : | : | : | | ① 资源加载失败 | DOM 是空的 | 入口 JS 404、CDN 挂了、CSS 阻塞 |...
面试
八股文2026-08-27
背景图就是 1MB 大图,怎么优化
1MB 大背景图优化分 三步 :压缩体积(10 30x)、按需加载(按设备/视口/网速)、渲染期优化(GPU 合成)。背景图跟 不同——它是 CSS,不走浏览器的原生懒加载机制,得手动处理。 背景图 vs 的关键区别(先讲清楚这个) 这是面试官想听的"针对性认知"——背景图不是普通图片,不能套通用方案。 三步优化(按优先级) 第 1 步:压缩体积(最重要,立竿见影) 1MB 的来源一般是这几种 ,对应解决方案: | 原始问题 | 体积来...
面试
八股文2026-08-20
Embedding 向量模型:从语义表示到相似度计算
前言 大模型「读懂」文字靠的是 token,但 token 之间只有离散的编号关系,模型并不知道「苹果」和「李子」在语义上很近。要让程序能「理解」两段文字的相似程度,必须先把文本映射成一个 高维向量 ,再用几何方法比较。这一步就是 Embedding。 本篇基于我本地 今天的真实代码,从语义表示讲到余弦相似度,并复盘几个踩过的真实坑。 一、为什么需要 Embedding 传统关键词检索是「字面匹配」: Embedding 做的是「语义匹...
面试
八股文2026-08-19
前端面试100题
前端面试 100 题 适用方向:中高级前端 / React / Vue / Next.js / Nuxt / TypeScript / 工程化 / 实时通信 / Electron / Node.js / AI 应用前端 使用方式:优先掌握“标准回答”,再练“面试官追问”,最后把“结合你的简历怎么答”组织成自己的项目故事。 说明 “结合你的简历怎么答”只使用你简历中已经出现的项目与技术事实。 “标准回答 / 追问”属于通用前端知识总结,用...
面试
八股文2026-08-19
深入理解 JavaScript 原型与原型链:从关系图到核心逻辑 - heshanwan - 博客园
在 JavaScript 世界里, 原型(Prototype)和原型链(Prototype Chain) 是理解对象继承、属性查找机制的基石。很多开发者初学时对它们 “又爱又恨”,这篇文章将结合经典关系图,用通俗易懂的方式拆解原型与原型链的核心逻辑,帮你彻底掌握这套机制! 一、先搞懂几个核心概念 在分析关系图前,先明确 JavaScript 中与原型相关的关键概念,避免后续混淆: 1\. 函数对象与普通对象 函数对象 :由...
面试
评论
请登录后发表评论
去登录