[{"data":1,"prerenderedAt":1573},["ShallowReactive",2],{"guide-web-performance-basics":3},{"id":4,"title":5,"body":6,"date":1565,"description":1566,"extension":1567,"meta":1568,"navigation":462,"path":1569,"readingTime":538,"seo":1570,"stem":1571,"__hash__":1572},"guides\u002Fguides\u002Fweb-performance-basics.md","Web Performance Basics: From First Byte to Interactive",{"type":7,"value":8,"toc":1538},"minimark",[9,14,18,21,25,28,175,178,183,186,216,219,223,226,230,268,284,288,369,568,572,575,579,586,700,704,786,876,880,883,887,944,947,955,962,966,969,1105,1109,1112,1127,1130,1134,1137,1141,1232,1236,1239,1389,1392,1396,1466,1470,1498,1502,1523,1527,1535],[10,11,13],"h2",{"id":12},"why-performance-matters","Why Performance Matters",[15,16,17],"p",{},"Every 100 ms of delay costs you conversions. Google reports that 53% of mobile users abandon sites that take longer than 3 seconds to load. Performance is not a luxury — it is the foundation of user experience and search ranking.",[15,19,20],{},"This guide walks through the metrics, the rendering pipeline, and the strategies you need to ship fast pages.",[10,22,24],{"id":23},"core-performance-metrics","Core Performance Metrics",[15,26,27],{},"Modern performance measurement focuses on what users actually perceive. These are the metrics that matter:",[29,30,31,53],"table",{},[32,33,34],"thead",{},[35,36,37,41,44,47,50],"tr",{},[38,39,40],"th",{},"Metric",[38,42,43],{},"Full Name",[38,45,46],{},"Measures",[38,48,49],{},"Good",[38,51,52],{},"Poor",[54,55,56,74,90,107,124,141,158],"tbody",{},[35,57,58,62,65,68,71],{},[59,60,61],"td",{},"FP",[59,63,64],{},"First Paint",[59,66,67],{},"First pixel on screen",[59,69,70],{},"≤ 1 s",[59,72,73],{},"> 3 s",[35,75,76,79,82,85,88],{},[59,77,78],{},"FCP",[59,80,81],{},"First Contentful Paint",[59,83,84],{},"First text or image renders",[59,86,87],{},"≤ 1.8 s",[59,89,73],{},[35,91,92,95,98,101,104],{},[59,93,94],{},"LCP",[59,96,97],{},"Largest Contentful Paint",[59,99,100],{},"Main content visible",[59,102,103],{},"≤ 2.5 s",[59,105,106],{},"> 4 s",[35,108,109,112,115,118,121],{},[59,110,111],{},"TTI",[59,113,114],{},"Time to Interactive",[59,116,117],{},"Page responds to input",[59,119,120],{},"≤ 3.8 s",[59,122,123],{},"> 7.3 s",[35,125,126,129,132,135,138],{},[59,127,128],{},"CLS",[59,130,131],{},"Cumulative Layout Shift",[59,133,134],{},"Visual stability",[59,136,137],{},"≤ 0.1",[59,139,140],{},"> 0.25",[35,142,143,146,149,152,155],{},[59,144,145],{},"INP",[59,147,148],{},"Interaction to Next Paint",[59,150,151],{},"Input responsiveness",[59,153,154],{},"≤ 200 ms",[59,156,157],{},"> 500 ms",[35,159,160,163,166,169,172],{},[59,161,162],{},"TTFB",[59,164,165],{},"Time to First Byte",[59,167,168],{},"Server response speed",[59,170,171],{},"≤ 800 ms",[59,173,174],{},"> 1.8 s",[15,176,177],{},"Google's Core Web Vitals (LCP, CLS, INP) directly influence search rankings. If you track nothing else, track these three.",[179,180,182],"h3",{"id":181},"how-the-metrics-relate","How the Metrics Relate",[15,184,185],{},"Metrics fire in sequence:",[187,188,189,196,201,206,211],"ol",{},[190,191,192,195],"li",{},[193,194,162],"strong",{}," — Server responds",[190,197,198,200],{},[193,199,61],{}," — Browser paints the first pixel (often a blank screen)",[190,202,203,205],{},[193,204,78],{}," — First useful content appears (text, image, canvas)",[190,207,208,210],{},[193,209,94],{}," — Largest above-the-fold element finishes rendering",[190,212,213,215],{},[193,214,111],{}," — JavaScript event handlers attached, page is usable",[15,217,218],{},"Each metric depends on the previous one. A slow TTFB cascades into slow everything else.",[10,220,222],{"id":221},"the-critical-rendering-path","The Critical Rendering Path",[15,224,225],{},"The critical rendering path is the sequence of steps the browser takes to turn HTML, CSS, and JavaScript into pixels on screen.",[179,227,229],{"id":228},"step-by-step","Step-by-Step",[187,231,232,238,244,250,256,262],{},[190,233,234,237],{},[193,235,236],{},"Parse HTML"," → Build the DOM tree",[190,239,240,243],{},[193,241,242],{},"Fetch and parse CSS"," → Build the CSSOM tree",[190,245,246,249],{},[193,247,248],{},"Combine DOM + CSSOM"," → Render tree (visible nodes only)",[190,251,252,255],{},[193,253,254],{},"Layout"," → Calculate geometry (size, position)",[190,257,258,261],{},[193,259,260],{},"Paint"," → Fill pixels (colors, images, borders)",[190,263,264,267],{},[193,265,266],{},"Composite"," → Layer compositing for final screen output",[15,269,270,271,275,276,279,280,283],{},"JavaScript can interrupt this path. When the parser hits a ",[272,273,274],"code",{},"\u003Cscript>"," tag, it stops building the DOM until the script executes (unless the script is ",[272,277,278],{},"async"," or ",[272,281,282],{},"defer",").",[179,285,287],{"id":286},"optimizing-the-path","Optimizing the Path",[29,289,290,303],{},[32,291,292],{},[35,293,294,297,300],{},[38,295,296],{},"Technique",[38,298,299],{},"What It Does",[38,301,302],{},"Impact",[54,304,305,316,331,345,359],{},[35,306,307,310,313],{},[59,308,309],{},"Inline critical CSS",[59,311,312],{},"Renders above-the-fold content without waiting for external CSS",[59,314,315],{},"Faster FCP",[35,317,318,325,328],{},[59,319,320,322,323],{},[272,321,282],{}," on ",[272,324,274],{},[59,326,327],{},"Parses HTML first, executes scripts after DOM ready",[59,329,330],{},"Faster FCP\u002FTTI",[35,332,333,339,342],{},[59,334,335,322,337],{},[272,336,278],{},[272,338,274],{},[59,340,341],{},"Downloads in parallel, executes whenever ready",[59,343,344],{},"Good for analytics",[35,346,347,350,356],{},[59,348,349],{},"Preload key resources",[59,351,352,355],{},[272,353,354],{},"\u003Clink rel=\"preload\">"," fetches early",[59,357,358],{},"Faster LCP",[35,360,361,364,367],{},[59,362,363],{},"Avoid render-blocking CSS",[59,365,366],{},"Split CSS into critical and deferred chunks",[59,368,315],{},[370,371,376],"pre",{"className":372,"code":373,"language":374,"meta":375,"style":375},"language-html shiki shiki-themes github-light github-dark","\u003C!-- Critical CSS inlined in \u003Chead> -->\n\u003Cstyle>body{margin:0;font-family:sans-serif}.hero{font-size:2rem}\u003C\u002Fstyle>\n\n\u003C!-- Non-critical CSS loaded asynchronously -->\n\u003Clink rel=\"preload\" href=\"styles.css\" as=\"style\"\n      onload=\"this.rel='stylesheet'\">\n\n\u003C!-- Scripts deferred to avoid blocking parsing -->\n\u003Cscript src=\"app.js\" defer>\u003C\u002Fscript>\n","html","",[272,377,378,387,457,464,470,504,531,536,542],{"__ignoreMap":375},[379,380,383],"span",{"class":381,"line":382},"line",1,[379,384,386],{"class":385},"sJ8bj","\u003C!-- Critical CSS inlined in \u003Chead> -->\n",[379,388,390,394,398,401,404,407,411,414,417,420,423,425,428,431,435,437,440,442,445,449,452,454],{"class":381,"line":389},2,[379,391,393],{"class":392},"sVt8B","\u003C",[379,395,397],{"class":396},"s9eBZ","style",[379,399,400],{"class":392},">",[379,402,403],{"class":396},"body",[379,405,406],{"class":392},"{",[379,408,410],{"class":409},"sj4cs","margin",[379,412,413],{"class":392},":",[379,415,416],{"class":409},"0",[379,418,419],{"class":392},";",[379,421,422],{"class":409},"font-family",[379,424,413],{"class":392},[379,426,427],{"class":409},"sans-serif",[379,429,430],{"class":392},"}",[379,432,434],{"class":433},"sScJk",".hero",[379,436,406],{"class":392},[379,438,439],{"class":409},"font-size",[379,441,413],{"class":392},[379,443,444],{"class":409},"2",[379,446,448],{"class":447},"szBVR","rem",[379,450,451],{"class":392},"}\u003C\u002F",[379,453,397],{"class":396},[379,455,456],{"class":392},">\n",[379,458,460],{"class":381,"line":459},3,[379,461,463],{"emptyLinePlaceholder":462},true,"\n",[379,465,467],{"class":381,"line":466},4,[379,468,469],{"class":385},"\u003C!-- Non-critical CSS loaded asynchronously -->\n",[379,471,473,475,478,481,484,488,491,493,496,499,501],{"class":381,"line":472},5,[379,474,393],{"class":392},[379,476,477],{"class":396},"link",[379,479,480],{"class":433}," rel",[379,482,483],{"class":392},"=",[379,485,487],{"class":486},"sZZnC","\"preload\"",[379,489,490],{"class":433}," href",[379,492,483],{"class":392},[379,494,495],{"class":486},"\"styles.css\"",[379,497,498],{"class":433}," as",[379,500,483],{"class":392},[379,502,503],{"class":486},"\"style\"\n",[379,505,507,510,512,515,518,521,524,526,529],{"class":381,"line":506},6,[379,508,509],{"class":433},"      onload",[379,511,483],{"class":392},[379,513,514],{"class":486},"\"",[379,516,517],{"class":409},"this",[379,519,520],{"class":486},".",[379,522,523],{"class":392},"rel",[379,525,483],{"class":447},[379,527,528],{"class":486},"'stylesheet'\"",[379,530,456],{"class":392},[379,532,534],{"class":381,"line":533},7,[379,535,463],{"emptyLinePlaceholder":462},[379,537,539],{"class":381,"line":538},8,[379,540,541],{"class":385},"\u003C!-- Scripts deferred to avoid blocking parsing -->\n",[379,543,545,547,550,553,555,558,561,564,566],{"class":381,"line":544},9,[379,546,393],{"class":392},[379,548,549],{"class":396},"script",[379,551,552],{"class":433}," src",[379,554,483],{"class":392},[379,556,557],{"class":486},"\"app.js\"",[379,559,560],{"class":433}," defer",[379,562,563],{"class":392},">\u003C\u002F",[379,565,549],{"class":396},[379,567,456],{"class":392},[10,569,571],{"id":570},"resource-prioritization","Resource Prioritization",[15,573,574],{},"Not all resources are equally important. The browser assigns priorities based on type and position, but you can override them.",[179,576,578],{"id":577},"priority-hints","Priority Hints",[15,580,581,582,585],{},"Use ",[272,583,584],{},"fetchpriority"," to tell the browser what matters most:",[370,587,589],{"className":372,"code":588,"language":374,"meta":375,"style":375},"\u003C!-- High priority: hero image above the fold -->\n\u003Cimg src=\"hero.jpg\" fetchpriority=\"high\" alt=\"Hero image\">\n\n\u003C!-- Low priority: below-the-fold content -->\n\u003Cimg src=\"supplementary.jpg\" fetchpriority=\"low\" alt=\"Supplementary image\">\n\n\u003C!-- High priority: critical script -->\n\u003Cscript src=\"core.js\" fetchpriority=\"high\">\u003C\u002Fscript>\n",[272,590,591,596,628,632,637,666,670,675],{"__ignoreMap":375},[379,592,593],{"class":381,"line":382},[379,594,595],{"class":385},"\u003C!-- High priority: hero image above the fold -->\n",[379,597,598,600,603,605,607,610,613,615,618,621,623,626],{"class":381,"line":389},[379,599,393],{"class":392},[379,601,602],{"class":396},"img",[379,604,552],{"class":433},[379,606,483],{"class":392},[379,608,609],{"class":486},"\"hero.jpg\"",[379,611,612],{"class":433}," fetchpriority",[379,614,483],{"class":392},[379,616,617],{"class":486},"\"high\"",[379,619,620],{"class":433}," alt",[379,622,483],{"class":392},[379,624,625],{"class":486},"\"Hero image\"",[379,627,456],{"class":392},[379,629,630],{"class":381,"line":459},[379,631,463],{"emptyLinePlaceholder":462},[379,633,634],{"class":381,"line":466},[379,635,636],{"class":385},"\u003C!-- Low priority: below-the-fold content -->\n",[379,638,639,641,643,645,647,650,652,654,657,659,661,664],{"class":381,"line":472},[379,640,393],{"class":392},[379,642,602],{"class":396},[379,644,552],{"class":433},[379,646,483],{"class":392},[379,648,649],{"class":486},"\"supplementary.jpg\"",[379,651,612],{"class":433},[379,653,483],{"class":392},[379,655,656],{"class":486},"\"low\"",[379,658,620],{"class":433},[379,660,483],{"class":392},[379,662,663],{"class":486},"\"Supplementary image\"",[379,665,456],{"class":392},[379,667,668],{"class":381,"line":506},[379,669,463],{"emptyLinePlaceholder":462},[379,671,672],{"class":381,"line":533},[379,673,674],{"class":385},"\u003C!-- High priority: critical script -->\n",[379,676,677,679,681,683,685,688,690,692,694,696,698],{"class":381,"line":538},[379,678,393],{"class":392},[379,680,549],{"class":396},[379,682,552],{"class":433},[379,684,483],{"class":392},[379,686,687],{"class":486},"\"core.js\"",[379,689,612],{"class":433},[379,691,483],{"class":392},[379,693,617],{"class":486},[379,695,563],{"class":392},[379,697,549],{"class":396},[379,699,456],{"class":392},[179,701,703],{"id":702},"resource-hints","Resource Hints",[29,705,706,719],{},[32,707,708],{},[35,709,710,713,716],{},[38,711,712],{},"Hint",[38,714,715],{},"Purpose",[38,717,718],{},"When to Use",[54,720,721,734,747,760,773],{},[35,722,723,728,731],{},[59,724,725],{},[272,726,727],{},"dns-prefetch",[59,729,730],{},"Resolve DNS early",[59,732,733],{},"Third-party domains",[35,735,736,741,744],{},[59,737,738],{},[272,739,740],{},"preconnect",[59,742,743],{},"Establish connection (DNS + TCP + TLS)",[59,745,746],{},"Critical third-party origins",[35,748,749,754,757],{},[59,750,751],{},[272,752,753],{},"preload",[59,755,756],{},"Fetch resource early with high priority",[59,758,759],{},"Hero images, critical fonts, key CSS",[35,761,762,767,770],{},[59,763,764],{},[272,765,766],{},"prefetch",[59,768,769],{},"Fetch for future navigation",[59,771,772],{},"Next-page resources",[35,774,775,780,783],{},[59,776,777],{},[272,778,779],{},"modulepreload",[59,781,782],{},"Preload ES modules",[59,784,785],{},"Critical JS modules",[370,787,789],{"className":372,"code":788,"language":374,"meta":375,"style":375},"\u003C!-- Preconnect to your API and CDN -->\n\u003Clink rel=\"preconnect\" href=\"https:\u002F\u002Fapi.example.com\">\n\u003Clink rel=\"preconnect\" href=\"https:\u002F\u002Fcdn.example.com\">\n\n\u003C!-- Preload the LCP image -->\n\u003Clink rel=\"preload\" as=\"image\" href=\"hero.webp\">\n",[272,790,791,796,818,839,843,848],{"__ignoreMap":375},[379,792,793],{"class":381,"line":382},[379,794,795],{"class":385},"\u003C!-- Preconnect to your API and CDN -->\n",[379,797,798,800,802,804,806,809,811,813,816],{"class":381,"line":389},[379,799,393],{"class":392},[379,801,477],{"class":396},[379,803,480],{"class":433},[379,805,483],{"class":392},[379,807,808],{"class":486},"\"preconnect\"",[379,810,490],{"class":433},[379,812,483],{"class":392},[379,814,815],{"class":486},"\"https:\u002F\u002Fapi.example.com\"",[379,817,456],{"class":392},[379,819,820,822,824,826,828,830,832,834,837],{"class":381,"line":459},[379,821,393],{"class":392},[379,823,477],{"class":396},[379,825,480],{"class":433},[379,827,483],{"class":392},[379,829,808],{"class":486},[379,831,490],{"class":433},[379,833,483],{"class":392},[379,835,836],{"class":486},"\"https:\u002F\u002Fcdn.example.com\"",[379,838,456],{"class":392},[379,840,841],{"class":381,"line":466},[379,842,463],{"emptyLinePlaceholder":462},[379,844,845],{"class":381,"line":472},[379,846,847],{"class":385},"\u003C!-- Preload the LCP image -->\n",[379,849,850,852,854,856,858,860,862,864,867,869,871,874],{"class":381,"line":506},[379,851,393],{"class":392},[379,853,477],{"class":396},[379,855,480],{"class":433},[379,857,483],{"class":392},[379,859,487],{"class":486},[379,861,498],{"class":433},[379,863,483],{"class":392},[379,865,866],{"class":486},"\"image\"",[379,868,490],{"class":433},[379,870,483],{"class":392},[379,872,873],{"class":486},"\"hero.webp\"",[379,875,456],{"class":392},[10,877,879],{"id":878},"caching-strategies","Caching Strategies",[15,881,882],{},"Caching prevents repeat downloads. Combine multiple layers for maximum effect:",[179,884,886],{"id":885},"browser-cache-http-headers","Browser Cache (HTTP Headers)",[29,888,889,901],{},[32,890,891],{},[35,892,893,896,898],{},[38,894,895],{},"Header",[38,897,715],{},[38,899,900],{},"Typical Value",[54,902,903,918,931],{},[35,904,905,910,913],{},[59,906,907],{},[272,908,909],{},"Cache-Control",[59,911,912],{},"Directives for caching behavior",[59,914,915],{},[272,916,917],{},"max-age=31536000, immutable",[35,919,920,925,928],{},[59,921,922],{},[272,923,924],{},"ETag",[59,926,927],{},"Validation token for revalidation",[59,929,930],{},"Auto-generated by server",[35,932,933,938,941],{},[59,934,935],{},[272,936,937],{},"Last-Modified",[59,939,940],{},"Timestamp for conditional requests",[59,942,943],{},"File modification date",[15,945,946],{},"For static assets with hashed filenames, use aggressive caching:",[370,948,953],{"className":949,"code":951,"language":952},[950],"language-text","Cache-Control: public, max-age=31536000, immutable\n","text",[272,954,951],{"__ignoreMap":375},[15,956,957,958,961],{},"The ",[272,959,960],{},"immutable"," flag tells the browser to skip revalidation entirely — the filename changes when the content changes, so the cached version is always valid.",[179,963,965],{"id":964},"service-worker-cache","Service Worker Cache",[15,967,968],{},"Service workers give you programmatic control over caching:",[370,970,974],{"className":971,"code":972,"language":973,"meta":375,"style":375},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F Cache-first strategy for static assets\nself.addEventListener('fetch', (event) => {\n  if (event.request.url.includes('\u002Fassets\u002F')) {\n    event.respondWith(\n      caches.match(event.request).then((cached) => {\n        return cached || fetch(event.request)\n      })\n    )\n  }\n})\n","javascript",[272,975,976,981,1011,1030,1041,1067,1084,1089,1094,1099],{"__ignoreMap":375},[379,977,978],{"class":381,"line":382},[379,979,980],{"class":385},"\u002F\u002F Cache-first strategy for static assets\n",[379,982,983,986,989,992,995,998,1002,1005,1008],{"class":381,"line":389},[379,984,985],{"class":392},"self.",[379,987,988],{"class":433},"addEventListener",[379,990,991],{"class":392},"(",[379,993,994],{"class":486},"'fetch'",[379,996,997],{"class":392},", (",[379,999,1001],{"class":1000},"s4XuR","event",[379,1003,1004],{"class":392},") ",[379,1006,1007],{"class":447},"=>",[379,1009,1010],{"class":392}," {\n",[379,1012,1013,1016,1019,1022,1024,1027],{"class":381,"line":459},[379,1014,1015],{"class":447},"  if",[379,1017,1018],{"class":392}," (event.request.url.",[379,1020,1021],{"class":433},"includes",[379,1023,991],{"class":392},[379,1025,1026],{"class":486},"'\u002Fassets\u002F'",[379,1028,1029],{"class":392},")) {\n",[379,1031,1032,1035,1038],{"class":381,"line":466},[379,1033,1034],{"class":392},"    event.",[379,1036,1037],{"class":433},"respondWith",[379,1039,1040],{"class":392},"(\n",[379,1042,1043,1046,1049,1052,1055,1058,1061,1063,1065],{"class":381,"line":472},[379,1044,1045],{"class":392},"      caches.",[379,1047,1048],{"class":433},"match",[379,1050,1051],{"class":392},"(event.request).",[379,1053,1054],{"class":433},"then",[379,1056,1057],{"class":392},"((",[379,1059,1060],{"class":1000},"cached",[379,1062,1004],{"class":392},[379,1064,1007],{"class":447},[379,1066,1010],{"class":392},[379,1068,1069,1072,1075,1078,1081],{"class":381,"line":506},[379,1070,1071],{"class":447},"        return",[379,1073,1074],{"class":392}," cached ",[379,1076,1077],{"class":447},"||",[379,1079,1080],{"class":433}," fetch",[379,1082,1083],{"class":392},"(event.request)\n",[379,1085,1086],{"class":381,"line":533},[379,1087,1088],{"class":392},"      })\n",[379,1090,1091],{"class":381,"line":538},[379,1092,1093],{"class":392},"    )\n",[379,1095,1096],{"class":381,"line":544},[379,1097,1098],{"class":392},"  }\n",[379,1100,1102],{"class":381,"line":1101},10,[379,1103,1104],{"class":392},"})\n",[179,1106,1108],{"id":1107},"cdn-cache","CDN Cache",[15,1110,1111],{},"CDNs serve your content from edge servers close to users. Benefits include:",[1113,1114,1115,1118,1121,1124],"ul",{},[190,1116,1117],{},"Reduced TTFB (response comes from nearby edge, not origin)",[190,1119,1120],{},"Automatic compression (gzip\u002FBrotli)",[190,1122,1123],{},"DDoS absorption",[190,1125,1126],{},"SSL termination offloaded from origin",[15,1128,1129],{},"Configure CDN cache based on content type: long TTL for static assets, short TTL or stale-while-revalidate for HTML.",[10,1131,1133],{"id":1132},"performance-budgets","Performance Budgets",[15,1135,1136],{},"A performance budget sets numeric limits on metrics and resource sizes. It prevents gradual bloat from eroding speed over time.",[179,1138,1140],{"id":1139},"setting-a-budget","Setting a Budget",[29,1142,1143,1156],{},[32,1144,1145],{},[35,1146,1147,1150,1153],{},[38,1148,1149],{},"Resource",[38,1151,1152],{},"Suggested Budget",[38,1154,1155],{},"Rationale",[54,1157,1158,1169,1180,1191,1202,1212,1222],{},[35,1159,1160,1163,1166],{},[59,1161,1162],{},"Total page weight",[59,1164,1165],{},"\u003C 1 MB (compressed)",[59,1167,1168],{},"Fits in slow 3G within 5 s",[35,1170,1171,1174,1177],{},[59,1172,1173],{},"JavaScript",[59,1175,1176],{},"\u003C 200 KB (compressed)",[59,1178,1179],{},"Keeps TTI under 5 s on mobile",[35,1181,1182,1185,1188],{},[59,1183,1184],{},"CSS",[59,1186,1187],{},"\u003C 50 KB (compressed)",[59,1189,1190],{},"Fast CSSOM construction",[35,1192,1193,1196,1199],{},[59,1194,1195],{},"Images",[59,1197,1198],{},"\u003C 500 KB total",[59,1200,1201],{},"Largest content type, easiest to optimize",[35,1203,1204,1206,1209],{},[59,1205,94],{},[59,1207,1208],{},"\u003C 2.5 s",[59,1210,1211],{},"Core Web Vitals \"good\" threshold",[35,1213,1214,1216,1219],{},[59,1215,128],{},[59,1217,1218],{},"\u003C 0.1",[59,1220,1221],{},"No jarring layout shifts",[35,1223,1224,1226,1229],{},[59,1225,111],{},[59,1227,1228],{},"\u003C 3.8 s",[59,1230,1231],{},"Users can interact quickly",[179,1233,1235],{"id":1234},"enforcing-budgets","Enforcing Budgets",[15,1237,1238],{},"Integrate budget checks into your CI pipeline:",[370,1240,1242],{"className":971,"code":1241,"language":973,"meta":375,"style":375},"\u002F\u002F performance-budget.js (Lighthouse CI config)\nmodule.exports = {\n  ci: {\n    assert: {\n      assertions: {\n        'categories:performance': ['error', { minScore: 0.9 }],\n        'first-contentful-paint': ['error', { maxNumericValue: 1800 }],\n        'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],\n        'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],\n        'total-byte-weight': ['warn', { maxNumericValue: 1000000 }],\n      },\n    },\n  },\n}\n",[272,1243,1244,1249,1264,1269,1274,1279,1299,1316,1332,1348,1365,1371,1377,1383],{"__ignoreMap":375},[379,1245,1246],{"class":381,"line":382},[379,1247,1248],{"class":385},"\u002F\u002F performance-budget.js (Lighthouse CI config)\n",[379,1250,1251,1254,1256,1259,1262],{"class":381,"line":389},[379,1252,1253],{"class":409},"module",[379,1255,520],{"class":392},[379,1257,1258],{"class":409},"exports",[379,1260,1261],{"class":447}," =",[379,1263,1010],{"class":392},[379,1265,1266],{"class":381,"line":459},[379,1267,1268],{"class":392},"  ci: {\n",[379,1270,1271],{"class":381,"line":466},[379,1272,1273],{"class":392},"    assert: {\n",[379,1275,1276],{"class":381,"line":472},[379,1277,1278],{"class":392},"      assertions: {\n",[379,1280,1281,1284,1287,1290,1293,1296],{"class":381,"line":506},[379,1282,1283],{"class":486},"        'categories:performance'",[379,1285,1286],{"class":392},": [",[379,1288,1289],{"class":486},"'error'",[379,1291,1292],{"class":392},", { minScore: ",[379,1294,1295],{"class":409},"0.9",[379,1297,1298],{"class":392}," }],\n",[379,1300,1301,1304,1306,1308,1311,1314],{"class":381,"line":533},[379,1302,1303],{"class":486},"        'first-contentful-paint'",[379,1305,1286],{"class":392},[379,1307,1289],{"class":486},[379,1309,1310],{"class":392},", { maxNumericValue: ",[379,1312,1313],{"class":409},"1800",[379,1315,1298],{"class":392},[379,1317,1318,1321,1323,1325,1327,1330],{"class":381,"line":538},[379,1319,1320],{"class":486},"        'largest-contentful-paint'",[379,1322,1286],{"class":392},[379,1324,1289],{"class":486},[379,1326,1310],{"class":392},[379,1328,1329],{"class":409},"2500",[379,1331,1298],{"class":392},[379,1333,1334,1337,1339,1341,1343,1346],{"class":381,"line":544},[379,1335,1336],{"class":486},"        'cumulative-layout-shift'",[379,1338,1286],{"class":392},[379,1340,1289],{"class":486},[379,1342,1310],{"class":392},[379,1344,1345],{"class":409},"0.1",[379,1347,1298],{"class":392},[379,1349,1350,1353,1355,1358,1360,1363],{"class":381,"line":1101},[379,1351,1352],{"class":486},"        'total-byte-weight'",[379,1354,1286],{"class":392},[379,1356,1357],{"class":486},"'warn'",[379,1359,1310],{"class":392},[379,1361,1362],{"class":409},"1000000",[379,1364,1298],{"class":392},[379,1366,1368],{"class":381,"line":1367},11,[379,1369,1370],{"class":392},"      },\n",[379,1372,1374],{"class":381,"line":1373},12,[379,1375,1376],{"class":392},"    },\n",[379,1378,1380],{"class":381,"line":1379},13,[379,1381,1382],{"class":392},"  },\n",[379,1384,1386],{"class":381,"line":1385},14,[379,1387,1388],{"class":392},"}\n",[15,1390,1391],{},"Builds fail when budgets are exceeded, forcing the team to address performance regressions immediately.",[10,1393,1395],{"id":1394},"quick-wins-checklist","Quick Wins Checklist",[1113,1397,1400,1409,1418,1424,1430,1440,1446,1460],{"className":1398},[1399],"contains-task-list",[190,1401,1404,1408],{"className":1402},[1403],"task-list-item",[1405,1406],"input",{"disabled":462,"type":1407},"checkbox"," Compress all text resources with Brotli or gzip",[190,1410,1412,1414,1415],{"className":1411},[1403],[1405,1413],{"disabled":462,"type":1407}," Serve images in WebP or AVIF with responsive ",[272,1416,1417],{},"srcset",[190,1419,1421,1423],{"className":1420},[1403],[1405,1422],{"disabled":462,"type":1407}," Defer non-critical JavaScript",[190,1425,1427,1429],{"className":1426},[1403],[1405,1428],{"disabled":462,"type":1407}," Inline critical CSS, lazy-load the rest",[190,1431,1433,1435,1436,1439],{"className":1432},[1403],[1405,1434],{"disabled":462,"type":1407}," Set ",[272,1437,1438],{},"Cache-Control: immutable"," on hashed assets",[190,1441,1443,1445],{"className":1442},[1403],[1405,1444],{"disabled":462,"type":1407}," Preload the LCP image and critical fonts",[190,1447,1449,1451,1452,1455,1456,1459],{"className":1448},[1403],[1405,1450],{"disabled":462,"type":1407}," Add ",[272,1453,1454],{},"width"," and ",[272,1457,1458],{},"height"," to images to prevent CLS",[190,1461,1463,1465],{"className":1462},[1403],[1405,1464],{"disabled":462,"type":1407}," Configure a performance budget in CI",[10,1467,1469],{"id":1468},"key-takeaways","Key Takeaways",[1113,1471,1472,1475,1478,1489,1492,1495],{},[190,1473,1474],{},"Track LCP, CLS, and INP — Google's Core Web Vitals that affect rankings",[190,1476,1477],{},"The critical rendering path determines how fast pixels appear; minimize render-blocking resources",[190,1479,581,1480,1482,1483,1485,1486,1488],{},[272,1481,584],{},", ",[272,1484,753],{},", and ",[272,1487,740],{}," to prioritize what matters",[190,1490,1491],{},"Layer browser cache, service workers, and CDN for resilient caching",[190,1493,1494],{},"Performance budgets prevent gradual bloat — enforce them in CI",[190,1496,1497],{},"Every 100 ms counts: faster pages retain more users and rank higher",[10,1499,1501],{"id":1500},"related-guides","Related Guides",[1113,1503,1504,1511,1517],{},[190,1505,1506],{},[1507,1508,1510],"a",{"href":1509},"\u002Fguides\u002Fhtml-minification-guide","HTML Minification: Reducing Page Size for Faster Loading",[190,1512,1513],{},[1507,1514,1516],{"href":1515},"\u002Fguides\u002Fhtml-whitespace-optimization","HTML Whitespace and Comment Optimization Techniques",[190,1518,1519],{},[1507,1520,1522],{"href":1521},"\u002Fguides\u002Fcss-minification-guide","CSS Minification Guide",[10,1524,1526],{"id":1525},"try-it-yourself","Try It Yourself",[15,1528,1529,1530,1534],{},"Minify your HTML and see the size difference with our free ",[1507,1531,1533],{"href":1532},"\u002Ftools\u002Fhtml-minifier","HTML Minifier"," tool. Paste your markup, configure optimization options, and get leaner output in seconds.",[397,1536,1537],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":375,"searchDepth":389,"depth":389,"links":1539},[1540,1541,1544,1548,1552,1557,1561,1562,1563,1564],{"id":12,"depth":389,"text":13},{"id":23,"depth":389,"text":24,"children":1542},[1543],{"id":181,"depth":459,"text":182},{"id":221,"depth":389,"text":222,"children":1545},[1546,1547],{"id":228,"depth":459,"text":229},{"id":286,"depth":459,"text":287},{"id":570,"depth":389,"text":571,"children":1549},[1550,1551],{"id":577,"depth":459,"text":578},{"id":702,"depth":459,"text":703},{"id":878,"depth":389,"text":879,"children":1553},[1554,1555,1556],{"id":885,"depth":459,"text":886},{"id":964,"depth":459,"text":965},{"id":1107,"depth":459,"text":1108},{"id":1132,"depth":389,"text":1133,"children":1558},[1559,1560],{"id":1139,"depth":459,"text":1140},{"id":1234,"depth":459,"text":1235},{"id":1394,"depth":389,"text":1395},{"id":1468,"depth":389,"text":1469},{"id":1500,"depth":389,"text":1501},{"id":1525,"depth":389,"text":1526},"2026-05-28","Master web performance fundamentals — FP, FCP, LCP, TTI, CLS metrics, critical rendering path, caching, and performance budgets.","md",{"immutable":462},"\u002Fguides\u002Fweb-performance-basics",{"title":5,"description":1566},"guides\u002Fweb-performance-basics","skN-iP73grh2UIhehMO5dLpE7jOOlsZYW0SiQZ5osLc",1780401327290]