awesome-interview/book2/topic-multi-pics-site-optimize/index.html

22 lines
58 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-beta.5">
<link rel="search" type="application/opensearchdescription+xml" title="HZFE - 剑指前端 Offer" href="/awesome-interview/opensearch.xml">
<link rel="preconnect" href="https://hm.baidu.com">
<script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?c7cd0fd77ac518cc6ef46461cdc9524b";var c=document.getElementsByTagName("script")[0];c.parentNode.insertBefore(e,c)}()</script><title data-react-helmet="true">多图站点性能优化 | HZFE - 剑指前端 Offer</title><meta data-react-helmet="true" name="twitter:card" content="summary_large_image"><meta data-react-helmet="true" property="og:url" content="https://hzfe.github.io/awesome-interview/book2/topic-multi-pics-site-optimize"><meta data-react-helmet="true" name="docsearch:language" content="en"><meta data-react-helmet="true" name="docsearch:version" content="current"><meta data-react-helmet="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-react-helmet="true" property="og:title" content="多图站点性能优化 | HZFE - 剑指前端 Offer"><meta data-react-helmet="true" name="description" content="回答关键点"><meta data-react-helmet="true" property="og:description" content="回答关键点"><link data-react-helmet="true" rel="shortcut icon" href="/awesome-interview/img/favicon.ico"><link data-react-helmet="true" rel="canonical" href="https://hzfe.github.io/awesome-interview/book2/topic-multi-pics-site-optimize"><link data-react-helmet="true" rel="alternate" href="https://hzfe.github.io/awesome-interview/book2/topic-multi-pics-site-optimize" hreflang="en"><link data-react-helmet="true" rel="alternate" href="https://hzfe.github.io/awesome-interview/book2/topic-multi-pics-site-optimize" hreflang="x-default"><link data-react-helmet="true" rel="preconnect" href="https://61YWQXP6JY-dsn.algolia.net" crossorigin="anonymous"><link rel="stylesheet" href="/awesome-interview/assets/css/styles.304d13b7.css">
<link rel="preload" href="/awesome-interview/assets/js/runtime~main.50b7dd91.js" as="script">
<link rel="preload" href="/awesome-interview/assets/js/main.178fbfc5.js" as="script">
</head>
<body>
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<div><a href="#" class="skipToContent_1oUP">Skip to main content</a></div><nav class="navbar navbar--fixed-top navbarHideable_2qcr"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Navigation bar toggle" class="navbar__toggle clean-btn" type="button" tabindex="0"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/awesome-interview/"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><b class="navbar__title">剑指前端 Offer</b></a></div><div class="navbar__items navbar__items--right"><a href="https://github.com/hzfe/awesome-interview" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link"><span>GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_3J9K"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></span></a><div class="searchBox_1Doo"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div class="main-wrapper docs-wrapper docs-doc-page"><div class="docPage_31aa"><button class="clean-btn backToTopButton_35hR" type="button"><svg viewBox="0 0 24 24" width="28"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z" fill="currentColor"></path></svg></button><aside class="docSidebarContainer_3Kbt"><div class="sidebar_15mo sidebarWithHideableNavbar_267A"><a tabindex="-1" class="sidebarLogo_3h0W" href="/awesome-interview/"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--light_3UqQ"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_1VuW themedImage--dark_hz6m"><b>剑指前端 Offer</b></a><nav class="menu thin-scrollbar menu_Bmed menuWithAnnouncementBar_2WvA"><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" href="/awesome-interview/about">关于我们</a></li><li class="menu__list-item"><a class="menu__link" href="/awesome-interview/">前言</a></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">模拟题一</a></li><li class="menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#">模拟题二</a><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/browser-render-mechanism">浏览器:浏览器渲染机制</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/browser-garbage">浏览器:垃圾回收机制</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/engineer-babel">工程化Babel 的原理</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/frame-react-fiber">框架React Fiber 的作用和原理</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/frame-react-hoc-hooks">框架HOC vs Render Props vs Hooks</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/js-inherite">基础ES5、ES6 如何实现继承</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/js-new">基础New 操作符的原理</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/css-preprocessor">样式:谈谈 CSS 预处理器</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/network-http-cache">网络HTTP 缓存机制</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/coding-throttle-debounce">编码:实现节流去抖函数</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book2/algorithm-reverse-linked-list">算法:反转链表</a></li><li class="menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/awesome-interview/book2/topic-multi-pics-site-optimize">综合:多图站点性能优化</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#">模拟题三</a></li></ul></nav><button type="button" title="Collapse sidebar" aria-label="Collapse sidebar" class="button button--secondary button--outline collapseSidebarButton_1CGd"><svg width="20" height="20" aria-hidden="true" class="collapseSidebarButtonIcon_3E-R"><g fill="#7a7a7a"><path d="M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"></path><path d="M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"></path></g></svg></button></div></aside><main class="docMainContainer_3ufF"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_3FnS"><div class="docItemContainer_33ec"><article><div class="tocCollapsible_1PrD tocMobile_3Hoh"><button type="button" class="clean-btn tocCollapsibleButton_2O1e">On this page</button></div><div class="markdown"><header><h1>多图站点性能优化</h1></header><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3R7-" id="回答关键点"></a>回答关键点<a class="hash-link" href="#回答关键点" title="Direct link to heading">#</a></h2><p><code>图片优化</code> <code>传输优化</code> <code>加载策略</code></p><p>提高网站性能的一项重要指标是提高访问速度,这与用户留存率和转换率呈正相关。根据 <a href="https://httparchive.org/reports/page-weight?start=2017_03_01&amp;end=latest&amp;view=list#bytesImg" target="_blank" rel="noopener noreferrer">HTTPArchive</a> 的数据可知,图像是大多数网站需求最多的资源类型,通常比其他资源占用更多带宽。在多图站点中,图片资源对于页面的加载和整体的用户体验有更明显的影响。最常见的问题是图片加载慢。对应的优化策略包括:</p><ul><li>图片优化:进行图片压缩/缩放和选择正确的图片格式。</li><li>网络传输优化:使用 HTTP/2 和 CDN 服务。</li><li>图片加载策略优化:按需使用懒加载、预加载,响应式图片加载等策略。</li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3R7-" id="知识点深入"></a>知识点深入<a class="hash-link" href="#知识点深入" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3R7-" id="1-图片优化"></a>1. 图片优化<a class="hash-link" href="#1-图片优化" title="Direct link to heading">#</a></h3><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithHideOnScrollNavbar_3R7-" id="11-选择合适的图片格式"></a>1.1 选择合适的图片格式<a class="hash-link" href="#11-选择合适的图片格式" title="Direct link to heading">#</a></h4><p>为控制篇幅,以下提到的图片格式,为截止至 2021 年 8 月,市场份额大于 0.1% 的格式。</p><ol><li><p>JPEG 的压缩效率高,是一种高效且轻巧的有损压缩图片格式。但不适合对矢量或对比度强的图像压缩,会有明显的图片质量下降。超过一定的压缩阈值,压缩的图像也会出现明显的图片质量下降。</p></li><li><p>PNG 是一种无损压缩的高保真图片格式。相比 JPEG 有更强色彩表现力,且支持透明通道。</p></li><li><p>GIF 是一种最多支持 256 种颜色的 8 位无损图片格式,支持动图。</p></li><li><p>WebP 是一种同时提供有损压缩与无损压缩的图片格式。不仅支持透明图片,有优秀的色彩表现,也能支持动画。支持无损压缩且通常比 PNG 格式的相同图像小 26%。支持有损压缩且比视觉上相似压缩水平的 JPEG 图像平均小 25-35%。但是浏览器兼容性差。</p></li><li><p>SVG 是一种基于 XML 语法的图像格式全称是可缩放矢量图Scalable Vector Graphics。适合非照片类型的图片的缩放或高保真场景。</p></li></ol><p>图中所示为 2012 年 1 月至 2021 年 8 月的主流图片格式的使用趋势。</p><p><img src="https://user-images.githubusercontent.com/17002181/128595023-a0ceb0f4-9066-4145-b1e3-345e0c0d2b36.png" alt="image"></p><blockquote><p>图片来源 <a href="https://w3techs.com/technologies/history_overview/image_format/all/y" target="_blank" rel="noopener noreferrer">w3techs.com</a></p></blockquote><p>按需选择更高效的图片格式,不仅能提升用户视觉体验,也可以提升网站加载效率。在选用图片格式时,一般可以基于一些简单规则来筛选:在兼容性支持的情况下,可以选用 WebP否则可以通过动图和透明度两个需求点来进行筛选</p><ul><li><p><strong>动图</strong></p><p>可以使用 GIF 或者是视频格式。前者的问题在于支持的色彩少,低帧率低分辨率,文件体积利用率低,而视频方案则可以避免这些问题。也可以使用 APNG支持更多色彩的前提下和对应 GIF 格式的文件体积相近。</p></li><li><p><strong>透明度</strong></p><p>PNG 和 GIF 都支持透明图片,可以按需使用。</p></li></ul><p>在没有透明和动画需求的情况下JPEG 格式图片胜任大部分场景,如果对图片的展示质量有较高要求时,可使用 PNG 格式图片。</p><p>绘制 LOGO、ICON 等非照片的图片内容时,一般使用 SVG 格式。比如 iconfont 等矢量图标管理平台中大量使用 SVG 格式。</p><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithHideOnScrollNavbar_3R7-" id="12-图片压缩和缩放处理"></a>1.2 图片压缩和缩放处理<a class="hash-link" href="#12-图片压缩和缩放处理" title="Direct link to heading">#</a></h4><p>由于实际应用场景的差异,对应图片的布局大小以及图片细节要求各有不同,大量未经压缩或缩放调整的图片会使网页加载许多不必要的字节,且对用户的视觉效果没有太大的提升。前端常见的压缩和缩放的处理方案包括:</p><ul><li>静态资源通过工具(比如 imagemin按需进行有损或无损压缩。</li><li>将用户上传的图片绘制到 Canvas 画布上,利用<code>CanvasRenderingContext2D.drawImage(image, dx, dy, dWidth, dHeight)</code> API 进行图片缩放;利用 <code>HTMLCanvasElement.toDataURL(type, encoderOptions)</code> API 进行有损压缩。</li><li>根据用户侧的显示需求(如头像、缩略图、商品图等),通过对象存储服务(如七牛、阿里云 OSS所提供的压缩或缩放等功能处理后返回使用。</li></ul><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3R7-" id="2-网络传输优化"></a>2. 网络传输优化<a class="hash-link" href="#2-网络传输优化" title="Direct link to heading">#</a></h3><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithHideOnScrollNavbar_3R7-" id="21-使用-http2-协议"></a>2.1 使用 HTTP/2 协议<a class="hash-link" href="#21-使用-http2-协议" title="Direct link to heading">#</a></h4><p>使用 HTTP/1.X 协议时,浏览器有同源最大并发连接数的限制,且 HTTP/1.X 不支持多路复用因此一个多图站点想要获得较完整的视觉呈现会有一定程度的延迟所有的资源请求包括图片资源会进入先进先出FIFO队列等待被下载。</p><p><img src="https://user-images.githubusercontent.com/17002181/128637043-8810bdb4-f190-4196-abc2-37d78896b71b.png" alt="image"></p><p>使用 HTTP/2 前的常见优化方案包括:</p><ul><li>使用精灵图 / 雪碧图,减少 HTTP 请求数。</li><li>10kb 大小以内的图片资源使用 base64 编码,减少 HTTP 请求数。</li><li>通过使用多个域名,开启多个 TCP 连接,突破浏览器同源最大并发连接数的限制。</li></ul><p>由于 HTTP/2 支持多路复用,因此使用 HTTP/2 可以进一步减少网络延迟,更加快速的加载图片资源。</p><p>如下图所示,观察 Connection ID 一列可知,使用 HTTP/2 的情况下,资源重用同一条 TCP 连接,并发请求大量图片资源。</p><p><img src="https://user-images.githubusercontent.com/17002181/128636947-43337c16-3517-41c0-aea9-06c5ff3741a2.png" alt="image"></p><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithHideOnScrollNavbar_3R7-" id="22-使用-cdn"></a>2.2 使用 CDN<a class="hash-link" href="#22-使用-cdn" title="Direct link to heading">#</a></h4><p>CDN 将源站资源缓存到各加速节点后,用户请求源站资源时无需回源,可就近获取 CDN 节点上已缓存的资源,从而提高资源访问速度,分担源站压力。常见的 CDN 服务还支持对图片进行压缩、缩放、裁剪等图像处理功能。</p><h3><a aria-hidden="true" tabindex="-1" class="anchor anchor__h3 anchorWithHideOnScrollNavbar_3R7-" id="3-图片加载策略优化"></a>3. 图片加载策略优化<a class="hash-link" href="#3-图片加载策略优化" title="Direct link to heading">#</a></h3><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithHideOnScrollNavbar_3R7-" id="31-图片懒加载"></a>3.1 图片懒加载<a class="hash-link" href="#31-图片懒加载" title="Direct link to heading">#</a></h4><p>懒加载的策略是推迟加载离屏图片资源,从而减少资源请求数。实现懒加载的主流方案有:</p><ul><li>使用 img 标签的 loading 属性。</li><li>使用 Intersection Observer API。</li><li>使用 scroll、resize 和 orientationchange 事件。</li></ul><p>后两种方案的实现原理是通过在 img 标签上添加 data-src 或其他自定义属性存放图片链接,而 src 属性不被设置或设置为占位图链接。通过 Intersection Observer 或 scroll 等 API 检测离屏图片是否滚动到预期位置,如果是则将 data-src 的值赋给 src 属性,从而达到懒加载的目的。</p><p>一般使用图片懒加载时,图片的占位处会使用各种方式来提升用户体验:</p><ul><li>色块 / 骨架屏占位。</li><li>LOGO 等品牌元素做默认图片。</li><li>使用图片缩略图做模糊效果占位。</li></ul><p><strong>img loading</strong></p><p>从 Chrome 76+ 版本起,开发者可以使用 loading 属性来推迟加载可通过滚动进入视口内的离屏图像。通过给 loading 属性设置 lazy 值,可以推迟加载资源,直到它与视口达到一定距离。<a href="https://caniuse.com/loading-lazy-attr" target="_blank" rel="noopener noreferrer">caniuse.com</a> 可查阅跨浏览器兼容性支持的详细信息。不支持 loading 属性的浏览器会忽略该属性,不会产生副作用。</p><div class="codeBlockContainer_K1bP"><div class="codeBlockContent_hGly html"><pre tabindex="0" class="prism-code language-html codeBlock_23N8 thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_39YC"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">image.png</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">loading</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">lazy</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c"></span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">width</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">200</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">height</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">200</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_Ue-o clean-btn">Copy</button></div></div><p><strong>Intersection Observer</strong></p><p>Intersection Observer API 可用于异步观察目标元素与祖先元素或与顶级文档视口的交叉点变化。</p><div class="codeBlockContainer_K1bP"><div class="codeBlockContent_hGly html"><pre tabindex="0" class="prism-code language-html codeBlock_23N8 thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_39YC"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">data-src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">https://hzfe-blah.com/anyphoto1.jpg</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">data-src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">https://hzfe-blah.com/anyphoto2.jpg</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_Ue-o clean-btn">Copy</button></div></div><div class="codeBlockContainer_K1bP"><div class="codeBlockContent_hGly js"><pre tabindex="0" class="prism-code language-js codeBlock_23N8 thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_39YC"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> config </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">/** any option */</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block">
</span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> observer </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">IntersectionObserver</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">entries</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> self</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> entries</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter punctuation" style="color:#393A34">{</span><span class="token parameter"> isIntersecting</span><span class="token parameter punctuation" style="color:#393A34">,</span><span class="token parameter"> target </span><span class="token parameter punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">isIntersecting</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword control-flow" style="color:#00009f">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">target</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">dataset</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">src</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> target</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">src</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> target</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">dataset</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">src</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> target</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">removeAttribute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">&quot;data-src&quot;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block">
</span></span><span class="token-line" style="color:#393A34"><span class="token plain"> self</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">unobserve</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">target</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> config</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block">
</span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">const</span><span class="token plain"> images </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token dom variable" style="color:#36acaa">document</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">querySelectorAll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">&quot;[data-src]&quot;</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain">images</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">forEach</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">image</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token arrow operator" style="color:#393A34">=&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> observer</span><span class="token punctuation" style="color:#393A34">.</span><span class="token method function property-access" style="color:#d73a49">observe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">image</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_Ue-o clean-btn">Copy</button></div></div><p><strong>scroll</strong></p><p>如果 Intersection Observer 存在兼容性问题,除了可以添加对应 polyfill 之外,也可以考虑降级为监听 scroll、resize、orientationchange 事件的方案。实现思路和 Intersection Observer 一致。具体细节上,需要自行计算图片节点与目标视口的纵向或横向距离,且需使用节流函数来避免性能问题。</p><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithHideOnScrollNavbar_3R7-" id="32-图片预加载"></a>3.2 图片预加载<a class="hash-link" href="#32-图片预加载" title="Direct link to heading">#</a></h4><p>图片预加载机制是为了增强用户体验,尽快地加载出图片,使得用户体验更为流畅。</p><p>如果预加载的图片是确切且有限的,可以通过硬编码 link 标签来实现预加载。但是多数情况下,预加载的使用场景是动态的。</p><p><strong>link</strong></p><p><code>&lt;link rel=&quot;preload&quot;&gt;</code> 允许开发者在 HTML 的 head 标签中声明资源请求,指定页面需要预加载的资源,并且在浏览器的主要渲染机制启动之前加载,避免阻塞页面渲染且保证资源尽早可用。</p><div class="codeBlockContainer_K1bP"><div class="codeBlockContent_hGly html"><pre tabindex="0" class="prism-code language-html codeBlock_23N8 thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_39YC"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">link</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">preload</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">as</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">image</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">important.png</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_Ue-o clean-btn">Copy</button></div></div><p><strong>动态场景</strong></p><p>一般常见方案是动态创建 Image 标签或者是 Ajax 请求。使用 Ajax 时需要注意可能存在跨域问题。</p><div class="codeBlockContainer_K1bP"><div class="codeBlockContent_hGly js"><pre tabindex="0" class="prism-code language-js codeBlock_23N8 thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_39YC"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// 动态创建 Image</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">function</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">preloadImage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token parameter">url</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> img </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">new</span><span class="token plain"> </span><span class="token class-name">Image</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> img</span><span class="token punctuation" style="color:#393A34">.</span><span class="token property-access">src</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> url</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_Ue-o clean-btn">Copy</button></div></div><h4><a aria-hidden="true" tabindex="-1" class="anchor anchor__h4 anchorWithHideOnScrollNavbar_3R7-" id="33-响应式图片加载"></a>3.3 响应式图片加载<a class="hash-link" href="#33-响应式图片加载" title="Direct link to heading">#</a></h4><p>由于用户终端设备不同,如果图片资源无差别使用相同图片,可能造成带宽浪费或者是图片不清晰以及视觉体验差的问题。</p><p>一般可以通过使用 picture 标签来定义零或多个 source 节点和一个 img 节点,用于提供图片在不同设备/显示场景下对应的内容展示。picture 的常见作用包括:</p><ul><li><p><strong>艺术指导Art direction</strong></p><p>为不同的媒体条件裁剪或修改图像。比如在较小的显示器上,加载一个更突出重点的图像。</p><p><img src="https://user-images.githubusercontent.com/17002181/128734922-3d28cc38-b3c1-4a6e-afd9-5a8c0f5113b1.jpg" alt="38666B5C621028DD6F3050D95EF1889E"></p><div class="codeBlockContainer_K1bP"><div class="codeBlockContent_hGly html"><pre tabindex="0" class="prism-code language-html codeBlock_23N8 thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_39YC"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">picture</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">source</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">srcset</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar-desktop.png</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">media</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">(min-width: 990px)</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">source</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">srcset</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar-tablet.png</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">media</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">(min-width: 750px)</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar.png</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-default-avatar</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">picture</span><span class="token tag punctuation" style="color:#393A34">&gt;</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_Ue-o clean-btn">Copy</button></div></div></li><li><p><strong>提供图片格式回退方案</strong></p><p>在支持的浏览器中优先使用更适合的图片格式,比如 WebP 等。同时支持在有兼容性问题的浏览器中回退加载其他格式的图片。</p><div class="codeBlockContainer_K1bP"><div class="codeBlockContent_hGly html"><pre tabindex="0" class="prism-code language-html codeBlock_23N8 thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_39YC"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">picture</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">source</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">srcset</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar.webp</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">type</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">image/webp</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">source</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">srcset</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar.jpg</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">type</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">image/jpeg</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar.jpg</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-default-avatar</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">picture</span><span class="token tag punctuation" style="color:#393A34">&gt;</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_Ue-o clean-btn">Copy</button></div></div></li><li><p><strong>节省带宽并提升页面加载速度</strong></p><p>通过按需加载并显示最适合用户设备的图像,从而节省带宽和加快页面加载时间。</p><div class="codeBlockContainer_K1bP"><div class="codeBlockContent_hGly html"><pre tabindex="0" class="prism-code language-html codeBlock_23N8 thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_39YC"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">picture</span><span class="token tag punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">source</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">srcset</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar-desktop.png, hzfe-avatar-desktop-2x.png 2x</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">media</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">(min-width: 990px)</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">source</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">srcset</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar-tablet.png, hzfe-avatar-tablet-2x.png 2x</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">media</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">(min-width: 750px)</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">img</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">srcset</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar.png, hzfe-avatar-2x.png 2x</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">src</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-avatar.png</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">alt</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">hzfe-default-avatar</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"></span></span><span class="token-line" style="color:#393A34"><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><span class="token plain"></span></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token tag punctuation" style="color:#393A34">&lt;/</span><span class="token tag" style="color:#00009f">picture</span><span class="token tag punctuation" style="color:#393A34">&gt;</span></span></code></pre><button type="button" aria-label="Copy code to clipboard" class="copyButton_Ue-o clean-btn">Copy</button></div></div></li></ul><h2><a aria-hidden="true" tabindex="-1" class="anchor anchor__h2 anchorWithHideOnScrollNavbar_3R7-" id="参考资料"></a>参考资料<a class="hash-link" href="#参考资料" title="Direct link to heading">#</a></h2><ol><li><a href="https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types" target="_blank" rel="noopener noreferrer">image types</a></li><li><a href="https://web.dev/fast" target="_blank" rel="noopener noreferrer">Fast load times</a></li><li><a href="https://w3techs.com/technologies/details/im-webp" target="_blank" rel="noopener noreferrer">Usage statistics of WebP for websites</a></li><li><a href="https://web.dev/browser-level-image-lazy-loading/" target="_blank" rel="noopener noreferrer">Browser-level image lazy-loading for the web</a></li></ol></div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/awesome-interview/book2/algorithm-reverse-linked-list"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« 算法:反转链表</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/awesome-interview/book3/browser-event-loop"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">浏览器:浏览器事件循环 »</div></a></div></nav></div></div><div class="col col--3"><div class="tableOfContents_35-E thin-scrollbar"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#回答关键点" class="table-of-contents__link">回答关键点</a></li><li><a href="#知识点深入" class="table-of-contents__link">知识点深入</a><ul><li><a href="#1-图片优化" class="table-of-contents__link">1. 图片优化</a></li><li><a href="#2-网络传输优化" class="table-of-contents__link">2. 网络传输优化</a></li><li><a href="#3-图片加载策略优化" class="table-of-contents__link">3. 图片加载策略优化</a></li></ul></li><li><a href="#参考资料" class="table-of-contents__link">参考资料</a></li></ul></div></div></div><div class="row"><div class="col"><div class="react-utterences"><div>Loading script...</div></div></div><div class="col col--3"></div></div></div></main></div></div></div>
<script src="/awesome-interview/assets/js/runtime~main.50b7dd91.js"></script>
<script src="/awesome-interview/assets/js/main.178fbfc5.js"></script>
</body>
</html>