[{"data":1,"prerenderedAt":1437},["ShallowReactive",2],{"navigation":3,"/blog/js-perf":50},[4],{"title":5,"path":6,"stem":7,"children":8,"page":49},"Blog","/blog","blog",[9,13,17,21,25,29,33,37,41,45],{"title":10,"path":11,"stem":12},"Unlocking the Power of Django: A Developer-Friendly Architecture Guide","/blog/django-arhitecture","blog/01.django-arhitecture",{"title":14,"path":15,"stem":16},"Getting Started with Go: Why You Should Learn Golang","/blog/intro-go","blog/02.intro-go",{"title":18,"path":19,"stem":20},"Recursion in JavaScript: The Art of Functions Calling Themselves","/blog/recursion-js","blog/03.recursion-js",{"title":22,"path":23,"stem":24},"What Go Got Right and Wrong: A Thoughtful Look Back","/blog/golang-pro-and-cons","blog/04.golang-pro-and-cons",{"title":26,"path":27,"stem":28},"JavaScript Performance Optimization: A Practical Guide for Better Web Applications","/blog/js-perf","blog/05.js-perf",{"title":30,"path":31,"stem":32},"Understanding Go Slices: A Powerful Data Structure","/blog/go-slices-article","blog/06.go-slices-article",{"title":34,"path":35,"stem":36},"The Model Context Protocol (MCP): Giving AI \"Hands\"","/blog/mcp-article-complete","blog/07.mcp-article-complete",{"title":38,"path":39,"stem":40},"CSS Grid Mastery: Advanced Layout Techniques for Intermediate Developers","/blog/css-grid","blog/08.css-grid",{"title":42,"path":43,"stem":44},"Modern JavaScript: Mastering the Fetch API with Async/Await","/blog/fetch-api","blog/09.fetch-api",{"title":46,"path":47,"stem":48},"How to Use AWS for Cloud-Based Web Development","/blog/aws-webdev","blog/10.aws-webdev",false,[51,1432],{"id":52,"title":26,"author":53,"badge":59,"body":61,"date":1419,"description":1420,"extension":1421,"image":1422,"meta":1423,"navigation":254,"path":27,"readingTime":1424,"seo":1429,"stem":28,"tags":1430,"__hash__":1431},"blog/blog/05.js-perf.md",[54],{"name":55,"to":56,"avatar":57},"Norbert Br3tt","https://www.linkedin.com/in/norbert-brett/",{"src":58,"alt":55},"https://res.cloudinary.com/nbrett/image/upload/v1725625689/IMG_0698_d0nhun.jpg",{"label":60},"JavaScript",{"type":62,"value":63,"toc":1410},"minimark",[64,69,73,76,81,84,87,384,387,505,508,512,515,632,646,649,722,725,732,739,916,919,923,926,1123,1133,1136,1219,1223,1226,1302,1309,1363,1366,1370,1373,1404,1407],[65,66,68],"h1",{"id":67},"javascript-performance-tricks-that-actually-move-the-needle","JavaScript Performance Tricks That Actually Move the Needle",[70,71,72],"p",{},"Storytime: I once inherited a codebase where a \"simple\" list render was taking over 800ms. The culprit? A loop that was touching the DOM 200 times instead of once. One refactor, four lines changed, and it dropped to 12ms. I've been a little obsessed with JS performance ever since.",[70,74,75],{},"The good news: you don't need to understand V8 internals to write fast JavaScript. A handful of patterns cover 90% of the gains you'll ever need. Let's dig in.",[77,78,80],"h2",{"id":79},"stop-touching-the-dom-so-much","Stop Touching the DOM So Much",[70,82,83],{},"Every time you modify the DOM, the browser recalculates styles, reruns layout, and repaints. Do it in a loop and you're triggering that whole pipeline on every iteration.",[70,85,86],{},"The fix: batch your changes off-screen first, then commit once.",[88,89,94],"pre",{"className":90,"code":91,"language":92,"meta":93,"style":93},"language-javascript shiki shiki-themes vitesse-dark","// ❌ Triggers a reflow for every single item\nconst container = document.getElementById('user-list');\nusers.forEach(user => {\n  const li = document.createElement('li');\n  li.textContent = user.name;\n  container.appendChild(li); // reflow, reflow, reflow...\n});\n\n// ✅ One reflow, no matter how many items\nconst fragment = document.createDocumentFragment();\nusers.forEach(user => {\n  const li = document.createElement('li');\n  li.textContent = user.name;\n  fragment.appendChild(li);\n});\ncontainer.appendChild(fragment); // single reflow here\n","javascript","",[95,96,97,106,147,169,198,222,243,249,256,262,282,299,324,343,359,364],"code",{"__ignoreMap":93},[98,99,102],"span",{"class":100,"line":101},"line",1,[98,103,105],{"class":104},"sux-A","// ❌ Triggers a reflow for every single item\n",[98,107,109,113,117,121,124,127,131,134,138,142,144],{"class":100,"line":108},2,[98,110,112],{"class":111},"s_wWq","const",[98,114,116],{"class":115},"st-jp"," container",[98,118,120],{"class":119},"s_pn2"," =",[98,122,123],{"class":115}," document",[98,125,126],{"class":119},".",[98,128,130],{"class":129},"sCK9x","getElementById",[98,132,133],{"class":119},"(",[98,135,137],{"class":136},"sNJcY","'",[98,139,141],{"class":140},"s7rlk","user-list",[98,143,137],{"class":136},[98,145,146],{"class":119},");\n",[98,148,150,153,155,158,160,163,166],{"class":100,"line":149},3,[98,151,152],{"class":115},"users",[98,154,126],{"class":119},[98,156,157],{"class":129},"forEach",[98,159,133],{"class":119},[98,161,162],{"class":115},"user",[98,164,165],{"class":119}," =>",[98,167,168],{"class":119}," {\n",[98,170,172,175,178,180,182,184,187,189,191,194,196],{"class":100,"line":171},4,[98,173,174],{"class":111},"  const",[98,176,177],{"class":115}," li",[98,179,120],{"class":119},[98,181,123],{"class":115},[98,183,126],{"class":119},[98,185,186],{"class":129},"createElement",[98,188,133],{"class":119},[98,190,137],{"class":136},[98,192,193],{"class":140},"li",[98,195,137],{"class":136},[98,197,146],{"class":119},[98,199,201,204,206,209,211,214,216,219],{"class":100,"line":200},5,[98,202,203],{"class":115},"  li",[98,205,126],{"class":119},[98,207,208],{"class":115},"textContent",[98,210,120],{"class":119},[98,212,213],{"class":115}," user",[98,215,126],{"class":119},[98,217,218],{"class":115},"name",[98,220,221],{"class":119},";\n",[98,223,225,228,230,233,235,237,240],{"class":100,"line":224},6,[98,226,227],{"class":115},"  container",[98,229,126],{"class":119},[98,231,232],{"class":129},"appendChild",[98,234,133],{"class":119},[98,236,193],{"class":115},[98,238,239],{"class":119},");",[98,241,242],{"class":104}," // reflow, reflow, reflow...\n",[98,244,246],{"class":100,"line":245},7,[98,247,248],{"class":119},"});\n",[98,250,252],{"class":100,"line":251},8,[98,253,255],{"emptyLinePlaceholder":254},true,"\n",[98,257,259],{"class":100,"line":258},9,[98,260,261],{"class":104},"// ✅ One reflow, no matter how many items\n",[98,263,265,267,270,272,274,276,279],{"class":100,"line":264},10,[98,266,112],{"class":111},[98,268,269],{"class":115}," fragment",[98,271,120],{"class":119},[98,273,123],{"class":115},[98,275,126],{"class":119},[98,277,278],{"class":129},"createDocumentFragment",[98,280,281],{"class":119},"();\n",[98,283,285,287,289,291,293,295,297],{"class":100,"line":284},11,[98,286,152],{"class":115},[98,288,126],{"class":119},[98,290,157],{"class":129},[98,292,133],{"class":119},[98,294,162],{"class":115},[98,296,165],{"class":119},[98,298,168],{"class":119},[98,300,302,304,306,308,310,312,314,316,318,320,322],{"class":100,"line":301},12,[98,303,174],{"class":111},[98,305,177],{"class":115},[98,307,120],{"class":119},[98,309,123],{"class":115},[98,311,126],{"class":119},[98,313,186],{"class":129},[98,315,133],{"class":119},[98,317,137],{"class":136},[98,319,193],{"class":140},[98,321,137],{"class":136},[98,323,146],{"class":119},[98,325,327,329,331,333,335,337,339,341],{"class":100,"line":326},13,[98,328,203],{"class":115},[98,330,126],{"class":119},[98,332,208],{"class":115},[98,334,120],{"class":119},[98,336,213],{"class":115},[98,338,126],{"class":119},[98,340,218],{"class":115},[98,342,221],{"class":119},[98,344,346,349,351,353,355,357],{"class":100,"line":345},14,[98,347,348],{"class":115},"  fragment",[98,350,126],{"class":119},[98,352,232],{"class":129},[98,354,133],{"class":119},[98,356,193],{"class":115},[98,358,146],{"class":119},[98,360,362],{"class":100,"line":361},15,[98,363,248],{"class":119},[98,365,367,370,372,374,376,379,381],{"class":100,"line":366},16,[98,368,369],{"class":115},"container",[98,371,126],{"class":119},[98,373,232],{"class":129},[98,375,133],{"class":119},[98,377,378],{"class":115},"fragment",[98,380,239],{"class":119},[98,382,383],{"class":104}," // single reflow here\n",[70,385,386],{},"Same idea applies to style changes. Instead of setting individual properties — which each trigger their own recalculation — swap a CSS class instead:",[88,388,390],{"className":90,"code":389,"language":92,"meta":93,"style":93},"// ❌ Multiple style changes = multiple reflows\nelement.style.width = '200px';\nelement.style.height = '200px';\nelement.style.backgroundColor = 'blue';\n\n// ✅ One class change = one reflow\nelement.classList.add('highlighted-box');\n",[95,391,392,397,424,447,471,475,480],{"__ignoreMap":93},[98,393,394],{"class":100,"line":101},[98,395,396],{"class":104},"// ❌ Multiple style changes = multiple reflows\n",[98,398,399,402,404,407,409,412,414,417,420,422],{"class":100,"line":108},[98,400,401],{"class":115},"element",[98,403,126],{"class":119},[98,405,406],{"class":115},"style",[98,408,126],{"class":119},[98,410,411],{"class":115},"width",[98,413,120],{"class":119},[98,415,416],{"class":136}," '",[98,418,419],{"class":140},"200px",[98,421,137],{"class":136},[98,423,221],{"class":119},[98,425,426,428,430,432,434,437,439,441,443,445],{"class":100,"line":149},[98,427,401],{"class":115},[98,429,126],{"class":119},[98,431,406],{"class":115},[98,433,126],{"class":119},[98,435,436],{"class":115},"height",[98,438,120],{"class":119},[98,440,416],{"class":136},[98,442,419],{"class":140},[98,444,137],{"class":136},[98,446,221],{"class":119},[98,448,449,451,453,455,457,460,462,464,467,469],{"class":100,"line":171},[98,450,401],{"class":115},[98,452,126],{"class":119},[98,454,406],{"class":115},[98,456,126],{"class":119},[98,458,459],{"class":115},"backgroundColor",[98,461,120],{"class":119},[98,463,416],{"class":136},[98,465,466],{"class":140},"blue",[98,468,137],{"class":136},[98,470,221],{"class":119},[98,472,473],{"class":100,"line":200},[98,474,255],{"emptyLinePlaceholder":254},[98,476,477],{"class":100,"line":224},[98,478,479],{"class":104},"// ✅ One class change = one reflow\n",[98,481,482,484,486,489,491,494,496,498,501,503],{"class":100,"line":245},[98,483,401],{"class":115},[98,485,126],{"class":119},[98,487,488],{"class":115},"classList",[98,490,126],{"class":119},[98,492,493],{"class":129},"add",[98,495,133],{"class":119},[98,497,137],{"class":136},[98,499,500],{"class":140},"highlighted-box",[98,502,137],{"class":136},[98,504,146],{"class":119},[70,506,507],{},"Your CSS already lives in a stylesheet. Let the browser do its job.",[77,509,511],{"id":510},"write-loops-that-know-when-to-stop","Write Loops That Know When to Stop",[70,513,514],{},"Loops are where I see the most avoidable waste. The classic example: iterating an entire array looking for one item, even after you've found it.",[88,516,518],{"className":90,"code":517,"language":92,"meta":93,"style":93},"// ❌ Checks all 10,000 users even after finding the one you want\nlet target;\nusers.forEach(user => {\n  if (user.id === 42) target = user;\n});\n\n// ✅ Stops the moment it finds a match\nconst target = users.find(user => user.id === 42);\n",[95,519,520,525,535,551,585,589,593,598],{"__ignoreMap":93},[98,521,522],{"class":100,"line":101},[98,523,524],{"class":104},"// ❌ Checks all 10,000 users even after finding the one you want\n",[98,526,527,530,533],{"class":100,"line":108},[98,528,529],{"class":111},"let",[98,531,532],{"class":115}," target",[98,534,221],{"class":119},[98,536,537,539,541,543,545,547,549],{"class":100,"line":149},[98,538,152],{"class":115},[98,540,126],{"class":119},[98,542,157],{"class":129},[98,544,133],{"class":119},[98,546,162],{"class":115},[98,548,165],{"class":119},[98,550,168],{"class":119},[98,552,553,557,560,562,564,567,570,574,577,579,581,583],{"class":100,"line":171},[98,554,556],{"class":555},"s3QIE","  if",[98,558,559],{"class":119}," (",[98,561,162],{"class":115},[98,563,126],{"class":119},[98,565,566],{"class":115},"id",[98,568,569],{"class":111}," ===",[98,571,573],{"class":572},"sxA9i"," 42",[98,575,576],{"class":119},")",[98,578,532],{"class":115},[98,580,120],{"class":119},[98,582,213],{"class":115},[98,584,221],{"class":119},[98,586,587],{"class":100,"line":200},[98,588,248],{"class":119},[98,590,591],{"class":100,"line":224},[98,592,255],{"emptyLinePlaceholder":254},[98,594,595],{"class":100,"line":245},[98,596,597],{"class":104},"// ✅ Stops the moment it finds a match\n",[98,599,600,602,604,606,609,611,614,616,618,620,622,624,626,628,630],{"class":100,"line":251},[98,601,112],{"class":111},[98,603,532],{"class":115},[98,605,120],{"class":119},[98,607,608],{"class":115}," users",[98,610,126],{"class":119},[98,612,613],{"class":129},"find",[98,615,133],{"class":119},[98,617,162],{"class":115},[98,619,165],{"class":119},[98,621,213],{"class":115},[98,623,126],{"class":119},[98,625,566],{"class":115},[98,627,569],{"class":111},[98,629,573],{"class":572},[98,631,146],{"class":119},[70,633,634,637,638,641,642,645],{},[95,635,636],{},"find()",", ",[95,639,640],{},"some()",", and ",[95,643,644],{},"findIndex()"," all short-circuit — they stop iterating the moment the condition is met. Reach for them before writing a manual loop.",[70,647,648],{},"For hot loops over large datasets, cache the array length:",[88,650,652],{"className":90,"code":651,"language":92,"meta":93,"style":93},"const len = items.length;\nfor (let i = 0; i \u003C len; i++) {\n  // avoids re-evaluating items.length on every iteration\n}\n",[95,653,654,674,712,717],{"__ignoreMap":93},[98,655,656,658,661,663,666,668,672],{"class":100,"line":101},[98,657,112],{"class":111},[98,659,660],{"class":115}," len",[98,662,120],{"class":119},[98,664,665],{"class":115}," items",[98,667,126],{"class":119},[98,669,671],{"class":670},"sm68I","length",[98,673,221],{"class":119},[98,675,676,679,681,683,686,688,691,694,696,699,701,703,705,708,710],{"class":100,"line":108},[98,677,678],{"class":555},"for",[98,680,559],{"class":119},[98,682,529],{"class":111},[98,684,685],{"class":115}," i",[98,687,120],{"class":119},[98,689,690],{"class":572}," 0",[98,692,693],{"class":119},";",[98,695,685],{"class":115},[98,697,698],{"class":119}," \u003C",[98,700,660],{"class":115},[98,702,693],{"class":119},[98,704,685],{"class":115},[98,706,707],{"class":111},"++",[98,709,576],{"class":119},[98,711,168],{"class":119},[98,713,714],{"class":100,"line":149},[98,715,716],{"class":104},"  // avoids re-evaluating items.length on every iteration\n",[98,718,719],{"class":100,"line":171},[98,720,721],{"class":119},"}\n",[70,723,724],{},"Micro-optimization? Maybe. But in tight loops processing thousands of items, it adds up.",[77,726,728,729],{"id":727},"parallel-async-operations-with-promiseall","Parallel Async Operations with ",[95,730,731],{},"Promise.all",[70,733,734,735,738],{},"This one is genuinely underused. If you have multiple independent async operations, ",[95,736,737],{},"await","-ing them sequentially is leaving performance on the table.",[88,740,742],{"className":90,"code":741,"language":92,"meta":93,"style":93},"// ❌ Sequential — 6 seconds total\nasync function loadPage() {\n  const users    = await fetchUsers();    // 2s\n  const posts    = await fetchPosts();    // 2s\n  const comments = await fetchComments(); // 2s\n}\n\n// ✅ Parallel — 2 seconds total\nasync function loadPage() {\n  const [users, posts, comments] = await Promise.all([\n    fetchUsers(),\n    fetchPosts(),\n    fetchComments()\n  ]);\n}\n",[95,743,744,749,765,786,804,823,827,831,836,848,884,892,899,907,912],{"__ignoreMap":93},[98,745,746],{"class":100,"line":101},[98,747,748],{"class":104},"// ❌ Sequential — 6 seconds total\n",[98,750,751,754,757,760,763],{"class":100,"line":108},[98,752,753],{"class":111},"async",[98,755,756],{"class":111}," function",[98,758,759],{"class":129}," loadPage",[98,761,762],{"class":119},"()",[98,764,168],{"class":119},[98,766,767,769,771,774,777,780,783],{"class":100,"line":149},[98,768,174],{"class":111},[98,770,608],{"class":115},[98,772,773],{"class":119},"    =",[98,775,776],{"class":555}," await",[98,778,779],{"class":129}," fetchUsers",[98,781,782],{"class":119},"();",[98,784,785],{"class":104},"    // 2s\n",[98,787,788,790,793,795,797,800,802],{"class":100,"line":171},[98,789,174],{"class":111},[98,791,792],{"class":115}," posts",[98,794,773],{"class":119},[98,796,776],{"class":555},[98,798,799],{"class":129}," fetchPosts",[98,801,782],{"class":119},[98,803,785],{"class":104},[98,805,806,808,811,813,815,818,820],{"class":100,"line":200},[98,807,174],{"class":111},[98,809,810],{"class":115}," comments",[98,812,120],{"class":119},[98,814,776],{"class":555},[98,816,817],{"class":129}," fetchComments",[98,819,782],{"class":119},[98,821,822],{"class":104}," // 2s\n",[98,824,825],{"class":100,"line":224},[98,826,721],{"class":119},[98,828,829],{"class":100,"line":245},[98,830,255],{"emptyLinePlaceholder":254},[98,832,833],{"class":100,"line":251},[98,834,835],{"class":104},"// ✅ Parallel — 2 seconds total\n",[98,837,838,840,842,844,846],{"class":100,"line":258},[98,839,753],{"class":111},[98,841,756],{"class":111},[98,843,759],{"class":129},[98,845,762],{"class":119},[98,847,168],{"class":119},[98,849,850,852,855,857,860,862,864,866,869,871,873,876,878,881],{"class":100,"line":264},[98,851,174],{"class":111},[98,853,854],{"class":119}," [",[98,856,152],{"class":115},[98,858,859],{"class":119},",",[98,861,792],{"class":115},[98,863,859],{"class":119},[98,865,810],{"class":115},[98,867,868],{"class":119},"]",[98,870,120],{"class":119},[98,872,776],{"class":555},[98,874,875],{"class":670}," Promise",[98,877,126],{"class":119},[98,879,880],{"class":129},"all",[98,882,883],{"class":119},"([\n",[98,885,886,889],{"class":100,"line":284},[98,887,888],{"class":129},"    fetchUsers",[98,890,891],{"class":119},"(),\n",[98,893,894,897],{"class":100,"line":301},[98,895,896],{"class":129},"    fetchPosts",[98,898,891],{"class":119},[98,900,901,904],{"class":100,"line":326},[98,902,903],{"class":129},"    fetchComments",[98,905,906],{"class":119},"()\n",[98,908,909],{"class":100,"line":345},[98,910,911],{"class":119},"  ]);\n",[98,913,914],{"class":100,"line":361},[98,915,721],{"class":119},[70,917,918],{},"The rule is simple: if the requests don't depend on each other's results, run them together. I personally check for this pattern in every code review — it's one of the easiest wins available.",[77,920,922],{"id":921},"lazy-load-what-you-dont-need-yet","Lazy Load What You Don't Need Yet",[70,924,925],{},"Don't pay the cost of loading something until the user actually needs it. The Intersection Observer API makes this trivial for images:",[88,927,929],{"className":90,"code":928,"language":92,"meta":93,"style":93},"const observer = new IntersectionObserver(entries => {\n  entries.forEach(entry => {\n    if (entry.isIntersecting) {\n      const img = entry.target;\n      img.src = img.dataset.src;\n      observer.unobserve(img);\n    }\n  });\n});\n\ndocument.querySelectorAll('img[data-src]').forEach(img => {\n  observer.observe(img);\n});\n",[95,930,931,955,973,991,1011,1036,1053,1058,1063,1067,1071,1103,1119],{"__ignoreMap":93},[98,932,933,935,938,940,943,946,948,951,953],{"class":100,"line":101},[98,934,112],{"class":111},[98,936,937],{"class":115}," observer",[98,939,120],{"class":119},[98,941,942],{"class":111}," new",[98,944,945],{"class":129}," IntersectionObserver",[98,947,133],{"class":119},[98,949,950],{"class":115},"entries",[98,952,165],{"class":119},[98,954,168],{"class":119},[98,956,957,960,962,964,966,969,971],{"class":100,"line":108},[98,958,959],{"class":115},"  entries",[98,961,126],{"class":119},[98,963,157],{"class":129},[98,965,133],{"class":119},[98,967,968],{"class":115},"entry",[98,970,165],{"class":119},[98,972,168],{"class":119},[98,974,975,978,980,982,984,987,989],{"class":100,"line":149},[98,976,977],{"class":555},"    if",[98,979,559],{"class":119},[98,981,968],{"class":115},[98,983,126],{"class":119},[98,985,986],{"class":115},"isIntersecting",[98,988,576],{"class":119},[98,990,168],{"class":119},[98,992,993,996,999,1001,1004,1006,1009],{"class":100,"line":171},[98,994,995],{"class":111},"      const",[98,997,998],{"class":115}," img",[98,1000,120],{"class":119},[98,1002,1003],{"class":115}," entry",[98,1005,126],{"class":119},[98,1007,1008],{"class":115},"target",[98,1010,221],{"class":119},[98,1012,1013,1016,1018,1021,1023,1025,1027,1030,1032,1034],{"class":100,"line":200},[98,1014,1015],{"class":115},"      img",[98,1017,126],{"class":119},[98,1019,1020],{"class":115},"src",[98,1022,120],{"class":119},[98,1024,998],{"class":115},[98,1026,126],{"class":119},[98,1028,1029],{"class":115},"dataset",[98,1031,126],{"class":119},[98,1033,1020],{"class":115},[98,1035,221],{"class":119},[98,1037,1038,1041,1043,1046,1048,1051],{"class":100,"line":224},[98,1039,1040],{"class":115},"      observer",[98,1042,126],{"class":119},[98,1044,1045],{"class":129},"unobserve",[98,1047,133],{"class":119},[98,1049,1050],{"class":115},"img",[98,1052,146],{"class":119},[98,1054,1055],{"class":100,"line":245},[98,1056,1057],{"class":119},"    }\n",[98,1059,1060],{"class":100,"line":251},[98,1061,1062],{"class":119},"  });\n",[98,1064,1065],{"class":100,"line":258},[98,1066,248],{"class":119},[98,1068,1069],{"class":100,"line":264},[98,1070,255],{"emptyLinePlaceholder":254},[98,1072,1073,1076,1078,1081,1083,1085,1088,1090,1093,1095,1097,1099,1101],{"class":100,"line":284},[98,1074,1075],{"class":115},"document",[98,1077,126],{"class":119},[98,1079,1080],{"class":129},"querySelectorAll",[98,1082,133],{"class":119},[98,1084,137],{"class":136},[98,1086,1087],{"class":140},"img[data-src]",[98,1089,137],{"class":136},[98,1091,1092],{"class":119},").",[98,1094,157],{"class":129},[98,1096,133],{"class":119},[98,1098,1050],{"class":115},[98,1100,165],{"class":119},[98,1102,168],{"class":119},[98,1104,1105,1108,1110,1113,1115,1117],{"class":100,"line":301},[98,1106,1107],{"class":115},"  observer",[98,1109,126],{"class":119},[98,1111,1112],{"class":129},"observe",[98,1114,133],{"class":119},[98,1116,1050],{"class":115},[98,1118,146],{"class":119},[98,1120,1121],{"class":100,"line":326},[98,1122,248],{"class":119},[70,1124,1125,1126,1129,1130,1132],{},"Mark your images with ",[95,1127,1128],{},"data-src"," instead of ",[95,1131,1020],{},", and they only load as they scroll into view. For image-heavy pages, this alone can dramatically improve initial load time.",[70,1134,1135],{},"The same principle applies to JavaScript modules. If a feature is only used sometimes, import it dynamically instead of bundling it upfront:",[88,1137,1139],{"className":90,"code":1138,"language":92,"meta":93,"style":93},"button.addEventListener('click', async () => {\n  const { heavyFeature } = await import('./heavyFeature.js');\n  heavyFeature.init();\n});\n",[95,1140,1141,1172,1203,1215],{"__ignoreMap":93},[98,1142,1143,1146,1148,1151,1153,1155,1158,1160,1162,1165,1168,1170],{"class":100,"line":101},[98,1144,1145],{"class":115},"button",[98,1147,126],{"class":119},[98,1149,1150],{"class":129},"addEventListener",[98,1152,133],{"class":119},[98,1154,137],{"class":136},[98,1156,1157],{"class":140},"click",[98,1159,137],{"class":136},[98,1161,859],{"class":119},[98,1163,1164],{"class":111}," async",[98,1166,1167],{"class":119}," ()",[98,1169,165],{"class":119},[98,1171,168],{"class":119},[98,1173,1174,1176,1179,1182,1185,1187,1189,1192,1194,1196,1199,1201],{"class":100,"line":108},[98,1175,174],{"class":111},[98,1177,1178],{"class":119}," {",[98,1180,1181],{"class":115}," heavyFeature",[98,1183,1184],{"class":119}," }",[98,1186,120],{"class":119},[98,1188,776],{"class":555},[98,1190,1191],{"class":111}," import",[98,1193,133],{"class":119},[98,1195,137],{"class":136},[98,1197,1198],{"class":140},"./heavyFeature.js",[98,1200,137],{"class":136},[98,1202,146],{"class":119},[98,1204,1205,1208,1210,1213],{"class":100,"line":149},[98,1206,1207],{"class":115},"  heavyFeature",[98,1209,126],{"class":119},[98,1211,1212],{"class":129},"init",[98,1214,281],{"class":119},[98,1216,1217],{"class":100,"line":171},[98,1218,248],{"class":119},[77,1220,1222],{"id":1221},"measure-first-optimize-second","Measure First, Optimize Second",[70,1224,1225],{},"Here's the thing I wish someone had told me earlier: don't guess at bottlenecks. Measure them.",[88,1227,1229],{"className":90,"code":1228,"language":92,"meta":93,"style":93},"const start = performance.now();\ndoExpensiveThing();\nconsole.log(`Took ${performance.now() - start}ms`);\n",[95,1230,1231,1250,1257],{"__ignoreMap":93},[98,1232,1233,1235,1238,1240,1243,1245,1248],{"class":100,"line":101},[98,1234,112],{"class":111},[98,1236,1237],{"class":115}," start",[98,1239,120],{"class":119},[98,1241,1242],{"class":115}," performance",[98,1244,126],{"class":119},[98,1246,1247],{"class":129},"now",[98,1249,281],{"class":119},[98,1251,1252,1255],{"class":100,"line":108},[98,1253,1254],{"class":129},"doExpensiveThing",[98,1256,281],{"class":119},[98,1258,1259,1262,1264,1267,1269,1272,1275,1278,1281,1283,1285,1287,1290,1292,1295,1298,1300],{"class":100,"line":149},[98,1260,1261],{"class":115},"console",[98,1263,126],{"class":119},[98,1265,1266],{"class":129},"log",[98,1268,133],{"class":119},[98,1270,1271],{"class":136},"`",[98,1273,1274],{"class":140},"Took ",[98,1276,1277],{"class":555},"${",[98,1279,1280],{"class":140},"performance",[98,1282,126],{"class":119},[98,1284,1247],{"class":129},[98,1286,762],{"class":119},[98,1288,1289],{"class":111}," -",[98,1291,1237],{"class":140},[98,1293,1294],{"class":555},"}",[98,1296,1297],{"class":140},"ms",[98,1299,1271],{"class":136},[98,1301,146],{"class":119},[70,1303,1304,1305,1308],{},"Or use ",[95,1306,1307],{},"console.time"," for quick checks:",[88,1310,1312],{"className":90,"code":1311,"language":92,"meta":93,"style":93},"console.time('render');\nrenderList();\nconsole.timeEnd('render'); // \"render: 23.4ms\"\n",[95,1313,1314,1334,1341],{"__ignoreMap":93},[98,1315,1316,1318,1320,1323,1325,1327,1330,1332],{"class":100,"line":101},[98,1317,1261],{"class":115},[98,1319,126],{"class":119},[98,1321,1322],{"class":129},"time",[98,1324,133],{"class":119},[98,1326,137],{"class":136},[98,1328,1329],{"class":140},"render",[98,1331,137],{"class":136},[98,1333,146],{"class":119},[98,1335,1336,1339],{"class":100,"line":108},[98,1337,1338],{"class":129},"renderList",[98,1340,281],{"class":119},[98,1342,1343,1345,1347,1350,1352,1354,1356,1358,1360],{"class":100,"line":149},[98,1344,1261],{"class":115},[98,1346,126],{"class":119},[98,1348,1349],{"class":129},"timeEnd",[98,1351,133],{"class":119},[98,1353,137],{"class":136},[98,1355,1329],{"class":140},[98,1357,137],{"class":136},[98,1359,239],{"class":119},[98,1361,1362],{"class":104}," // \"render: 23.4ms\"\n",[70,1364,1365],{},"Open DevTools, run a Performance trace, and let the flame graph show you where time is actually going. Nine times out of ten it's not where you expected.",[77,1367,1369],{"id":1368},"the-short-list","The Short List",[70,1371,1372],{},"When something feels slow, work through this in order:",[1374,1375,1376,1379,1382,1393,1398,1401],"ul",{},[193,1377,1378],{},"Batch DOM changes with document fragments",[193,1380,1381],{},"Swap CSS classes instead of inline styles",[193,1383,1384,1385,1387,1388,1129,1390,1392],{},"Use ",[95,1386,636],{}," / ",[95,1389,640],{},[95,1391,157],{}," when you need early exit",[193,1394,1395,1396],{},"Run independent async calls with ",[95,1397,731],{},[193,1399,1400],{},"Lazy load images and heavy modules",[193,1402,1403],{},"Measure before and after — every time",[70,1405,1406],{},"Performance work is satisfying precisely because the feedback is immediate. Slow → fast, measured before and after. Go find your 800ms and make it 12. 🎉",[406,1408,1409],{},"html pre.shiki code .sux-A, html code.shiki .sux-A{--shiki-default:#758575DD}html pre.shiki code .s_wWq, html code.shiki .s_wWq{--shiki-default:#CB7676}html pre.shiki code .st-jp, html code.shiki .st-jp{--shiki-default:#BD976A}html pre.shiki code .s_pn2, html code.shiki .s_pn2{--shiki-default:#666666}html pre.shiki code .sCK9x, html code.shiki .sCK9x{--shiki-default:#80A665}html pre.shiki code .sNJcY, html code.shiki .sNJcY{--shiki-default:#C98A7D77}html pre.shiki code .s7rlk, html code.shiki .s7rlk{--shiki-default:#C98A7D}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 pre.shiki code .s3QIE, html code.shiki .s3QIE{--shiki-default:#4D9375}html pre.shiki code .sxA9i, html code.shiki .sxA9i{--shiki-default:#4C9A91}html pre.shiki code .sm68I, html code.shiki .sm68I{--shiki-default:#B8A965}",{"title":93,"searchDepth":108,"depth":108,"links":1411},[1412,1413,1414,1416,1417,1418],{"id":79,"depth":108,"text":80},{"id":510,"depth":108,"text":511},{"id":727,"depth":108,"text":1415},"Parallel Async Operations with Promise.all",{"id":921,"depth":108,"text":922},{"id":1221,"depth":108,"text":1222},{"id":1368,"depth":108,"text":1369},"2026-01-03T00:00:00.000Z","Learn proven techniques to optimize your JavaScript code for better performance. Master DOM manipulation, efficient loops, HTTP request optimization, and asynchronous programming with practical examples.","md","https://res.cloudinary.com/nbrett/image/upload/v1767465370/js_perf_hero_kq8zua.jpg",{},{"text":1425,"minutes":1426,"time":1427,"words":1428},"4 min read",3.69,221400,738,{"title":26,"description":1420},null,"wLJ9wR3CAM1V7e1KZPMIDo87BQ3ql49bs_wBWhjH2Ko",[1433,1435],{"title":22,"path":23,"stem":24,"description":1434,"children":-1},"A reflective and opinionated look at the Go programming language, combining insights from co-creator Rob Pike with real-world developer experience. This article explores Go’s strengths, trade-offs, and where it truly shines or falls short in modern software development.",{"title":30,"path":31,"stem":32,"description":1436,"children":-1},"Discover how Go slices work and why they're one of the most versatile data structures in the language. Learn to create, manipulate, and optimize slices with practical examples and best practices.",1774167727253]