[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"categories-en":3,"post:\u002Fpost\u002Flazy-loading-load-less-to-deliver-more":37},[4,11,17,24,30],{"id":5,"slug":6,"name":7,"colorHex":8,"iconName":9,"postCount":10},"0e2c1225-f78a-4c20-8c93-998ab9dc93b9","frontend","Frontend","#40484f",null,25,{"id":12,"slug":13,"name":14,"colorHex":15,"iconName":9,"postCount":16},"bc8df70e-b7fb-4d89-a80c-fd458d36d58c","code-development","Code & Development","#8b5cf6",23,{"id":18,"slug":19,"name":20,"colorHex":21,"iconName":22,"postCount":23},"550e8400-e29b-41d4-a716-446655440001","inteligencia-artificial","Artificial Intelligence","#6366f1","brain",14,{"id":25,"slug":26,"name":27,"colorHex":28,"iconName":9,"postCount":29},"ea63b69c-2eb4-4100-81f3-70ce52d33743","tech-news","Tech News","#e50606",4,{"id":31,"slug":32,"name":33,"colorHex":34,"iconName":35,"postCount":36},"550e8400-e29b-41d4-a716-446655440017","how-to-guides","How-To & Guides","#be123c","book-open",2,{"post":38,"related":893,"translations":956,"resolved":9},{"id":39,"slug":40,"title":41,"excerpt":42,"image":43,"featured":44,"groupId":45,"publishedAt":46,"readingTime":47,"views":48,"author":49,"category":51,"tags":52,"contentJson":65,"metaTitle":41,"metaDescription":891,"updatedAt":892},"98f6dff5-36ab-4c11-88cc-9303210f5558","lazy-loading-load-less-to-deliver-more","Lazy Loading: load less to deliver more","The web has never been so fast, yet never swallowed so many megabytes. The way out isn't speeding up delivery, but deferring what doesn't matter now.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1781223190438-featured-0vuabu.webp",false,"9d929438-44e5-45d5-9fae-0c0575255130","2026-06-16T01:28:29.299376+00:00",13,0,{"name":50,"avatar":9},"Genildo Souza",{"slug":6,"name":7,"color":8},[53,56,59,62],{"slug":54,"name":55},"css","CSS",{"slug":57,"name":58},"javascript","JavaScript",{"slug":60,"name":61},"nextjs","Next.js",{"slug":63,"name":64},"typescript","TypeScript",{"type":66,"content":67},"doc",[68,81,87,93,95,102,109,121,172,178,184,196,243,249,250,256,262,281,300,312,320,332,344,352,370,376,394,401,407,415,444,450,462,474,480,504,525,526,532,538,544,562,569,575,608,614,632,638,644,650,656,657,663,669,687,716,727,733,745,751,767,773,791,797,809,810,816,826,845,857,858,864,870,882,883],{"type":69,"attrs":70,"content":72},"paragraph",{"id":71},"p_nqhdgymd",[73,76],{"text":74,"type":75},"There is a paradox at the heart of the modern web: we have never had such fast connections, and pages have never been so heavy. The average weight of a web page surpassed 2 MB years ago and continues to grow, driven by high-resolution images, ever-larger JavaScript bundles, custom fonts, embedded videos, and third-party scripts. Software engineering's response to this problem was not merely to compress more or transmit faster — it was to question a fundamental premise: ","text",{"text":77,"type":75,"marks":78},"why load everything at once?",[79],{"type":80},"italic",{"type":69,"attrs":82,"content":84},{"id":83},"p_7jrr8vl9",[85],{"text":86,"type":75},"Lazy loading (or on-demand loading) is the materialization of that question. Instead of downloading, processing, and rendering all of an application's resources at the initial moment, lazy loading defers the loading of each resource until the instant it becomes necessary — when the user scrolls the page to an image, navigates to a route, opens a modal, or interacts with a component. What began as a niche optimization for photo galleries has become an architectural pattern present in virtually all modern frameworks, browsers, and platforms.",{"type":69,"attrs":88,"content":90},{"id":89},"p_mm77di1m",[91],{"text":92,"type":75},"This article examines lazy loading in depth: its technical fundamentals, its relationship with the performance metrics that govern the current web, its pitfalls, and the trends that are redefining its limits.",{"type":94},"horizontalRule",{"type":96,"attrs":97,"content":99},"heading",{"id":98,"level":36},"h_2sa8v3l8",[100],{"text":101,"type":75},"Part 1 — The problem: the real cost of loading everything",{"type":96,"attrs":103,"content":106},{"id":104,"level":105},"h_appq7edj",3,[107],{"text":108,"type":75},"The critical rendering path",{"type":69,"attrs":110,"content":112},{"id":111},"p_hs21hr6x",[113,115,119],{"text":114,"type":75},"When a browser loads a page, it traverses what we call ",{"text":116,"type":75,"marks":117},"critical rendering path",[118],{"type":80},{"text":120,"type":75},": downloads the HTML, discovers the referenced resources (CSS, JavaScript, images, fonts), downloads them, builds the DOM tree and the CSSOM tree, executes scripts, calculates the layout, and finally paints the pixels on the screen. Each resource added to this path has three distinct costs:",{"type":122,"attrs":123,"content":127},"orderedList",{"id":124,"type":9,"start":125,"tight":126},"ol_zrjkczh5",1,true,[128,144,158],{"type":129,"attrs":130,"content":132},"listItem",{"id":131},"li_kok7mwdh",[133],{"type":69,"attrs":134,"content":136},{"id":135},"p_jv98vd3t",[137,142],{"text":138,"type":75,"marks":139},"Network cost",[140],{"type":141},"bold",{"text":143,"type":75}," — bytes transferred, which consume bandwidth, time, and, on mobile data plans, the user's money.",{"type":129,"attrs":145,"content":147},{"id":146},"li_ybsi8kfx",[148],{"type":69,"attrs":149,"content":151},{"id":150},"p_vxfysadt",[152,156],{"text":153,"type":75,"marks":154},"Processing cost",[155],{"type":141},{"text":157,"type":75}," — JavaScript needs to be parsed, compiled, and executed; images need to be decoded. On entry-level mobile devices, parsing 1 MB of JavaScript can take more than one second of blocked CPU.",{"type":129,"attrs":159,"content":161},{"id":160},"li_2xfp3vqc",[162],{"type":69,"attrs":163,"content":165},{"id":164},"p_aoxe13x5",[166,170],{"text":167,"type":75,"marks":168},"Memory cost",[169],{"type":141},{"text":171,"type":75}," — each decoded image, each mounted component, and each registered listener occupies RAM, a scarce resource on modest devices.",{"type":69,"attrs":173,"content":175},{"id":174},"p_me9pb145",[176],{"text":177,"type":75},"The central insight of lazy loading is that a large part of these costs is wasted. Telemetry studies consistently show that a significant fraction of images loaded on web pages never enters the viewport — the user simply doesn't scroll to them. The same holds for code: most sessions in a SPA (Single Page Application) visit only two or three routes, but the traditional bundle loads the code for all of them.",{"type":96,"attrs":179,"content":181},{"id":180,"level":105},"h_c71fnczg",[182],{"text":183,"type":75},"The tyranny of the first impression",{"type":69,"attrs":185,"content":187},{"id":186},"p_mkwcw7uv",[188,190,194],{"text":189,"type":75},"The problem is aggravated by the fact that the first seconds of loading are disproportionately important. User behavior research shows that the probability of abandonment rises sharply with each additional second of waiting. Google formalized this reality in the ",{"text":191,"type":75,"marks":192},"Core Web Vitals",[193],{"type":141},{"text":195,"type":75},", metrics that directly influence search ranking:",{"type":197,"attrs":198,"content":200},"bulletList",{"id":199,"tight":126},"ul_v1k2g79e",[201,215,229],{"type":129,"attrs":202,"content":204},{"id":203},"li_u6mqq86q",[205],{"type":69,"attrs":206,"content":208},{"id":207},"p_u5n32l0r",[209,213],{"text":210,"type":75,"marks":211},"LCP (Largest Contentful Paint)",[212],{"type":141},{"text":214,"type":75}," — how long it takes for the largest visible element to be rendered. Target: below 2.5 seconds.",{"type":129,"attrs":216,"content":218},{"id":217},"li_dh4cuwjl",[219],{"type":69,"attrs":220,"content":222},{"id":221},"p_ij1t3nxw",[223,227],{"text":224,"type":75,"marks":225},"INP (Interaction to Next Paint)",[226],{"type":141},{"text":228,"type":75}," — how responsive the page is to user interactions. Target: below 200 ms.",{"type":129,"attrs":230,"content":232},{"id":231},"li_1uk78p93",[233],{"type":69,"attrs":234,"content":236},{"id":235},"p_vm1hezz4",[237,241],{"text":238,"type":75,"marks":239},"CLS (Cumulative Layout Shift)",[240],{"type":141},{"text":242,"type":75}," — how much the layout \"shifts\" during loading. Target: below 0.1.",{"type":69,"attrs":244,"content":246},{"id":245},"p_67b3ufuu",[247],{"text":248,"type":75},"Lazy loading directly affects all three. By removing non-critical resources from the initial path, it frees up bandwidth and CPU for the content that matters (improves LCP); by reducing the JavaScript executed during loading, it frees the main thread (improves INP); and, when poorly implemented, it can cause layout shifts (worsens CLS) — one of the pitfalls we'll see ahead.",{"type":94},{"type":96,"attrs":251,"content":253},{"id":252,"level":36},"h_yg0h05hq",[254],{"text":255,"type":75},"Part 2 — Anatomy of lazy loading",{"type":96,"attrs":257,"content":259},{"id":258,"level":105},"h_mzggkhyi",[260],{"text":261,"type":75},"Lazy loading of images: from scroll listener to native attribute",{"type":69,"attrs":263,"content":265},{"id":264},"p_h2raof7c",[266,268,273,275,279],{"text":267,"type":75},"The history of lazy loading of images is a good synthesis of the evolution of the web platform. In the first generation (2000s and early 2010s), developers used scroll listeners that manually calculated the position of each image relative to the viewport — a functional, but costly approach, as each scroll event triggered synchronous layout calculations (",{"text":269,"type":75,"marks":270},"getBoundingClientRect",[271],{"type":272},"code",{"text":274,"type":75},")",{"text":276,"type":75,"marks":277},"layout thrashing",[278],{"type":80},{"text":280,"type":75},").",{"type":282,"attrs":283},"speedCards",{"id":284,"cards":285,"title":298,"caption":299},"speed_rfgrcdc9",[286,290,294],{"label":287,"value":288,"detail":289},"Manual scroll","1st generation","Listeners calculavam offset a cada evento de scroll, forçando cálculos síncronos de layout e causando jank.",{"label":291,"value":292,"detail":293},"Intersection Observer","2nd generation","Delegação assíncrona ao navegador para detectar entrada no viewport, com rootMargin que antecipa o download.",{"label":295,"value":296,"detail":297},"Native attribute","3rd generation","Atributo loading=\"lazy\" elimina scripts. O navegador aplica heurísticas adaptativas de distância por tipo de conexão.","Evolution of image lazy loading","From manual position calculation to native and automated browser delegation.",{"type":69,"attrs":301,"content":303},{"id":302},"p_9hxfad05",[304,306,310],{"text":305,"type":75},"The second generation arrived with the ",{"text":307,"type":75,"marks":308},"Intersection Observer API",[309],{"type":141},{"text":311,"type":75},", which delegates to the browser the task of observing when an element enters the viewport, asynchronously and efficiently:",{"type":313,"attrs":314,"content":317},"codeBlock",{"id":315,"language":57,"highlighted":316},"code_zdy1jl2n","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> observer\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> new\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> IntersectionObserver\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">((\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">entries\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  entries.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">forEach\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">((\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">entry\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (entry.isIntersecting) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">      const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> img\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> entry.target;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      img.src \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> img.dataset.src;       \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F troca o placeholder pela imagem real\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      observer.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">unobserve\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(img);          \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F para de observar após carregar\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  });\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}, {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  rootMargin: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"200px 0px\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">               \u002F\u002F começa a carregar 200px antes de entrar na tela\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">document.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">querySelectorAll\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"img[data-src]\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">).\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">forEach\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">((\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">img\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> observer.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">observe\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(img));\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[318],{"text":319,"type":75},"const observer = new IntersectionObserver((entries) => {\n  entries.forEach((entry) => {\n    if (entry.isIntersecting) {\n      const img = entry.target;\n      img.src = img.dataset.src;       \u002F\u002F troca o placeholder pela imagem real\n      observer.unobserve(img);          \u002F\u002F para de observar após carregar\n    }\n  });\n}, {\n  rootMargin: \"200px 0px\"               \u002F\u002F começa a carregar 200px antes de entrar na tela\n});\n\ndocument.querySelectorAll(\"img[data-src]\").forEach((img) => observer.observe(img));\n",{"type":69,"attrs":321,"content":323},{"id":322},"p_2dspvqtz",[324,326,330],{"text":325,"type":75},"The parameter ",{"text":327,"type":75,"marks":328},"rootMargin",[329],{"type":272},{"text":331,"type":75}," is the soul of this technique: it creates a margin of anticipation, initiating the download before the user reaches the image, so that the content is already ready when it enters the scene. It is the balance between laziness and anticipation that defines good lazy loading.",{"type":69,"attrs":333,"content":335},{"id":334},"p_u6tn9fhy",[336,338,342],{"text":337,"type":75},"The third generation eliminated JavaScript completely. Since 2019\u002F2020, browsers support lazy loading ",{"text":339,"type":75,"marks":340},"native",[341],{"type":141},{"text":343,"type":75},":",{"type":313,"attrs":345,"content":349},{"id":346,"language":347,"highlighted":348},"code_6hfmkmj3","html","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#22863A;--shiki-dark:#85E89D\">img\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> src\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"foto.webp\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> alt\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"Descrição da foto\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> loading\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"lazy\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> width\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"800\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> height\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"600\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#22863A;--shiki-dark:#85E89D\">iframe\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> src\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"https:\u002F\u002Fexemplo.com\u002Fvideo\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> loading\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"lazy\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> title\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"Vídeo\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>&#x3C;\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#22863A;--shiki-dark:#85E89D\">iframe\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[350],{"text":351,"type":75},"\u003Cimg src=\"foto.webp\" alt=\"Descrição da foto\" loading=\"lazy\" width=\"800\" height=\"600\">\n\u003Ciframe src=\"https:\u002F\u002Fexemplo.com\u002Fvideo\" loading=\"lazy\" title=\"Vídeo\">\u003C\u002Fiframe>\n",{"type":69,"attrs":353,"content":355},{"id":354},"p_6rm65wsg",[356,358,362,364,368],{"text":357,"type":75},"A single attribute, zero dependencies, distance heuristics managed by the browser itself (which considers the user's connection type). Note the attributes ",{"text":359,"type":75,"marks":360},"width",[361],{"type":272},{"text":363,"type":75}," and ",{"text":365,"type":75,"marks":366},"height",[367],{"type":272},{"text":369,"type":75},": they allow the browser to reserve the image's space before loading, preventing layout shifts — a small detail with huge impact on CLS.",{"type":96,"attrs":371,"content":373},{"id":372,"level":105},"h_kej0vtqd",[374],{"text":375,"type":75},"Lazy loading of code: code splitting and dynamic import",{"type":69,"attrs":377,"content":379},{"id":378},"p_lliotfsv",[380,382,386,388,392],{"text":381,"type":75},"If images were the first target, JavaScript became the most important. ECMAScript introduced the ",{"text":383,"type":75,"marks":384},"import()",[385],{"type":272},{"text":387,"type":75}," dynamic, which returns a Promise and instructs the bundler (Webpack, Vite, Rollup, esbuild) to split the module into a ",{"text":389,"type":75,"marks":390},"chunk",[391],{"type":80},{"text":393,"type":75}," independent, downloaded only when the function is called:",{"type":313,"attrs":395,"content":398},{"id":396,"language":57,"highlighted":397},"code_razxe7dr","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Em vez de importar no topo do arquivo (carregamento imediato):\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F import { gerarRelatorioPDF } from \".\u002Frelatorios\";\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F Importa apenas quando o usuário clica no botão:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">botaoExportar.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">addEventListener\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"click\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">async\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> () \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">gerarRelatorioPDF\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\".\u002Frelatorios\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">  gerarRelatorioPDF\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(dados);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[399],{"text":400,"type":75},"\u002F\u002F Em vez de importar no topo do arquivo (carregamento imediato):\n\u002F\u002F import { gerarRelatorioPDF } from \".\u002Frelatorios\";\n\n\u002F\u002F Importa apenas quando o usuário clica no botão:\nbotaoExportar.addEventListener(\"click\", async () => {\n  const { gerarRelatorioPDF } = await import(\".\u002Frelatorios\");\n  gerarRelatorioPDF(dados);\n});\n",{"type":69,"attrs":402,"content":404},{"id":403},"p_l4ldin7r",[405],{"text":406,"type":75},"Frameworks built elegant abstractions on top of this mechanism. In React:",{"type":313,"attrs":408,"content":412},{"id":409,"language":410,"highlighted":411},"code_16d91lku","jsx","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { lazy, Suspense } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> \"react\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F O componente Dashboard só é baixado quando renderizado pela primeira vez\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> Dashboard\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> lazy\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(() \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\".\u002Fpages\u002FDashboard\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">));\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">function\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> App\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">() {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    &#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">Suspense\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> fallback\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">{&#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">TelaDeCarregamento\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> \u002F>}>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">      &#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">Dashboard\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> \u002F>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    &#x3C;\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">Suspense\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  );\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[413],{"text":414,"type":75},"import { lazy, Suspense } from \"react\";\n\n\u002F\u002F O componente Dashboard só é baixado quando renderizado pela primeira vez\nconst Dashboard = lazy(() => import(\".\u002Fpages\u002FDashboard\"));\n\nfunction App() {\n  return (\n    \u003CSuspense fallback={\u003CTelaDeCarregamento \u002F>}>\n      \u003CDashboard \u002F>\n    \u003C\u002FSuspense>\n  );\n}\n",{"type":69,"attrs":416,"content":418},{"id":417},"p_zdh6oirw",[419,421,425,427,431,432,436,438,442],{"text":420,"type":75},"In Vue, ",{"text":422,"type":75,"marks":423},"defineAsyncComponent",[424],{"type":272},{"text":426,"type":75}," plays the same role; in Angular, routes with ",{"text":428,"type":75,"marks":429},"loadChildren",[430],{"type":272},{"text":363,"type":75},{"text":433,"type":75,"marks":434},"loadComponent",[435],{"type":272},{"text":437,"type":75}," perform route-based code splitting declaratively. The dominant pattern is the ",{"text":439,"type":75,"marks":440},"route-based splitting",[441],{"type":141},{"text":443,"type":75},": each route of the application turns into a chunk, and the user downloads only the code of the pages they actually visit.",{"type":96,"attrs":445,"content":447},{"id":446,"level":105},"h_l3lcy2mu",[448],{"text":449,"type":75},"Lazy loading of data: pagination, infinite scroll, and virtualization",{"type":69,"attrs":451,"content":453},{"id":452},"p_tfr0z3wd",[454,456,460],{"text":455,"type":75},"The same philosophy applies to data. Rather than fetching a thousand records from an API, a page of twenty is fetched and the rest is loaded as the user advances — whether through explicit pagination, or through ",{"text":457,"type":75,"marks":458},"infinite scroll",[459],{"type":80},{"text":461,"type":75}," (frequently implemented with the same Intersection Observer, observing a sentinel element at the end of the list).",{"type":69,"attrs":463,"content":465},{"id":464},"p_2e1n7ii3",[466,468,472],{"text":467,"type":75},"Virtualization (with libraries like TanStack Virtual or react-window) takes the concept to the extreme: even data already loaded is only ",{"text":469,"type":75,"marks":470},"rendered",[471],{"type":80},{"text":473,"type":75}," when visible. A list of ten thousand items keeps in the DOM only the few dozen that fit on the screen, recycling elements as the user scrolls. It is lazy loading applied not to the network, but to rendering.",{"type":96,"attrs":475,"content":477},{"id":476,"level":105},"h_71lwihh3",[478],{"text":479,"type":75},"Lazy loading in other layers",{"type":69,"attrs":481,"content":483},{"id":482},"p_qgl13rhw",[484,486,490,492,496,498,502],{"text":485,"type":75},"The pattern permeates the entire stack. In ORMs like SQLAlchemy and Hibernate, relationships are loaded on demand by default (with the famous risk of the ",{"text":487,"type":75,"marks":488},"N+1 problem",[489],{"type":80},{"text":491,"type":75},", when a loop fires a query per item). In languages, lazy generators and iterators (Python, Haskell, and Java streams) compute values only when consumed. In operating systems, the ",{"text":493,"type":75,"marks":494},"demand paging",[495],{"type":80},{"text":497,"type":75}," loads memory pages from executables only when accessed. Lazy loading is not a front-end technique: it is an engineering principle — ",{"text":499,"type":75,"marks":500},"defer work until it is demonstrably necessary",[501],{"type":80},{"text":503,"type":75},".",{"type":282,"attrs":505},{"id":506,"cards":507,"title":479,"caption":524},"speed_57fgmrs4",[508,512,516,520],{"label":509,"value":510,"detail":511},"SQLAlchemy \u002F Hibernate","ORMs","Relacionamentos carregados sob demanda, com risco de queries N+1 quando iterados em loops.",{"label":513,"value":514,"detail":515},"Python \u002F Haskell \u002F Java","Languages","Geradores e iteradores preguiçosos computam valores apenas no momento do consumo.",{"label":517,"value":518,"detail":519},"Operating system","OS","Demand paging traz páginas de memória de executáveis apenas quando acessadas.",{"label":521,"value":522,"detail":523},"TanStack Virtual \u002F react-window","Virtualization","Dados já carregados só renderizam quando visíveis no viewport, reciclando nós no scroll.","Engineering principle: defer work until it is demonstrably necessary.",{"type":94},{"type":96,"attrs":527,"content":529},{"id":528,"level":36},"h_m6vcijf4",[530],{"text":531,"type":75},"Part 3 — The pitfalls: when laziness costs dearly",{"type":69,"attrs":533,"content":535},{"id":534},"p_g8tes3hu",[536],{"text":537,"type":75},"No technique is free, and poorly applied lazy loading can degrade exactly the metrics it intends to improve.",{"type":96,"attrs":539,"content":541},{"id":540,"level":105},"h_9qs1acui",[542],{"text":543,"type":75},"The cardinal error: lazy loading critical content",{"type":69,"attrs":545,"content":547},{"id":546},"p_d1po9k5g",[548,550,554,556,560],{"text":549,"type":75},"The most common and most harmful trap is applying ",{"text":551,"type":75,"marks":552},"loading=\"lazy\"",[553],{"type":272},{"text":555,"type":75}," to the hero's main image — precisely the element that is usually the page's LCP. The browser, instructed to deprioritize the image, delays its download, and the LCP worsens drastically. The rule is crystal clear: ",{"text":557,"type":75,"marks":558},"above-the-fold content must never be lazy",[559],{"type":141},{"text":561,"type":75},". For the LCP element, the correct approach is the opposite — prioritize it aggressively:",{"type":313,"attrs":563,"content":566},{"id":564,"language":347,"highlighted":565},"code_azapf8qe","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#22863A;--shiki-dark:#85E89D\">img\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> src\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"hero.webp\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> alt\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"Banner principal\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> fetchpriority\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"high\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> width\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"1200\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> height\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"600\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#22863A;--shiki-dark:#85E89D\">link\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> rel\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"preload\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> as\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"image\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> href\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"hero.webp\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">>\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[567],{"text":568,"type":75},"\u003Cimg src=\"hero.webp\" alt=\"Banner principal\" fetchpriority=\"high\" width=\"1200\" height=\"600\">\n\u003Clink rel=\"preload\" as=\"image\" href=\"hero.webp\">\n",{"type":96,"attrs":570,"content":572},{"id":571,"level":105},"h_cggqr7pt",[573],{"text":574,"type":75},"Layout shifts and the importance of reserving space",{"type":69,"attrs":576,"content":578},{"id":577},"p_31hoem3o",[579,581,584,586,589,591,595,597,601,603,607],{"text":580,"type":75},"When a lazy image loads and pushes content down, the user who was reading loses their position — and CLS spikes. Prevention is simple and mandatory: always declare dimensions (",{"text":359,"type":75,"marks":582},[583],{"type":272},{"text":585,"type":75},"\u002F",{"text":365,"type":75,"marks":587},[588],{"type":272},{"text":590,"type":75}," or ",{"text":592,"type":75,"marks":593},"aspect-ratio",[594],{"type":272},{"text":596,"type":75}," in CSS) so that space is reserved before loading. The same applies to lazy components: the ",{"text":598,"type":75,"marks":599},"fallback",[600],{"type":272},{"text":602,"type":75}," of Suspense must have dimensions close to those of the final component (hence the popularity of ",{"text":604,"type":75,"marks":605},"skeleton screens",[606],{"type":80},{"text":280,"type":75},{"type":96,"attrs":609,"content":611},{"id":610,"level":105},"h_nxax5tmb",[612],{"text":613,"type":75},"Loading cascades (waterfalls)",{"type":69,"attrs":615,"content":617},{"id":616},"p_bk1caylx",[618,620,624,626,630],{"text":619,"type":75},"Chained lazy loading creates serial waits: the route loads, which then discovers it needs a component, which then discovers it needs data. Each link adds a network round trip. Modern frameworks attack this problem with ",{"text":621,"type":75,"marks":622},"preloading",[623],{"type":80},{"text":625,"type":75}," intelligent — loading the next route when the user hovers over the link (a strategy popularized by Remix and by ",{"text":627,"type":75,"marks":628},"quicklink",[629],{"type":272},{"text":631,"type":75}," by Google) or in parallel with data (React Router loaders, for example).",{"type":96,"attrs":633,"content":635},{"id":634,"level":105},"h_6qand2uv",[636],{"text":637,"type":75},"SEO and content discovery",{"type":69,"attrs":639,"content":641},{"id":640},"p_ovr28g12",[642],{"text":643,"type":75},"Content loaded only after interaction may be invisible to crawlers. Googlebot renders JavaScript and processes Intersection Observer, but content behind clicks or custom scroll events may not be indexed. The recommendation is to keep content essential for SEO in the initial HTML (via SSR or SSG) and reserve lazy loading for what is complementary.",{"type":96,"attrs":645,"content":647},{"id":646,"level":105},"h_x5hcmspf",[648],{"text":649,"type":75},"The cost of the transition",{"type":69,"attrs":651,"content":653},{"id":652},"p_p5e5f9j6",[654],{"text":655,"type":75},"Lazy loading trades initial load time for interaction latency. If the checkout modal chunk takes two seconds to download when the user clicks \"Buy\", the optimization turned into a loss at the most critical moment of the funnel. The answer is a hierarchy of priorities: critical conversion paths deserve preload; what is peripheral can wait.",{"type":94},{"type":96,"attrs":658,"content":660},{"id":659,"level":36},"h_8098xdb2",[661],{"text":662,"type":75},"Part 4 — Trends: where on-demand loading is heading",{"type":96,"attrs":664,"content":666},{"id":665,"level":105},"h_y1p156fo",[667],{"text":668,"type":75},"1. From lazy loading to \"lazy execution\": resumability and Islands",{"type":69,"attrs":670,"content":672},{"id":671},"p_rz8kgnd7",[673,675,679,681,685],{"text":674,"type":75},"The current frontier is no longer ",{"text":676,"type":75,"marks":677},"downloading",[678],{"type":80},{"text":680,"type":75}," less, but ",{"text":682,"type":75,"marks":683},"executing",[684],{"type":80},{"text":686,"type":75}," less. The cost of hydration — re-executing on the client all the JavaScript of a server-rendered page — has become the new bottleneck of SPAs. Two architectures tackle this problem:",{"type":69,"attrs":688,"content":690},{"id":689},"p_siidjyp7",[691,693,697,699,703,705,709,711,715],{"text":692,"type":75},"The ",{"text":694,"type":75,"marks":695},"Islands Architecture",[696],{"type":141},{"text":698,"type":75}," (popularized by Astro) treats the page as static HTML with \"islands\" of interactivity. Each island is hydrated independently and can be lazy: ",{"text":700,"type":75,"marks":701},"client:visible",[702],{"type":272},{"text":704,"type":75}," hydrates the component only when it enters the viewport, ",{"text":706,"type":75,"marks":707},"client:idle",[708],{"type":272},{"text":710,"type":75}," when the main thread is idle. It's lazy loading applied to ",{"text":712,"type":75,"marks":713},"interactivity",[714],{"type":80},{"text":503,"type":75},{"type":69,"attrs":717,"content":719},{"id":718},"p_5gib6vlk",[720,721,725],{"text":692,"type":75},{"text":722,"type":75,"marks":723},"resumability",[724],{"type":141},{"text":726,"type":75}," (central concept of Qwik) goes further: serializes the application state into HTML and eliminates hydration entirely. Each event handler is a tiny chunk, downloaded only when the event occurs. It's lazy loading taken to its logical conclusion — granularity at the function level, not the component or route level.",{"type":96,"attrs":728,"content":730},{"id":729,"level":105},"h_rm0gcqd9",[731],{"text":732,"type":75},"2. React Server Components and the shifting of code to the server",{"type":69,"attrs":734,"content":736},{"id":735},"p_glnk8cpx",[737,739,743],{"text":738,"type":75},"React Server Components (adopted by the Next.js App Router) represent another answer: components that run exclusively on the server send to the client only the rendered result — their code ",{"text":740,"type":75,"marks":741},"never",[742],{"type":80},{"text":744,"type":75}," is downloaded. Instead of deferring JavaScript loading, the need for it is eliminated. Client-side lazy loading then applies only to the genuinely interactive fraction of the application.",{"type":96,"attrs":746,"content":748},{"id":747,"level":105},"h_bdwx3y7c",[749],{"text":750,"type":75},"3. Lazy loading driven by real data and machine learning",{"type":69,"attrs":752,"content":754},{"id":753},"p_xosiz2ox",[755,757,760,762,766],{"text":756,"type":75},"The heuristic \"load when within 200px of the viewport\" is static. The trend is to make it adaptive: libraries such as ",{"text":627,"type":75,"marks":758},[759],{"type":272},{"text":761,"type":75}," already factor in connection quality (via Network Information API) and the user's data saver mode. Emerging research and tools use real browsing analytics to predict which routes a user will likely visit from the current page, doing probabilistic prefetch — loading ceases to be lazy or eager to become ",{"text":763,"type":75,"marks":764},"predictive",[765],{"type":80},{"text":503,"type":75},{"type":96,"attrs":768,"content":770},{"id":769,"level":105},"h_sz9vbfco",[771],{"text":772,"type":75},"4. The platform absorbing the pattern",{"type":69,"attrs":774,"content":776},{"id":775},"p_cbzmhwp8",[777,779,783,785,789],{"text":778,"type":75},"The history of image lazy loading — from hack with scroll listeners to native attribute — tends to repeat itself in other layers. APIs such as ",{"text":780,"type":75,"marks":781},"content-visibility: auto",[782],{"type":272},{"text":784,"type":75}," in CSS (which defers rendering of off-screen sections without any JavaScript), on-demand loading of compression dictionaries and the ",{"text":786,"type":75,"marks":787},"speculation rules",[788],{"type":80},{"text":790,"type":75}," for declarative prefetch\u002Fprerender indicate the direction: the browser increasingly assumes responsibility for intelligent resource orchestration, and the developer shifts to declaring intentions rather than implementing mechanisms.",{"type":96,"attrs":792,"content":794},{"id":793,"level":105},"h_2cisgr5c",[795],{"text":796,"type":75},"5. Sustainability: bytes not transferred are carbon not emitted",{"type":69,"attrs":798,"content":800},{"id":799},"p_phtabn1x",[801,803,807],{"text":802,"type":75},"An emerging motivation is environmental. Internet infrastructure accounts for a relevant slice of global electricity consumption, and every byte transferred has an energy cost in servers, networks, and devices. The ",{"text":804,"type":75,"marks":805},"sustainable web design",[806],{"type":80},{"text":808,"type":75}," positions lazy loading as an efficiency practice not merely economic, but ecological — loading only what is necessary is also a way to waste less energy at a planetary scale.",{"type":94},{"type":96,"attrs":811,"content":813},{"id":812,"level":36},"h_9dakj1i7",[814],{"text":815,"type":75},"Part 5 — Practical decision guide",{"type":69,"attrs":817,"content":819},{"id":818},"p_8pnbxev8",[820,822],{"text":821,"type":75},"The synthesis of everything discussed fits in one question per resource: ",{"text":823,"type":75,"marks":824},"is this resource necessary for the first impression or for the user's critical path?",[825],{"type":80},{"type":827,"attrs":828,"content":832},"callout",{"id":829,"type":830,"title":831},"call_x1awqoff","tip","Golden rule: is this resource necessary for the first impression?",[833,839],{"type":69,"attrs":834,"content":836},{"id":835},"p_x7ktp1k5",[837],{"text":838,"type":75},"For each resource, apply the central question: is it essential for the first impression or for the critical path? If yes — hero image, critical CSS, initial route code, main text fonts — load immediately and prioritize with fetchpriority=\"high\" or preload.",{"type":69,"attrs":840,"content":842},{"id":841},"p_rhc2hqrk",[843],{"text":844,"type":75},"If it is not essential — below-the-fold images, secondary routes, modals, chat widgets, video players, export libraries — defer with lazy loading. But keep three non-negotiable precautions: reserve layout space, anticipate loading with margin or preload on hover, and measure impact with real field data (CrUX, RUM) instead of laboratory tests.",{"type":69,"attrs":846,"content":848},{"id":847},"p_z1c8f6mi",[849,851,855],{"text":850,"type":75},"If yes — hero image, critical CSS, initial route code, main text fonts — the resource should be loaded immediately and, ideally, prioritized (",{"text":852,"type":75,"marks":853},"fetchpriority=\"high\"",[854],{"type":272},{"text":856,"type":75},", preload). If not — images below the fold, secondary routes, modals, chat widgets, video players, export libraries — the resource is a natural candidate for lazy loading, with three non-negotiable precautions: reserve layout space, anticipate loading with margin or preload on hover, and measure impact with real field data (CrUX, RUM) instead of just lab tests.",{"type":94},{"type":96,"attrs":859,"content":861},{"id":860,"level":36},"h_40v0xqzm",[862],{"text":863,"type":75},"Conclusion",{"type":69,"attrs":865,"content":867},{"id":866},"p_jbl9cu8r",[868],{"text":869,"type":75},"Lazy loading is the technical expression of an idea older than computing: don't do now what may never need to be done. Its trajectory — from photo gallery hack to native browser attribute, from image optimization to architectural principle that rewrites entire frameworks — illustrates how performance engineering evolves: identifying waste, deferring it, and finally eliminating it by design.",{"type":69,"attrs":871,"content":873},{"id":872},"p_kqf8ak03",[874,876,880],{"text":875,"type":75},"Trends point to a future where the term may disappear by becoming ubiquitous: when browsers orchestrate resources predictively, servers send only the computation result and interactivity is serialized into resumable fragments, ",{"text":877,"type":75,"marks":878},"every",[879],{"type":80},{"text":881,"type":75}," loading will be, to some degree, on demand. Laziness, well applied, will have won — not by doing less, but by doing only what matters, at the exact moment it matters.",{"type":94},{"type":69,"attrs":884,"content":886},{"id":885},"p_3qihhstn",[887],{"text":888,"type":75,"marks":889},"Article generated in June 2026. The techniques and APIs cited (Intersection Observer, loading=\\\"lazy\\\", content-visibility, dynamic import(), React Server Components, Islands Architecture) reflect the state of the web platform on that date.",[890],{"type":80},"Why load everything at once if most images never hit the screen? See how native lazy loading saves bytes, CPU, and improves LCP.","2026-08-24T14:53:53.315534+00:00",[894,910,925,939],{"id":895,"slug":896,"title":897,"excerpt":898,"image":899,"featured":44,"groupId":900,"publishedAt":901,"readingTime":902,"views":48,"author":903,"category":904,"tags":905},"841890b2-1a8c-43d4-b434-b94714705605","debugging-css-the-forgotten-margin-and-frontend-lessons","Debugging CSS: The Forgotten Margin and Frontend Lessons","A forgotten CSS property turned a minor layout glitch into a two-week ordeal. Learn how to avoid emotional debugging and fix complex UI issues faster.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1767745741814-featured-i6p1gc.jpeg","bcaf503a-15c1-4d28-8795-6ae3c2a3e06f","2026-08-02T16:09:35.153874+00:00",8,{"name":50,"avatar":9},{"slug":6,"name":7,"color":8},[906,907],{"slug":54,"name":55},{"slug":908,"name":909},"performance","Performance",{"id":911,"slug":912,"title":913,"excerpt":914,"image":915,"featured":44,"groupId":916,"publishedAt":917,"readingTime":23,"views":48,"author":918,"category":919,"tags":920},"d5167910-cc5b-4fae-a2e8-d09adcf354b2","stop-using-usememo-wrong-a-practical-guide-to-react-performance","Stop Using useMemo Wrong: A Practical Guide to React Performance","Master React useMemo with this guide. Learn when to memoize, how to fix dependency array bugs, and why over-optimization can hurt your performance.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1769657096789-featured-r2q2sb.jpeg","a1c571c1-aa37-404d-ac67-f265c8a9985b","2026-07-08T23:34:34.563653+00:00",{"name":50,"avatar":9},{"slug":6,"name":7,"color":8},[921,922],{"slug":57,"name":58},{"slug":923,"name":924},"react","React",{"id":926,"slug":927,"title":928,"excerpt":929,"image":930,"featured":44,"groupId":931,"publishedAt":932,"readingTime":933,"views":48,"author":934,"category":935,"tags":936},"f1b5af43-20da-4150-a7c7-ef17675d1fee","css-animations-how-to-build-performant-professional-interfaces-without-messy-code","CSS Animations: How to Build Performant, Professional Interfaces Without Messy Code","Bring your web interfaces to life. Learn when to use CSS transitions versus keyframes and how to optimize your animations for peak performance.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1770952624247-featured-in9pir.jpeg","de5a7726-1227-4080-b572-9d91a37b207b","2026-07-04T03:00:53.174696+00:00",17,{"name":50,"avatar":9},{"slug":6,"name":7,"color":8},[937,938],{"slug":54,"name":55},{"slug":908,"name":909},{"id":940,"slug":941,"title":942,"excerpt":943,"image":944,"featured":44,"groupId":945,"publishedAt":946,"readingTime":947,"views":48,"author":948,"category":949,"tags":950},"86e804a8-71f4-4985-a013-d6c033e28967","angular-micro-frontends-how-to-scale-large-applications-and-eliminate-monolithic-build-times-with-module-federation","Angular Micro-frontends: How to Scale Large Applications and Eliminate Monolithic Build Times with Module Federation","Discover how to break down large Angular monoliths using Module Federation to enable independent deployments and seamless team scaling.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1774499855857-featured-x9ugz1.jpg","a029aa9b-573b-4e5b-921b-eaecea6e989f","2026-06-21T06:41:59.230237+00:00",10,{"name":50,"avatar":9},{"slug":6,"name":7,"color":8},[951,954,955],{"slug":952,"name":953},"angular","Angular",{"slug":57,"name":58},{"slug":63,"name":64},{"pt":957,"en":40},"lazy-loading-carregar-menos-para-entregar-mais"]