首页/文章/八股文

项目里很多图片和视频,怎么优化

2026-08-27
23028 分钟
...

图片视频优化分四层:网络层(CDN/格式)、加载层(懒加载/预加载)、渲染层(解码/缓存)、业务层(按需/降级)。面试要把这四层都讲到位才算有体系。

四层优化模型

用户看到一张图的链路

请求DNSTLSCDN服务器下载解码上屏渲染
 ↓        ↓      ↓        ↓        ↓      ↓      ↓
网络层              网络层              加载层    渲染层
       ←──────────────── 业务层按需/降级)────────────────→

第 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 层:加载层(控制请求时机)

核心目标:用户要时再要,要了就一次成功

手段场景实现
懒加载首屏外的图/视频IntersectionObserverloading="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) 是理解对象继承、属性查找机制的基石。很多开发者初学时对它们 “又爱又恨”,这篇文章将结合经典关系图,用通俗易懂的方式拆解原型与原型链的核心逻辑,帮你彻底掌握这套机制! &nbsp; 一、先搞懂几个核心概念 在分析关系图前,先明确 JavaScript 中与原型相关的关键概念,避免后续混淆: 1\. 函数对象与普通对象 函数对象 :由...
面试

评论

请登录后发表评论

去登录
加载评论中...

目录