[{"data":1,"prerenderedAt":1265},["ShallowReactive",2],{"content:\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Freducing-total-blocking-time-in-lighthouse":3,"surroundings:\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Freducing-total-blocking-time-in-lighthouse":1256},{"id":4,"title":5,"body":6,"description":1235,"extension":1236,"meta":1237,"navigation":1249,"path":1250,"seo":1251,"stem":1254,"__hash__":1255},"content\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Freducing-total-blocking-time-in-lighthouse\u002Findex.md","Reducing Total Blocking Time in Lighthouse",{"type":7,"value":8,"toc":1221},"minimark",[9,14,34,41,212,217,256,260,266,272,278,284,374,378,383,386,563,566,570,573,653,661,665,670,892,895,899,902,910,1015,1019,1022,1126,1138,1142,1145,1149,1161,1170,1179,1183,1206,1211,1214,1217],[10,11,13],"h1",{"id":12},"how-to-reduce-total-blocking-time-in-lighthouse","How to Reduce Total Blocking Time in Lighthouse",[15,16,17,18,23,24,28,29,33],"p",{},"This guide belongs to ",[19,20,22],"a",{"href":21},"\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002F","Optimizing First Input Delay (FID) and INP"," within ",[19,25,27],{"href":26},"\u002Fcore-web-vitals-measurement\u002F","Core Web Vitals & Measurement",". Total Blocking Time (TBT) is Lighthouse's lab proxy for interactivity: the sum, across every long task between First Contentful Paint and Time to Interactive, of the portion of each task beyond ",[30,31,32],"code",{},"50ms",". A 120ms task contributes 70ms; a 40ms task contributes nothing.",[15,35,36,37,40],{},"TBT is not a Core Web Vital, but it carries 30% of the Lighthouse performance score and correlates strongly with INP during page load — an interaction that arrives while a long task is running waits for it to finish. Lighthouse considers TBT good under ",[30,38,39],{},"200ms"," on its mobile profile. Pages built on modern frameworks routinely ship 600–1500ms of TBT on that profile because hydration, third-party tags and analytics all compete for the main thread in the same few seconds.",[15,42,43],{},[44,45,51,52,51,59,51,63,51,66,51,75,51,81,51,86,51,95,51,102,51,107,51,111,51,118,51,122,51,126,51,130,51,134,51,138,51,142,51,147,51,152,51,156,51,160,51,163,51,167,51,171,51,178,51,184,51,187,51,191,51,195,51,199,51,203,51,207,51],"svg",{"viewBox":46,"width":47,"role":48,"ariaLabel":49,"style":50},"0 0 760 204","100%","img","Timeline of five main-thread tasks between FCP and TTI, with only the portion of each task beyond 50 milliseconds counted toward Total Blocking Time.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[53,54],"rect",{"className":55,"x":57,"y":57,"width":47,"height":47,"fill":58},[56],"svg-canvas","0","#ffffff",[60,61,62],"title",{},"How TBT is summed from long tasks",[64,65,49],"desc",{},[53,67],{"x":68,"y":68,"width":69,"height":70,"rx":71,"fill":72,"stroke":73,"style":74},"1","758","202","10","none","currentColor","stroke-opacity:0.18",[76,77,62],"text",{"x":78,"y":79,"fill":73,"style":80},"28.0","34.0","font-size:16px;font-weight:700",[76,82,85],{"x":78,"y":83,"fill":73,"style":84},"74.0","font-size:12.5px;font-weight:700","Tasks",[53,87],{"x":88,"y":89,"width":90,"height":91,"rx":92,"fill":93,"stroke":93,"style":94},"91.9","56.0","93.7","26.0","3","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[76,96,101],{"x":97,"y":98,"fill":73,"style":99,"textAnchor":100},"138.7","73.5","font-size:11.5px","middle","180ms",[53,103],{"x":104,"y":89,"width":105,"height":91,"rx":92,"fill":73,"stroke":73,"style":106},"197.7","19.7","fill-opacity:0.06;stroke-opacity:0.4",[76,108,110],{"x":109,"y":98,"fill":73,"style":99,"textAnchor":100},"207.5","40",[53,112],{"x":113,"y":89,"width":114,"height":91,"rx":92,"fill":115,"stroke":116,"style":117},"229.4","220.7","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[76,119,121],{"x":120,"y":98,"fill":73,"style":99,"textAnchor":100},"339.8","hydration 420ms",[53,123],{"x":124,"y":89,"width":125,"height":91,"rx":92,"fill":93,"stroke":93,"style":94},"472.8","46.1",[76,127,129],{"x":128,"y":98,"fill":73,"style":99,"textAnchor":100},"495.9","90ms",[53,131],{"x":132,"y":89,"width":133,"height":91,"rx":92,"fill":115,"stroke":116,"style":117},"546.9","125.5",[76,135,137],{"x":136,"y":98,"fill":73,"style":99,"textAnchor":100},"609.6","GTM 240ms",[76,139,141],{"x":78,"y":140,"fill":73,"style":84},"112.0","Counted",[53,143],{"x":144,"y":145,"width":146,"height":91,"rx":92,"fill":73,"stroke":73,"style":106},"118.3","94.0","67.3",[76,148,151],{"x":149,"y":150,"fill":73,"style":99,"textAnchor":100},"152.0","111.5","130",[53,153],{"x":154,"y":145,"width":155,"height":91,"rx":92,"fill":115,"stroke":116,"style":117},"255.9","194.3",[76,157,159],{"x":158,"y":150,"fill":73,"style":99,"textAnchor":100},"353.0","370",[53,161],{"x":162,"y":145,"width":105,"height":91,"rx":92,"fill":73,"stroke":73,"style":106},"499.3",[53,164],{"x":165,"y":145,"width":166,"height":91,"rx":92,"fill":115,"stroke":116,"style":117},"573.3","99.0",[76,168,170],{"x":169,"y":150,"fill":73,"style":99,"textAnchor":100},"622.8","190",[172,173],"line",{"x1":174,"y1":175,"x2":176,"y2":175,"stroke":73,"style":177},"91.1","134.0","726.0","stroke-opacity:0.4",[76,179,183],{"x":180,"y":181,"fill":182,"style":99,"textAnchor":100},"101.8","151.0","#51617a","0ms",[76,185,39],{"x":186,"y":181,"fill":182,"style":99,"textAnchor":100},"196.9",[76,188,190],{"x":189,"y":181,"fill":182,"style":99,"textAnchor":100},"302.7","400ms",[76,192,194],{"x":193,"y":181,"fill":182,"style":99,"textAnchor":100},"408.6","600ms",[76,196,198],{"x":197,"y":181,"fill":182,"style":99,"textAnchor":100},"514.4","800ms",[76,200,202],{"x":201,"y":181,"fill":182,"style":99,"textAnchor":100},"620.2","1000ms",[76,204,206],{"x":205,"y":181,"fill":182,"style":99,"textAnchor":100},"712.3","1200ms",[76,208,211],{"x":78,"y":209,"fill":182,"style":210},"182.0","font-size:12.5px","TBT here is 130 + 0 + 370 + 40 + 190 = 730ms. Splitting the two gold tasks into 50ms chunks would remove most of it.",[213,214,216],"h2",{"id":215},"rapid-diagnosis","Rapid Diagnosis",[218,219,220,228,234,240,250],"ul",{},[221,222,223,227],"li",{},[224,225,226],"strong",{},"Read the \"Diagnostics\" in the Lighthouse report."," \"Minimize main-thread work\" and \"Reduce JavaScript execution time\" list the scripts with the most CPU time; \"Avoid long main-thread tasks\" lists the longest tasks with their URLs.",[221,229,230,233],{},[224,231,232],{},"Open the trace."," In DevTools' Lighthouse panel, \"View Trace\" (or run the Performance panel with 4x CPU throttling) shows long tasks marked with red corners. Sort the Bottom-Up tab by self time, grouped by URL or by activity.",[221,235,236,239],{},[224,237,238],{},"Separate first-party from third-party."," Use the \"Group by product\" or third-party badges in the Performance panel to see how much TBT belongs to vendors.",[221,241,242,245,246,249],{},[224,243,244],{},"Check task start points."," A task that begins at a ",[30,247,248],{},"\u003Cscript>"," evaluation is load-time code; one that begins at a timer or a message event is often a framework scheduler or a tag manager.",[221,251,252,255],{},[224,253,254],{},"Repeat three to five times."," TBT varies between runs; use the median before deciding what changed.",[213,257,259],{"id":258},"root-cause-analysis","Root Cause Analysis",[15,261,262,265],{},[224,263,264],{},"1. Hydration as one giant task."," Server-rendered frameworks hydrate the whole tree synchronously by default, producing a single task proportional to component count — often 300–800ms on the Lighthouse mobile profile.",[15,267,268,271],{},[224,269,270],{},"2. Large script evaluation."," Every script's top-level code runs in one task when it is evaluated. A 400KB bundle with heavy module initialisation produces a long evaluation task even before any component renders.",[15,273,274,277],{},[224,275,276],{},"3. Third-party tags firing at load."," Tag managers fire many tags on the page-view trigger, each evaluating its own script; the container can occupy the thread for hundreds of milliseconds right after load.",[15,279,280,283],{},[224,281,282],{},"4. Synchronous work in startup code."," Building large in-memory indexes, parsing big JSON blobs, setting up analytics with synchronous storage access, or feature-flag evaluation over large rule sets — all done eagerly at startup.",[15,285,286],{},[44,287,51,290,51,293,51,296,51,298,51,301,51,303,51,312,51,319,51,326,51,331,51,335,51,340,51,344,51,348,51,352,51,356,51,360,51,364,51,368,51],{"viewBox":288,"width":47,"role":48,"ariaLabel":289,"style":50},"0 0 760 216","Bar chart of Total Blocking Time attributed to hydration, the app bundle, a tag manager and other third parties, with the 200 millisecond good threshold.",[53,291],{"className":292,"x":57,"y":57,"width":47,"height":47,"fill":58},[56],[60,294,295],{},"TBT by source on a typical storefront (Lighthouse mobile)",[64,297,289],{},[53,299],{"x":68,"y":68,"width":69,"height":300,"rx":71,"fill":72,"stroke":73,"style":74},"214",[76,302,295],{"x":78,"y":79,"fill":73,"style":80},[172,304],{"x1":305,"y1":306,"x2":305,"y2":307,"stroke":116,"strokeWidth":308,"strokeDashArray":309,"style":311},"411.7","72.0","194.0","1.5",[310,310],"4","stroke-opacity:0.9",[76,313,318],{"x":314,"y":315,"fill":73,"style":316,"textAnchor":317},"155.6","92.0","font-size:13px","end","Hydration",[53,320],{"x":321,"y":322,"width":323,"height":324,"rx":92,"fill":115,"stroke":116,"style":325},"167.6","78.0","500.4","19","fill-opacity:0.7;stroke-opacity:0.9",[76,327,330],{"x":328,"y":315,"fill":73,"style":329},"674.0","font-size:12px;font-weight:600","410ms",[76,332,334],{"x":314,"y":333,"fill":73,"style":316,"textAnchor":317},"123.0","App bundle evaluation",[53,336],{"x":321,"y":337,"width":338,"height":324,"rx":92,"fill":93,"stroke":93,"style":339},"109.0","195.3","fill-opacity:0.55;stroke-opacity:0.9",[76,341,343],{"x":342,"y":333,"fill":73,"style":329},"368.9","160ms",[76,345,347],{"x":314,"y":346,"fill":73,"style":316,"textAnchor":317},"154.0","Tag manager + tags",[53,349],{"x":321,"y":350,"width":351,"height":324,"rx":92,"fill":115,"stroke":116,"style":325},"140.0","353.9",[76,353,355],{"x":354,"y":346,"fill":73,"style":329},"527.6","290ms",[76,357,359],{"x":314,"y":358,"fill":73,"style":316,"textAnchor":317},"185.0","Other third parties",[53,361],{"x":321,"y":362,"width":363,"height":324,"rx":92,"fill":93,"stroke":93,"style":339},"171.0","146.4",[76,365,367],{"x":366,"y":358,"fill":73,"style":329},"320.1","120ms",[76,369,373],{"x":305,"y":370,"fill":371,"style":372,"textAnchor":100},"68.0","#8a6608","font-size:12px;font-weight:700","TBT good: 200ms",[213,375,377],{"id":376},"step-by-step-resolution","Step-by-Step Resolution",[379,380,382],"h3",{"id":381},"_1-defer-and-split-third-party-tags","1. Defer and split third-party tags",[15,384,385],{},"Move non-essential tags off the load path. For tag managers, change page-view triggers for analytics-adjacent tags to fire on \"Window Loaded\" plus an idle delay, and load chat, survey and heatmap tools on interaction.",[387,388,393],"pre",{"className":389,"code":390,"language":391,"meta":392,"style":392},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F Load the tag manager after the page is interactive and the browser is idle.\nfunction loadGTM(id) {\n  const s = document.createElement('script');\n  s.src = `https:\u002F\u002Fwww.googletagmanager.com\u002Fgtm.js?id=${id}`;\n  s.async = true;\n  document.head.appendChild(s);\n}\naddEventListener('load', () => requestIdleCallback(() => loadGTM('GTM-XXXX'), { timeout: 3000 }));\n\u002F\u002F trade-off: delaying the container delays every tag, including conversion\n\u002F\u002F pixels. Keep conversion-critical tags in a separate, early container or send\n\u002F\u002F them server-side; defer only the rest.\n","javascript","",[30,394,395,403,425,453,473,486,498,504,545,551,557],{"__ignoreMap":392},[396,397,399],"span",{"class":172,"line":398},1,[396,400,402],{"class":401},"sjfSM","\u002F\u002F Load the tag manager after the page is interactive and the browser is idle.\n",[396,404,406,410,414,418,422],{"class":172,"line":405},2,[396,407,409],{"class":408},"sPARh","function",[396,411,413],{"class":412},"smZ65"," loadGTM",[396,415,417],{"class":416},"saISM","(",[396,419,421],{"class":420},"sQw3B","id",[396,423,424],{"class":416},") {\n",[396,426,428,431,435,438,441,444,446,450],{"class":172,"line":427},3,[396,429,430],{"class":408},"  const",[396,432,434],{"class":433},"sPXB4"," s",[396,436,437],{"class":408}," =",[396,439,440],{"class":416}," document.",[396,442,443],{"class":412},"createElement",[396,445,417],{"class":416},[396,447,449],{"class":448},"sZ8jY","'script'",[396,451,452],{"class":416},");\n",[396,454,456,459,462,465,467,470],{"class":172,"line":455},4,[396,457,458],{"class":416},"  s.src ",[396,460,461],{"class":408},"=",[396,463,464],{"class":448}," `https:\u002F\u002Fwww.googletagmanager.com\u002Fgtm.js?id=${",[396,466,421],{"class":416},[396,468,469],{"class":448},"}`",[396,471,472],{"class":416},";\n",[396,474,476,479,481,484],{"class":172,"line":475},5,[396,477,478],{"class":416},"  s.async ",[396,480,461],{"class":408},[396,482,483],{"class":433}," true",[396,485,472],{"class":416},[396,487,489,492,495],{"class":172,"line":488},6,[396,490,491],{"class":416},"  document.head.",[396,493,494],{"class":412},"appendChild",[396,496,497],{"class":416},"(s);\n",[396,499,501],{"class":172,"line":500},7,[396,502,503],{"class":416},"}\n",[396,505,507,510,512,515,518,521,524,527,529,531,533,536,539,542],{"class":172,"line":506},8,[396,508,509],{"class":412},"addEventListener",[396,511,417],{"class":416},[396,513,514],{"class":448},"'load'",[396,516,517],{"class":416},", () ",[396,519,520],{"class":408},"=>",[396,522,523],{"class":412}," requestIdleCallback",[396,525,526],{"class":416},"(() ",[396,528,520],{"class":408},[396,530,413],{"class":412},[396,532,417],{"class":416},[396,534,535],{"class":448},"'GTM-XXXX'",[396,537,538],{"class":416},"), { timeout: ",[396,540,541],{"class":433},"3000",[396,543,544],{"class":416}," }));\n",[396,546,548],{"class":172,"line":547},9,[396,549,550],{"class":401},"\u002F\u002F trade-off: delaying the container delays every tag, including conversion\n",[396,552,554],{"class":172,"line":553},10,[396,555,556],{"class":401},"\u002F\u002F pixels. Keep conversion-critical tags in a separate, early container or send\n",[396,558,560],{"class":172,"line":559},11,[396,561,562],{"class":401},"\u002F\u002F them server-side; defer only the rest.\n",[15,564,565],{},"Expected outcome: TBT falls by most of the third-party share; on tag-heavy sites this alone is often 200–400ms.",[379,567,569],{"id":568},"_2-make-hydration-incremental","2. Make hydration incremental",[15,571,572],{},"Hydrate above-the-fold interactive components first and defer the rest until visible or idle. React 18's streaming and Suspense boundaries let React yield between boundaries during hydration; islands frameworks avoid hydrating static content entirely.",[387,574,578],{"className":575,"code":576,"language":577,"meta":392,"style":392},"language-jsx shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F Wrap below-the-fold, independently hydratable sections in Suspense boundaries.\n\u003CSuspense fallback={\u003CReviewsPlaceholder \u002F>}>\n  \u003CReviews productId={id} \u002F>\n\u003C\u002FSuspense>\n\u002F\u002F trade-off: each boundary adds a fallback state and potential layout shift if\n\u002F\u002F the fallback is not sized like the content. Size fallbacks precisely.\n","jsx",[30,579,580,585,614,634,643,648],{"__ignoreMap":392},[396,581,582],{"class":172,"line":398},[396,583,584],{"class":401},"\u002F\u002F Wrap below-the-fold, independently hydratable sections in Suspense boundaries.\n",[396,586,587,590,594,597,600,602,605,608,611],{"class":172,"line":405},[396,588,589],{"class":416},"\u003C",[396,591,593],{"class":592},"sZBmE","Suspense",[396,595,596],{"class":433}," fallback",[396,598,599],{"class":408},"={",[396,601,589],{"class":416},[396,603,604],{"class":592},"ReviewsPlaceholder",[396,606,607],{"class":416}," \u002F>",[396,609,610],{"class":408},"}",[396,612,613],{"class":416},">\n",[396,615,616,619,622,625,627,629,631],{"class":172,"line":427},[396,617,618],{"class":416},"  \u003C",[396,620,621],{"class":592},"Reviews",[396,623,624],{"class":433}," productId",[396,626,599],{"class":408},[396,628,421],{"class":416},[396,630,610],{"class":408},[396,632,633],{"class":416}," \u002F>\n",[396,635,636,639,641],{"class":172,"line":455},[396,637,638],{"class":416},"\u003C\u002F",[396,640,593],{"class":592},[396,642,613],{"class":416},[396,644,645],{"class":172,"line":475},[396,646,647],{"class":401},"\u002F\u002F trade-off: each boundary adds a fallback state and potential layout shift if\n",[396,649,650],{"class":172,"line":488},[396,651,652],{"class":401},"\u002F\u002F the fallback is not sized like the content. Size fallbacks precisely.\n",[15,654,655,656,660],{},"Expected outcome: the single hydration task becomes several shorter tasks; TBT from hydration typically halves. See ",[19,657,659],{"href":658},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fhydration-and-partial-rehydration-strategies\u002Fselective-hydration-with-react-suspense\u002F","selective hydration with React Suspense",".",[379,662,664],{"id":663},"_3-split-long-startup-work-with-yields","3. Split long startup work with yields",[15,666,667,668,660],{},"For your own startup code, process work in chunks and yield between them so no task exceeds ",[30,669,32],{},[387,671,673],{"className":389,"code":672,"language":391,"meta":392,"style":392},"async function buildIndex(items) {\n  const index = new Map();\n  let deadline = performance.now() + 40;\n  for (const item of items) {\n    index.set(item.id, normalize(item));\n    if (performance.now() > deadline) {\n      await (globalThis.scheduler?.yield?.() ?? new Promise((r) => setTimeout(r)));\n      deadline = performance.now() + 40;\n    }\n  }\n  return index;\n}\n\u002F\u002F trade-off: chunking spreads the same CPU cost over more wall-clock time. If\n\u002F\u002F the result is needed before the first interaction, it may now arrive later;\n\u002F\u002F consider computing it on the server or in a worker instead.\n",[30,674,675,693,711,738,758,775,793,832,851,856,861,869,874,880,886],{"__ignoreMap":392},[396,676,677,680,683,686,688,691],{"class":172,"line":398},[396,678,679],{"class":408},"async",[396,681,682],{"class":408}," function",[396,684,685],{"class":412}," buildIndex",[396,687,417],{"class":416},[396,689,690],{"class":420},"items",[396,692,424],{"class":416},[396,694,695,697,700,702,705,708],{"class":172,"line":405},[396,696,430],{"class":408},[396,698,699],{"class":433}," index",[396,701,437],{"class":408},[396,703,704],{"class":408}," new",[396,706,707],{"class":412}," Map",[396,709,710],{"class":416},"();\n",[396,712,713,716,719,721,724,727,730,733,736],{"class":172,"line":427},[396,714,715],{"class":408},"  let",[396,717,718],{"class":416}," deadline ",[396,720,461],{"class":408},[396,722,723],{"class":416}," performance.",[396,725,726],{"class":412},"now",[396,728,729],{"class":416},"() ",[396,731,732],{"class":408},"+",[396,734,735],{"class":433}," 40",[396,737,472],{"class":416},[396,739,740,743,746,749,752,755],{"class":172,"line":455},[396,741,742],{"class":408},"  for",[396,744,745],{"class":416}," (",[396,747,748],{"class":408},"const",[396,750,751],{"class":433}," item",[396,753,754],{"class":408}," of",[396,756,757],{"class":416}," items) {\n",[396,759,760,763,766,769,772],{"class":172,"line":475},[396,761,762],{"class":416},"    index.",[396,764,765],{"class":412},"set",[396,767,768],{"class":416},"(item.id, ",[396,770,771],{"class":412},"normalize",[396,773,774],{"class":416},"(item));\n",[396,776,777,780,783,785,787,790],{"class":172,"line":488},[396,778,779],{"class":408},"    if",[396,781,782],{"class":416}," (performance.",[396,784,726],{"class":412},[396,786,729],{"class":416},[396,788,789],{"class":408},">",[396,791,792],{"class":416}," deadline) {\n",[396,794,795,798,801,804,807,810,812,815,818,821,824,826,829],{"class":172,"line":500},[396,796,797],{"class":408},"      await",[396,799,800],{"class":416}," (globalThis.scheduler?.",[396,802,803],{"class":412},"yield",[396,805,806],{"class":416},"?.() ",[396,808,809],{"class":408},"??",[396,811,704],{"class":408},[396,813,814],{"class":433}," Promise",[396,816,817],{"class":416},"((",[396,819,820],{"class":420},"r",[396,822,823],{"class":416},") ",[396,825,520],{"class":408},[396,827,828],{"class":412}," setTimeout",[396,830,831],{"class":416},"(r)));\n",[396,833,834,837,839,841,843,845,847,849],{"class":172,"line":506},[396,835,836],{"class":416},"      deadline ",[396,838,461],{"class":408},[396,840,723],{"class":416},[396,842,726],{"class":412},[396,844,729],{"class":416},[396,846,732],{"class":408},[396,848,735],{"class":433},[396,850,472],{"class":416},[396,852,853],{"class":172,"line":547},[396,854,855],{"class":416},"    }\n",[396,857,858],{"class":172,"line":553},[396,859,860],{"class":416},"  }\n",[396,862,863,866],{"class":172,"line":559},[396,864,865],{"class":408},"  return",[396,867,868],{"class":416}," index;\n",[396,870,872],{"class":172,"line":871},12,[396,873,503],{"class":416},[396,875,877],{"class":172,"line":876},13,[396,878,879],{"class":401},"\u002F\u002F trade-off: chunking spreads the same CPU cost over more wall-clock time. If\n",[396,881,883],{"class":172,"line":882},14,[396,884,885],{"class":401},"\u002F\u002F the result is needed before the first interaction, it may now arrive later;\n",[396,887,889],{"class":172,"line":888},15,[396,890,891],{"class":401},"\u002F\u002F consider computing it on the server or in a worker instead.\n",[15,893,894],{},"Expected outcome: long tasks from startup code disappear from the \"Avoid long main-thread tasks\" list.",[379,896,898],{"id":897},"_4-ship-less-javascript-on-the-critical-path","4. Ship less JavaScript on the critical path",[15,900,901],{},"Code-split by route and by interaction, remove unused polyfills, and replace heavy dependencies. Every kilobyte not evaluated is TBT not incurred.",[15,903,904,905,909],{},"Expected outcome: script evaluation tasks shrink in proportion to the code removed; ",[19,906,908],{"href":907},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fdynamic-imports-and-route-based-splitting\u002F","dynamic imports and route-based splitting"," is the starting point.",[15,911,912],{},[44,913,51,916,51,919,51,922,51,924,51,927,51,929,51,934,51,941,51,945,51,948,51,951,51,955,51,957,51,961,51,965,51,968,51,972,51,976,51,982,51,986,51,990,51,995,51,997,51,1000,51,1004,51,1006,51,1009,51,1012,51],{"viewBox":914,"width":47,"role":48,"ariaLabel":915,"style":50},"0 0 760 318","Four steps for reducing Total Blocking Time ordered by typical impact, starting with third-party deferral.",[53,917],{"className":918,"x":57,"y":57,"width":47,"height":47,"fill":58},[56],[60,920,921],{},"Order of attack for a high TBT score",[64,923,915],{},[53,925],{"x":68,"y":68,"width":69,"height":926,"rx":71,"fill":72,"stroke":73,"style":74},"316",[76,928,921],{"x":78,"y":79,"fill":73,"style":80},[53,930],{"x":306,"y":89,"width":931,"height":932,"rx":933,"fill":93,"stroke":93,"style":94},"660.0","51.0","6",[76,935,940],{"x":936,"y":937,"fill":73,"style":938,"textAnchor":939},"86.0","77.0","font-size:13px;font-weight:700","start","Defer third-party tags",[76,942,944],{"x":936,"y":145,"fill":73,"style":943,"textAnchor":939},"font-size:12px","Tag manager after load + idle; chat and surveys on interaction",[53,946],{"x":306,"y":947,"width":931,"height":932,"rx":933,"fill":93,"stroke":93,"style":94},"119.0",[76,949,950],{"x":936,"y":350,"fill":73,"style":938,"textAnchor":939},"Split hydration",[76,952,954],{"x":936,"y":953,"fill":73,"style":943,"textAnchor":939},"157.0","Suspense boundaries or islands so no single hydration task dominates",[53,956],{"x":306,"y":209,"width":931,"height":932,"rx":933,"fill":93,"stroke":93,"style":94},[76,958,960],{"x":936,"y":959,"fill":73,"style":938,"textAnchor":939},"203.0","Chunk startup code",[76,962,964],{"x":936,"y":963,"fill":73,"style":943,"textAnchor":939},"220.0","Yield every ~40ms in index building and data processing",[53,966],{"x":306,"y":967,"width":931,"height":932,"rx":933,"fill":93,"stroke":93,"style":94},"245.0",[76,969,971],{"x":936,"y":970,"fill":73,"style":938,"textAnchor":939},"266.0","Ship less JavaScript",[76,973,975],{"x":936,"y":974,"fill":73,"style":943,"textAnchor":939},"283.0","Route and interaction splitting; drop unused polyfills",[172,977],{"x1":978,"y1":979,"x2":978,"y2":980,"stroke":73,"strokeWidth":308,"style":981},"43.0","95.5","130.5","stroke-opacity:0.3",[172,983],{"x1":978,"y1":984,"x2":978,"y2":985,"stroke":73,"strokeWidth":308,"style":981},"158.5","193.5",[172,987],{"x1":978,"y1":988,"x2":978,"y2":989,"stroke":73,"strokeWidth":308,"style":981},"221.5","256.5",[991,992],"circle",{"cx":978,"cy":993,"r":994,"fill":93},"81.5","13",[76,996,68],{"x":978,"y":936,"fill":58,"style":938,"textAnchor":100},[991,998],{"cx":978,"cy":999,"r":994,"fill":93},"144.5",[76,1001,1003],{"x":978,"y":1002,"fill":58,"style":938,"textAnchor":100},"149.0","2",[991,1005],{"cx":978,"cy":109,"r":994,"fill":93},[76,1007,92],{"x":978,"y":1008,"fill":58,"style":938,"textAnchor":100},"212.0",[991,1010],{"cx":978,"cy":1011,"r":994,"fill":93},"270.5",[76,1013,310],{"x":978,"y":1014,"fill":58,"style":938,"textAnchor":100},"275.0",[213,1016,1018],{"id":1017},"verification","Verification",[15,1020,1021],{},"Run Lighthouse five times before and after, and compare median TBT. Then assert a budget in Lighthouse CI so the gain survives:",[387,1023,1025],{"className":389,"code":1024,"language":391,"meta":392,"style":392},"\u002F\u002F lighthouserc.js\nmodule.exports = { ci: {\n  collect: { numberOfRuns: 5 },\n  assert: { assertions: {\n    'total-blocking-time': ['error', { maxNumericValue: 300, aggregationMethod: 'median' }],\n    'mainthread-work-breakdown': ['warn', { maxNumericValue: 2500 }],\n  } },\n} };\n\u002F\u002F trade-off: CI machines vary; a budget of exactly 200ms will flake. Set the\n\u002F\u002F CI gate somewhat above the target and track the trend, tightening over time.\n",[30,1026,1027,1032,1047,1058,1063,1089,1106,1111,1116,1121],{"__ignoreMap":392},[396,1028,1029],{"class":172,"line":398},[396,1030,1031],{"class":401},"\u002F\u002F lighthouserc.js\n",[396,1033,1034,1037,1039,1042,1044],{"class":172,"line":405},[396,1035,1036],{"class":433},"module",[396,1038,660],{"class":416},[396,1040,1041],{"class":433},"exports",[396,1043,437],{"class":408},[396,1045,1046],{"class":416}," { ci: {\n",[396,1048,1049,1052,1055],{"class":172,"line":427},[396,1050,1051],{"class":416},"  collect: { numberOfRuns: ",[396,1053,1054],{"class":433},"5",[396,1056,1057],{"class":416}," },\n",[396,1059,1060],{"class":172,"line":455},[396,1061,1062],{"class":416},"  assert: { assertions: {\n",[396,1064,1065,1068,1071,1074,1077,1080,1083,1086],{"class":172,"line":475},[396,1066,1067],{"class":448},"    'total-blocking-time'",[396,1069,1070],{"class":416},": [",[396,1072,1073],{"class":448},"'error'",[396,1075,1076],{"class":416},", { maxNumericValue: ",[396,1078,1079],{"class":433},"300",[396,1081,1082],{"class":416},", aggregationMethod: ",[396,1084,1085],{"class":448},"'median'",[396,1087,1088],{"class":416}," }],\n",[396,1090,1091,1094,1096,1099,1101,1104],{"class":172,"line":488},[396,1092,1093],{"class":448},"    'mainthread-work-breakdown'",[396,1095,1070],{"class":416},[396,1097,1098],{"class":448},"'warn'",[396,1100,1076],{"class":416},[396,1102,1103],{"class":433},"2500",[396,1105,1088],{"class":416},[396,1107,1108],{"class":172,"line":500},[396,1109,1110],{"class":416},"  } },\n",[396,1112,1113],{"class":172,"line":506},[396,1114,1115],{"class":416},"} };\n",[396,1117,1118],{"class":172,"line":547},[396,1119,1120],{"class":401},"\u002F\u002F trade-off: CI machines vary; a budget of exactly 200ms will flake. Set the\n",[396,1122,1123],{"class":172,"line":553},[396,1124,1125],{"class":401},"\u002F\u002F CI gate somewhat above the target and track the trend, tightening over time.\n",[15,1127,1128,1129,1132,1133,1137],{},"In the field, TBT has no direct equivalent, but INP for interactions in the first few seconds after load, and the ",[30,1130,1131],{},"blockingDuration"," sum from ",[19,1134,1136],{"href":1135},"\u002Fcore-web-vitals-measurement\u002Flong-animation-frames-api\u002F","Long Animation Frames",", should both improve.",[213,1139,1141],{"id":1140},"tbt-inp-and-the-lighthouse-score-keeping-them-in-perspective","TBT, INP and the Lighthouse Score: Keeping Them in Perspective",[15,1143,1144],{},"TBT is a load-time lab metric; INP is a whole-visit field metric. They overlap only for interactions during load. A page can have excellent TBT and poor INP if its slow interactions happen later — a filter applied after a minute of browsing — and a page with mediocre TBT can have fine INP if users rarely interact during load. Use TBT to keep startup lean and to catch regressions in CI, where it is far more stable than any interaction-based lab measurement. Use field INP, broken down by interaction and phase, to decide what to fix for users. Avoid optimising TBT for its own sake: deferring work past Lighthouse's observation window lowers TBT without helping anyone if that work then blocks the user's first click.",[213,1146,1148],{"id":1147},"faq","FAQ",[1150,1151,1154,1158],"details",{"className":1152},[1153],"faq-item",[1155,1156,1157],"summary",{},"Why does my TBT differ so much between runs?",[15,1159,1160],{},"Long tasks are sensitive to timing: whether a third-party script arrives before or after hydration changes how tasks line up, and CPU throttling on shared machines adds noise. Use the median of at least three runs, keep the test machine quiet, and prefer devtools throttling settings that match your target device when comparing changes.",[1150,1162,1164,1167],{"className":1163},[1153],[1155,1165,1166],{},"Is TBT the same as First Input Delay?",[15,1168,1169],{},"No. FID measured the delay of the first real interaction in the field and was retired in favour of INP in 2024. TBT is a lab metric that sums blocking time over the load period, regardless of whether anyone interacts. It predicts input delay risk during load rather than measuring it.",[1150,1171,1173,1176],{"className":1172},[1153],[1155,1174,1175],{},"Does yielding inside tasks always reduce TBT?",[15,1177,1178],{},"Yes, if each resulting chunk is under 50ms: TBT only counts time beyond 50ms per task, so splitting a 300ms task into six 50ms tasks reduces its contribution from 250ms to zero. The total CPU time is unchanged, which is why yielding improves responsiveness without making the work itself finish sooner.",[213,1180,1182],{"id":1181},"related","Related",[218,1184,1185,1192,1199],{},[221,1186,1187,1191],{},[19,1188,1190],{"href":1189},"\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Ffixing-slow-first-interactions-during-hydration\u002F","Fixing slow first interactions during hydration"," — the INP side of the same startup work.",[221,1193,1194,1198],{},[19,1195,1197],{"href":1196},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fthird-party-script-performance\u002Fmeasuring-third-party-cost-with-the-coverage-panel\u002F","Measuring third-party cost with the Coverage panel"," — sizing what each vendor costs.",[221,1200,1201,1205],{},[19,1202,1204],{"href":1203},"\u002Fcore-web-vitals-measurement\u002Flong-animation-frames-api\u002Floaf-vs-long-tasks-api\u002F","LoAF vs the Long Tasks API"," — the field-side view of blocking time.",[1207,1208,1210],"script",{"type":1209},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Reduce Total Blocking Time in Lighthouse\",\n  \"description\": \"How Lighthouse computes TBT, which tasks dominate it on real pages, and the split, defer and remove fixes that bring it under 200ms.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Defer and split third-party tags\",\n      \"text\": \"Move non-essential tags off the load path.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Make hydration incremental\",\n      \"text\": \"Hydrate above-the-fold interactive components first and defer the rest until visible or idle.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Split long startup work with yields\",\n      \"text\": \"For your own startup code, process work in chunks and yield between them so no task exceeds 50ms.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Ship less JavaScript on the critical path\",\n      \"text\": \"Code-split by route and by interaction, remove unused polyfills, and replace heavy dependencies.\"\n    }\n  ]\n}\n",[1207,1212,1213],{"type":1209},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Reduce Total Blocking Time in Lighthouse\",\n  \"description\": \"How Lighthouse computes TBT, which tasks dominate it on real pages, and the split, defer and remove fixes that bring it under 200ms.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Freducing-total-blocking-time-in-lighthouse\u002F\"\n  }\n}\n",[1207,1215,1216],{"type":1209},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Core Web Vitals & Measurement\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Optimizing First Input Delay (FID) and INP\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Reducing Total Blocking Time in Lighthouse\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Freducing-total-blocking-time-in-lighthouse\u002F\"\n    }\n  ]\n}\n",[1218,1219,1220],"style",{},"html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}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 .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}",{"title":392,"searchDepth":405,"depth":405,"links":1222},[1223,1224,1225,1231,1232,1233,1234],{"id":215,"depth":405,"text":216},{"id":258,"depth":405,"text":259},{"id":376,"depth":405,"text":377,"children":1226},[1227,1228,1229,1230],{"id":381,"depth":427,"text":382},{"id":568,"depth":427,"text":569},{"id":663,"depth":427,"text":664},{"id":897,"depth":427,"text":898},{"id":1017,"depth":405,"text":1018},{"id":1140,"depth":405,"text":1141},{"id":1147,"depth":405,"text":1148},{"id":1181,"depth":405,"text":1182},"How Lighthouse computes TBT, which tasks dominate it on real pages, and the split, defer and remove fixes that bring it under 200ms.","md",{"slug":1238,"type":1239,"breadcrumb":1240,"datePublished":1248,"dateModified":1248},"reducing-total-blocking-time-in-lighthouse","article",[1241,1244,1245,1246],{"name":1242,"url":1243},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1247},"\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Freducing-total-blocking-time-in-lighthouse\u002F","2026-10-06",true,"\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Freducing-total-blocking-time-in-lighthouse",{"title":1252,"description":1253},"Reducing Total Blocking Time (TBT) in Lighthouse","TBT sums every long task’s time beyond 50ms between FCP and TTI. Find the tasks that dominate it, split or defer them, and lock in a TBT budget in CI.","core-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Freducing-total-blocking-time-in-lighthouse\u002Findex","ZuJiG4btGoQfJXnRnoQGuikwbV4hAJs5F6Xn3Ic2yzU",[1257,1261],{"title":1258,"path":1259,"stem":1260,"children":-1},"Improving INP for Complex Single-Page Applications","\u002Fcore-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Fimproving-inp-for-complex-single-page-applications","core-web-vitals-measurement\u002Foptimizing-first-input-delay-fid\u002Fimproving-inp-for-complex-single-page-applications\u002Findex",{"title":1262,"path":1263,"stem":1264,"children":-1},"Optimizing INP with scheduler.yield()","\u002Fcore-web-vitals-measurement\u002Foptimizing-inp-with-scheduler-yield","core-web-vitals-measurement\u002Foptimizing-inp-with-scheduler-yield\u002Findex",1791308073651]