尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Front-End-Checklist 前端清单系列:offscreen-lazy 规则实战——用原生 `loading=“lazy“` 为视口外图片做懒加载

Front-End-Checklist 前端清单系列:offscreen-lazy 规则实战——用原生 `loading=“lazy“` 为视口外图片做懒加载 Front-End-Checklist 前端清单系列offscreen-lazy 规则实战——用原生loadinglazy为视口外图片做懒加载【免费下载链接】Front-End-Checklist The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist本文围绕 Front-End-Checklist 开源仓库中的offscreen-lazy规则展开。核心结论一句话视口viewport之外的图片应当使用loadinglazy延迟下载直到用户滚动接近时才加载从而减少首屏传输的字节数。读完本文你将掌握loading属性的正确用法、LCP 图片的优先级红线、与width/height及picture的组合套路、React/Next.js 框架落地方式以及一套可在 DevTools 与 Lighthouse 中直接执行的验证流程。规则速览这条规则来自仓库中的 offscreen-lazy 规则文档 及配套的 SKILL.md属于images分类下performance子类目规则元数据标注为Priority优先级highDifficulty难度beginner新手可直接上手Estimated Time预估耗时10 分钟SKILL.md 中给出了 5 条 Quick Reference快速参考也是理解整条规则的最小集合为所有折线below the fold以下的img元素添加loadinglazy永远不要懒加载 LCP 图片hero 图、首张商品图——改用fetchpriorityhigh使用loadinglazy时必须同时提供width和height防止 CLS布局偏移原生loadinglazy在所有现代浏览器中通用支持无需任何 JavaScript polyfill如果从代码片段中无法判断图片是否在折线以下不要凭空报出懒加载缺陷这条对 AI Agent 审查尤其重要下文会展开。为什么重要首屏加载中看不见的字节Lazy loading eliminates unnecessary image downloads on initial page load. A page with 20 images below the fold may transfer several megabytes of data that users who dont scroll will never see.规则文档在 Why It Matters 一节给出了量级直觉一个页面如果有 20 张折线以下的图片首屏可能传输数 MB 用户根本不会看到的数据。把这些下载推迟带来的收益是降低 Time to InteractiveTTI浏览器无需为看不见的图片消耗网络与解码资源改善折线以上内容的 LCP首屏关键资源获得更多带宽与优先级节省带宽对按流量计费的移动用户尤其重要。用一句话概括懒加载的核心不是更快地加载图片而是不加载用户用不到的图片。基础写法一个属性完成图片懒加载原生浏览器懒加载的精髓在于——loadinglazy一个属性就完成了过去需要整套 JavaScript 库才能做到的事。规则文档的代码示例给出了反例 vs 正例的对比!-- ❌ Bad: All images load immediately regardless of position -- img srcproduct-1.jpg altProduct 1 width400 height300 img srcproduct-2.jpg altProduct 2 width400 height300 !-- ... 20 more product images -- !-- ✅ Good: Above-fold hero loads eagerly, rest defer -- !-- Hero image — above fold, must load immediately -- img srchero.jpg altHero image width1200 height600 fetchpriorityhigh !-- Below-fold product images — defer until near viewport -- img srcproduct-1.jpg altProduct 1 width400 height300 loadinglazy img srcproduct-2.jpg altProduct 2 width400 height300 loadinglazy反例中 22 张图片全部立刻下载正例中只有 hero 图立即加载并配合fetchpriorityhigh提升优先级商品图全部推迟。注意loading属性只有三个合法取值lazy延迟加载直到图片接近视口eager立即加载默认行为等同于不写auto由浏览器自行决定等同于默认行为。红线绝不懒加载 LCP 图片这是整条规则中最重要的一条规则文档用 Critical 单独成节强调The Largest Contentful Paint (LCP) element is usually the first large image visible on the page. Lazy-loading it delays the most important metric.LCPLargest Contentful Paint最大内容绘制是 Core Web Vitals 的核心指标之一而 LCP 元素往往是页面上第一张可见的大图hero 图、首屏主图。如果给它加上loadinglazy浏览器会故意推迟它的下载直接拖慢最重要的指标。!-- ❌ Bad: Lazy-loading the LCP image hurts LCP score -- img srchero.jpg altHero image loadinglazy width1200 height600 !-- ✅ Good: LCP image loads immediately with high priority -- img srchero.jpg altHero image width1200 height600 fetchpriorityhigh decodingasync 正确的 LCP 图片配置是去掉loadinglazy加上fetchpriorityhigh提示浏览器提升该请求的优先级并可选decodingasync异步解码避免阻塞渲染。这条反直觉规则极其容易踩坑——开发者为省带宽给所有图片统一加lazy结果把 LCP 也一起延迟了。在仓库的规则体系中这条红线与 critical-images 规则 直接呼应后者专门讲解优先加载关键图片使用fetchpriorityhigh标记 LCP 图片、在head中 preload hero 图、以及从折线以上的图片中移除loadinglazy。搭配显式尺寸防止 CLS懒加载与width/height是强绑定关系。规则文档指出Withoutwidthandheight, lazy-loaded images cause layout shift (CLS) when they eventually load.原因在于懒加载图片在进入视口那一刻才下载完成并渲染如果浏览器之前不知道它的尺寸就会先占 0 高度、加载完成后再把布局顶开造成可测量的布局偏移CLS。!-- ❌ Bad: No dimensions → layout shifts when image loads into view -- img srcarticle-photo.jpg altArticle photo loadinglazy !-- ✅ Good: Dimensions reserved, no shift when loading triggers -- img srcarticle-photo.jpg altArticle photo width800 height450 loadinglazy 为什么显式尺寸能防偏移仓库中配套的 dimensions 规则 给出了底层机制现代浏览器Chrome 79、Firefox 71、Safari 15会自动从 HTML 的width和height属性推导出aspect-ratio浏览器内部等效于应用了img { aspect-ratio: attr(width) / attr(height); }也就是说只要属性存在即使在 CSS 加载完成之前浏览器也能按比例预留空间。配合 CSS 的max-width: 100%; height: auto;即可在保持响应式的同时不产生偏移img { max-width: 100%; height: auto; /* Overrides the height attribute for responsive scaling */ }关于 CLS 的量化标准dimensions 规则 还提供了重要背景CLS 得分高于 0.1 即被视为需改进高于 0.25 即为差。picture元素与懒加载的正确组合当使用picture提供 AVIF/WebP 等自适应格式时规则文档给出了一个极易犯错的关键细节Addloadinglazyto theimgelement insidepicture, not thesourceelements.loading属性必须加在picture内部的img上而不是source上——因为真正负责渲染和加载的是img回退元素source只负责候选资源的选择picture source typeimage/avif srcsetphoto-400.avif 400w, photo-800.avif 800w sizes(max-width: 600px) 100vw, 50vw source typeimage/webp srcsetphoto-400.webp 400w, photo-800.webp 800w sizes(max-width: 600px) 100vw, 50vw img srcphoto-800.jpg srcsetphoto-400.jpg 400w, photo-800.jpg 800w sizes(max-width: 600px) 100vw, 50vw altPhoto description width800 height600 loadinglazy !-- Goes on the img, not source -- decodingasync /picture注意这里width800 height600仍然保留再次印证了上一条显式尺寸规则的组合必要性。此外仓库的 offscreen-lazy 规则元数据 中把srcset列为关联规则二者同属images/performance区域实践中经常一起审查。框架落地React 与 Next.js规则文档提供了 React 与 Next.js 两种框架示例这里给出完整可运行的版本。React封装一个可控优先级的OptimizedImage核心思路是把是否优先级抽象成priorityprop组件内部据此决定loading与fetchPriorityinterface ImageProps { src: string alt: string width: number height: number priority?: boolean } function OptimizedImage({ src, alt, width, height, priority false }: ImageProps) { return ( img src{src} alt{alt} width{width} height{height} // priority images load eagerly with high fetchpriority loading{priority ? eager : lazy} fetchPriority{priority ? high : auto} decodingasync / ) } // Usage OptimizedImage srchero.jpg altHero width{1200} height{600} priority / OptimizedImage srcproduct.jpg altProduct width{400} height{300} /这样在调用侧就形成了强制约束首屏关键图必须显式传priority其余图片默认走懒加载。Next.jsnext/image的默认行为与prioritypropimport Image from next/image // next/image applies loadinglazy by default // Use priority prop to disable lazy loading for LCP images function Gallery({ images }) { return ( div {images.map((img, index) ( Image key{img.id} src{img.src} alt{img.alt} width{800} height{600} priority{index 0} // Only first image loads eagerly sizes(max-width: 768px) 100vw, 50vw / ))} /div ) }Next.js 的next/image组件默认就是懒加载自动添加loadinglazy并把loadingeager与fetchPriorityhigh一起封装在priorityprop 中——首图传priority其余交给默认行为天然符合本规则首屏 eager、其余 lazy的要求。值得一提的是Front-End-Checklist 的 Web 应用自身 就采用了next/image并配置了完整的图片优化管线可作为实战参考// Performance optimizations images: { formats: [image/avif, image/webp], deviceSizes: [640, 828, 1200, 1920], imageSizes: [32, 64, 128, 256], remotePatterns: [ { protocol: https, hostname: avatars.githubusercontent.com, pathname: /** }, { protocol: https, hostname: images.opencollective.com, pathname: /** } ] }配置要点formats声明了 AVIF/WebP 自动协商格式deviceSizes/imageSizes定义了 srcset 的候选宽度档位remotePatterns白名单化外部图片来源域名。实际组件中的用法可以看 profile-account-card.tsx/(account)/profile/profile-account-card.tsx)其中头像即使用了next/image并显式给出width{64} height{64}Image src{user.image} alt width{64} height{64} classNamerounded-full /这印证了规则的两个要点next/image默认懒加载 组件强制要求显式尺寸。浏览器如何判定接近视口规则文档给出了一个常被误解的机制浏览器并不是在图片刚进入视口时才加载而是使用一个基于网络速度的距离阈值——网络越慢阈值越大越早开始加载以补偿较慢的下载速度。Per the HTML spec, the exact threshold is implementation-defined. Chromiums thresholds range from 1250px on a slow connection to 2500px on a fast connection.依据 HTML Living Standard外部规范链接正文中不再展开具体阈值由浏览器实现自行决定Chromium 的阈值范围为慢速连接 1250px 到快速连接 2500px。也就是说懒是相对的——浏览器会在图片进入这个预加载带时就开始下载而非滚动到可见才下载。自定义方案Intersection Observer 回退规则文档明确表示大多数现代场景下原生loadinglazy已足够JavaScript 方案仅在需要自定义行为如自定义交叉边距rootMargin时才需要。文档提供了标准回退实现// Only needed if you need custom lazy loading behaviour // Native loadinglazy is preferred for standard use cases const observer new IntersectionObserver( (entries) { entries.forEach(entry { if (entry.isIntersecting) { const img entry.target img.src img.dataset.src if (img.dataset.srcset) { img.srcset img.dataset.srcset } observer.unobserve(img) } }) }, { rootMargin: 200px } // Start loading 200px before entering viewport ) document.querySelectorAll(img[data-src]).forEach(img observer.observe(img))要点真实地址存放在data-src/data-srcset进入视口含rootMargin: 200px预加载带后写入src并在加载后unobserve解除观察避免重复触发。仓库中也有一个 Intersection Observer 的实际封装可以参考——use-intersection-in-view.ts 用useSyncExternalStore实现了一个观察元素是否进入视口的 React Hook其核心同样是IntersectionObserverentry.isIntersecting并优雅处理了IntersectionObserver未定义的环境回退const observer new IntersectionObserver( ([entry]) { storeRef.current.isInView entry.isIntersecting onStoreChange() }, { threshold } )这类 Hook 正是自定义懒加载行为的 React 侧实现形态可作为团队内部封装懒加载组件的起点。对 AI Agent 的审查指南Check / Fix / Explain这条规则在 Front-End-Checklist 中不仅面向人类开发者也面向 AI Agent仓库定位是 for humans and AI agents。SKILL.md 里为 Agent 定义了标准的审查流程其方法论同样适合人类 Code ReviewCheck检查扫描所有img识别三类问题——① 折线以下却缺少loadinglazy的图片② 折线以上却错误标记loadinglazy的图片hero、首张商品图、页头 logo③ 折线以下却显式写了loadingeager的图片。关键约束如果无法从代码片段推断折线位置不得把缺少 lazy报为缺陷——避免误报是规则元数据反复强调的原则aiContext字段明确写到只有能合理判断图片在屏外或非关键时缺失loadinglazy才算有效发现。Fix修复为折线以下图片补loadinglazy从 hero/logo/首屏图中移除loadinglazy确保所有懒加载图片带显式width/height对 LCP 图片加fetchpriorityhigh并移除loadinglazy最后对每个修改给出修正后的 HTML。Explain解释向开发者说明原生懒加载机制、阈值概念慢速连接约 1250px、对 TTI/带宽的收益以及绝不懒加载 LCP 图片的关键例外。验证与上线规则文档提供了完整的验证手段全部可在浏览器中直接执行自动化检查Automated Checks打开 Chrome DevTools →Network→ 按 Img 过滤 → 刷新并向下滚动图片应只在进入视口时出现在网络瀑布流中运行LighthouseDefer offscreen images 审计会标记可懒加载的图片使用 DevTools 的Coverage面板查看被推迟的数据量在 Lighthouse 报告中确认 LCP 图片没有被标记为loadinglazy。手动检查Manual Checks在具有代表性的浏览器或运行时流程中手动验证最终渲染行为与用户体验。支持注意事项Support Notes规则文档还留下两条上线提醒图片格式与投递行为会因浏览器、CDN 和设备特性而异需在支持矩阵中核对最终字节数与渲染输出当现代格式或懒加载行为无法覆盖所有目标浏览器时补充回退说明此时可考虑上文 Intersection Observer 方案作为降级路径。关联规则地图在仓库的规则体系中offscreen-lazy 与以下规则构成图片性能审查面元数据中的relatedRules明确列出关联规则关联原因dimensions懒加载图片必须带width/height防止加载时布局偏移largest-contentful-paintLCP 图片绝不能懒加载只有折线以下图片才应延迟srcset二者同属images/performance区域常被一起审查critical-images与优先加载关键图片互为镜像一端保 LCP 立即加载一端推迟其余图片实践建议是把这组规则作为一次图片性能审查的完整套餐先定 LCP 关键图eager high priority再定折线以下图片lazy 显式尺寸最后用 srcset/picture做自适应格式整体走一遍 DevTools Network 瀑布流 Lighthouse 审计即可闭环。总结offscreen-lazy规则用一句话概括就是首屏的立即加载屏外的按需加载——用原生loadinglazy一个属性省下首屏数 MB 传输同时守住三条红线不懒加载 LCP、必须带显式尺寸、picture中属性加在img上。它在 Front-End-Checklist 中由 规则文档、Agent SKILL 与 参考实现 三层构成既适合人类开发者对照自查也能作为 AI Agent 审查前端代码的可执行规范是页面性能优化中投入产出比最高的改动之一。【免费下载链接】Front-End-Checklist The essential checklist for modern web development, for humans and AI agents项目地址: https://gitcode.com/gh_mirrors/fr/Front-End-Checklist创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表