[{"data":1,"prerenderedAt":1512},["ShallowReactive",2],{"page:\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fspeeding-up-slow-jekyll-builds":3,"all-docs-nav":973},{"id":4,"title":5,"body":6,"breadcrumb":946,"dateModified":956,"datePublished":956,"description":957,"extension":958,"faq":959,"meta":966,"navigation":967,"path":968,"seo":969,"slug":12,"stem":970,"type":971,"__hash__":972},"content\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fspeeding-up-slow-jekyll-builds\u002Findex.md","Speeding Up Slow Jekyll Builds",{"type":7,"value":8,"toc":927},"minimark",[9,13,17,31,36,59,63,105,113,120,268,272,287,353,360,374,384,465,469,496,500,564,568,575,649,743,747,763,774,778,794,798,843,847,850,854,859,862,866,869,873,876,880,883,887,923],[10,11,5],"h1",{"id":12},"speeding-up-slow-jekyll-builds",[14,15,16],"p",{},"Jekyll has a reputation for slow builds, and for large sites it is partly deserved: Ruby and Liquid are slower than Go templates or a compiled JavaScript pipeline. But most slow Jekyll sites are not slow because of Jekyll. They are slow because of a handful of template patterns — a sidebar that loops over every post on every page, a \"related posts\" include that compares every post with every other, a plugin that rewrites every page after rendering — whose cost grows with the square of the site's size. Those are fixable without leaving Jekyll.",[14,18,19,20,25,26,30],{},"This guide profiles a 3,200-post Jekyll blog and documentation site that took 6 minutes 40 seconds to build, fixes the four hot spots, and gets it to under two minutes. It is part of ",[21,22,24],"a",{"href":23},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002F","Jekyll Plugin Ecosystem","; if the fixes are not enough, ",[21,27,29],{"href":28},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Freplacing-jekyll-plugins-when-migrating-to-eleventy\u002F","Replacing Jekyll Plugins When Migrating to Eleventy"," covers the way out.",[32,33,35],"h2",{"id":34},"prerequisites","Prerequisites",[37,38,39,48,56],"ul",{},[40,41,42,43,47],"li",{},"Jekyll 4.x (Jekyll 4 added caching that 3.x lacks — upgrading alone often halves build time; see ",[21,44,46],{"href":45},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fupgrading-jekyll-and-ruby-versions-safely\u002F","Upgrading Jekyll and Ruby Versions Safely",").",[40,49,50,51,55],{},"Bundler and a ",[52,53,54],"code",{},"Gemfile.lock"," so every run uses the same gem versions.",[40,57,58],{},"A way to diff build output before and after, to make sure optimisations change nothing readers see.",[32,60,62],{"id":61},"step-1-profile","Step 1: Profile",[64,65,70],"pre",{"className":66,"code":67,"language":68,"meta":69,"style":69},"language-bash shiki shiki-themes github-light github-dark","bundle exec jekyll build --profile | head -25\n","bash","",[52,71,72],{"__ignoreMap":69},[73,74,77,81,85,88,91,95,99,102],"span",{"class":75,"line":76},"line",1,[73,78,80],{"class":79},"sScJk","bundle",[73,82,84],{"class":83},"sZZnC"," exec",[73,86,87],{"class":83}," jekyll",[73,89,90],{"class":83}," build",[73,92,94],{"class":93},"sj4cs"," --profile",[73,96,98],{"class":97},"szBVR"," |",[73,100,101],{"class":79}," head",[73,103,104],{"class":93}," -25\n",[64,106,111],{"className":107,"code":109,"language":110,"meta":69},[108],"language-text","| Filename                          | Count |    Bytes |    Time |\n|-----------------------------------+-------+----------+---------|\n| _includes\u002Frelated.html            |  3200 |  9.12MB  | 171.402 |\n| _includes\u002Fsidebar-archive.html    |  3406 | 41.33MB  |  98.119 |\n| _layouts\u002Fdefault.html             |  3406 | 212.4MB  |  41.866 |\n| _includes\u002Ftag-cloud.html          |  3406 |  7.81MB  |  38.205 |\n| _layouts\u002Fpost.html                |  3200 | 118.7MB  |  11.940 |\n| feed.xml                          |     1 |  2.44MB  |   4.117 |\n","text",[52,112,109],{"__ignoreMap":69},[14,114,115,116,119],{},"Two includes — related posts and the archive sidebar — accounted for 270 of 400 seconds. Neither did anything unusual; both looped over ",[52,117,118],{},"site.posts"," on every page.",[121,122,123,264],"figure",{},[124,125,132,133,132,137,132,141,132,148],"svg",{"viewBox":126,"role":127,"ariaLabelledBy":128,"xmlns":131},"0 0 760 280","img",[129,130],"jks-prof-title","jks-prof-desc","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","\n  ",[134,135,136],"title",{"id":129},"Where a 400-second Jekyll build spends its time",[138,139,140],"desc",{"id":130},"Bars from jekyll build --profile: related posts include 171 seconds, archive sidebar 98 seconds, default layout 42 seconds, tag cloud 38 seconds, post layout 12 seconds, feed 4 seconds.",[142,143],"rect",{"x":144,"y":144,"width":145,"height":146,"fill":147},"0","760","280","#ffffff",[149,150,152,153,152,160,152,167,152,172,152,182,152,188,152,192,152,196,152,201,152,205,152,212,152,217,152,221,152,225,152,230,152,234,152,240,152,245,152,249,152,254,152,258,132],"g",{"style":151},"font-family:system-ui, sans-serif;font-size:12px","\n    ",[110,154,159],{"x":155,"y":156,"fill":157,"style":158},"380","28","#1f2937","font-size:16px;font-weight:700;text-anchor:middle","Seconds per template, 3,200 posts (jekyll --profile)",[75,161],{"x1":162,"y1":163,"x2":162,"y2":164,"stroke":165,"style":166},"230","46","246","#d9e2ef","stroke-width:1.5px",[110,168,171],{"x":169,"y":170,"fill":157},"40","72","related.html",[142,173],{"x":162,"y":174,"width":175,"height":176,"rx":177,"fill":178,"opacity":179,"stroke":180,"style":181},"58","428","22","4","#ff595e","0.28","#d83b41","stroke-width:1px",[110,183,187],{"x":184,"y":185,"fill":157,"style":186},"666","74","font-weight:700","171",[110,189,191],{"x":169,"y":190,"fill":157},"104","sidebar-archive.html",[142,193],{"x":162,"y":194,"width":195,"height":176,"rx":177,"fill":178,"opacity":179,"stroke":180,"style":181},"90","245",[110,197,200],{"x":198,"y":199,"fill":157,"style":186},"483","106","98",[110,202,204],{"x":169,"y":203,"fill":157},"136","default.html",[142,206],{"x":162,"y":207,"width":208,"height":176,"rx":177,"fill":209,"opacity":210,"stroke":211,"style":181},"122","105","#ffca3a","0.4","#a97b00",[110,213,216],{"x":214,"y":215,"fill":157,"style":186},"343","138","42",[110,218,220],{"x":169,"y":219,"fill":157},"168","tag-cloud.html",[142,222],{"x":162,"y":223,"width":224,"height":176,"rx":177,"fill":209,"opacity":210,"stroke":211,"style":181},"154","95",[110,226,229],{"x":227,"y":228,"fill":157,"style":186},"333","170","38",[110,231,233],{"x":169,"y":232,"fill":157},"200","post.html",[142,235],{"x":162,"y":236,"width":237,"height":176,"rx":177,"fill":238,"opacity":239,"stroke":238,"style":181},"186","30","#1982c4","0.25",[110,241,244],{"x":242,"y":243,"fill":157,"style":186},"268","202","12",[110,246,248],{"x":169,"y":247,"fill":157},"232","feed.xml",[142,250],{"x":162,"y":251,"width":252,"height":176,"rx":253,"fill":238,"opacity":239,"stroke":238,"style":181},"218","10","2",[110,255,177],{"x":256,"y":257,"fill":157,"style":186},"248","234",[110,259,263],{"x":155,"y":260,"fill":261,"style":262},"266","#556071","font-size:11px;text-anchor:middle","Two includes that loop over site.posts on every page: 270 of 400 seconds",[265,266,267],"figcaption",{},"Per-page loops over the whole site are quadratic: double the posts and those two bars quadruple.",[32,269,271],{"id":270},"step-2-fix-quadratic-includes","Step 2: Fix Quadratic Includes",[14,273,274,278,279,282,283,286],{},[275,276,277],"strong",{},"Related posts."," The include compared every post's tags with every other post's tags on every post page — about 10 million comparisons. Jekyll's built-in ",[52,280,281],{},"site.related_posts"," (with ",[52,284,285],{},"lsi: false",") is cheap but crude; the better fix computes related posts once in a small generator plugin and stores the result on each post:",[64,288,292],{"className":289,"code":290,"language":291,"meta":69,"style":69},"language-ruby shiki shiki-themes github-light github-dark","# _plugins\u002Frelated.rb\nJekyll::Hooks.register :site, :pre_render do |site|\n  by_tag = Hash.new { |h, k| h[k] = [] }\n  site.posts.docs.each { |p| p.data['tags'].to_a.each { |t| by_tag[t] \u003C\u003C p } }\n  site.posts.docs.each do |post|\n    scores = Hash.new(0)\n    post.data['tags'].to_a.each { |t| by_tag[t].each { |o| scores[o] += 1 unless o == post } }\n    post.data['related'] = scores.sort_by { |o, s| [-s, -o.date.to_i] }.first(4).map(&:first)\n  end\nend\n","ruby",[52,293,294,299,305,311,317,323,329,335,341,347],{"__ignoreMap":69},[73,295,296],{"class":75,"line":76},[73,297,298],{},"# _plugins\u002Frelated.rb\n",[73,300,302],{"class":75,"line":301},2,[73,303,304],{},"Jekyll::Hooks.register :site, :pre_render do |site|\n",[73,306,308],{"class":75,"line":307},3,[73,309,310],{},"  by_tag = Hash.new { |h, k| h[k] = [] }\n",[73,312,314],{"class":75,"line":313},4,[73,315,316],{},"  site.posts.docs.each { |p| p.data['tags'].to_a.each { |t| by_tag[t] \u003C\u003C p } }\n",[73,318,320],{"class":75,"line":319},5,[73,321,322],{},"  site.posts.docs.each do |post|\n",[73,324,326],{"class":75,"line":325},6,[73,327,328],{},"    scores = Hash.new(0)\n",[73,330,332],{"class":75,"line":331},7,[73,333,334],{},"    post.data['tags'].to_a.each { |t| by_tag[t].each { |o| scores[o] += 1 unless o == post } }\n",[73,336,338],{"class":75,"line":337},8,[73,339,340],{},"    post.data['related'] = scores.sort_by { |o, s| [-s, -o.date.to_i] }.first(4).map(&:first)\n",[73,342,344],{"class":75,"line":343},9,[73,345,346],{},"  end\n",[73,348,350],{"class":75,"line":349},10,[73,351,352],{},"end\n",[14,354,355,356,359],{},"The include then renders ",[52,357,358],{},"page.related"," directly. An index by tag turns the quadratic comparison into roughly linear work: 171 s became 2.3 s.",[14,361,362,365,366,369,370,373],{},[275,363,364],{},"Archive sidebar."," Every page rendered a month-by-month archive of all 3,200 posts — the same 12 KB of HTML each time. Rendering it once with ",[52,367,368],{},"jekyll-include-cache"," (",[52,371,372],{},"{% include_cached sidebar-archive.html %}",") made it render once per build: 98 s became 0.4 s.",[14,375,376,379,380,383],{},[275,377,378],{},"Tag cloud."," Same pattern, same fix with ",[52,381,382],{},"include_cached",": 38 s became 0.2 s.",[121,385,386,462],{},[124,387,132,392,132,395,132,398,132,401],{"viewBox":388,"role":127,"ariaLabelledBy":389,"xmlns":131},"0 0 760 270",[390,391],"jks-quad-title","jks-quad-desc",[134,393,394],{"id":390},"Quadratic versus indexed related-posts work as the site grows",[138,396,397],{"id":391},"A line chart of related-posts time against number of posts. The per-page loop grows quadratically from about 2 seconds at 400 posts to 171 seconds at 3,200 posts. The tag-indexed hook grows roughly linearly and stays under 3 seconds.",[142,399],{"x":144,"y":144,"width":145,"height":400,"fill":147},"270",[149,402,152,403,152,406,152,411,152,414,152,419,152,423,152,428,152,432,152,436,152,440,152,446,152,450,152,456,132],{"style":151},[110,404,405],{"x":155,"y":156,"fill":157,"style":158},"Related-posts time vs number of posts",[75,407],{"x1":408,"y1":409,"x2":410,"y2":409,"stroke":261,"style":166},"80","220","720",[75,412],{"x1":408,"y1":413,"x2":408,"y2":409,"stroke":261,"style":166},"50",[110,415,418],{"x":170,"y":416,"fill":261,"style":417},"224","font-size:11px;text-anchor:end","0 s",[110,420,422],{"x":170,"y":421,"fill":261,"style":417},"54","180 s",[110,424,427],{"x":425,"y":426,"fill":261,"style":262},"160","238","400",[110,429,431],{"x":430,"y":426,"fill":261,"style":262},"320","1,200",[110,433,435],{"x":434,"y":426,"fill":261,"style":262},"480","2,000",[110,437,439],{"x":438,"y":426,"fill":261,"style":262},"700","3,200 posts",[441,442],"polyline",{"points":443,"fill":444,"stroke":180,"style":445},"160,218 240,212 320,196 400,174 480,146 560,112 640,82 700,58","none","stroke-width:2.5px",[441,447],{"points":448,"fill":444,"stroke":449,"style":445},"160,220 320,219 480,219 700,218","#5a8a16",[110,451,455],{"x":452,"y":185,"fill":453,"style":454},"620","#b32b30","font-size:11px;font-weight:700;text-anchor:end","per-page loop: 171 s",[110,457,461],{"x":458,"y":459,"fill":460,"style":454},"690","208","#3f6410","tag index: 2.3 s",[265,463,464],{},"A quadratic include feels fine at a few hundred posts and dominates the build a few years later.",[32,466,468],{"id":467},"checking-the-plugins-too","Checking the Plugins Too",[14,470,471,472,475,476,479,480,483,484,487,488,491,492,495],{},"The profile table covers templates, but plugin generators and hooks run outside it. Time them by building with each plugin disabled in turn (comment it out of ",[52,473,474],{},"_config.yml"," and the ",[52,477,478],{},"Gemfile","), or wrap hook bodies in ",[52,481,482],{},"Benchmark.realtime"," and log the result. On this site ",[52,485,486],{},"jekyll-seo-tag",", ",[52,489,490],{},"jekyll-sitemap"," and ",[52,493,494],{},"jekyll-feed"," together cost under three seconds — cheap for what they do — while a custom \"reading time\" plugin that re-parsed each post's HTML with Nokogiri cost 14 seconds. Computing reading time from the word count of the raw Markdown instead, which Jekyll already has in memory, reduced it to under half a second with results within one minute of the old values on every post.",[32,497,499],{"id":498},"step-3-cache-across-builds-and-trim-work","Step 3: Cache Across Builds and Trim Work",[37,501,502,516,537,550],{},[40,503,504,369,507,510,511,515],{},[275,505,506],{},"Jekyll 4's cache",[52,508,509],{},".jekyll-cache\u002F",") stores rendered Markdown and Sass; persist it between CI runs, as with the Hugo cache in ",[21,512,514],{"href":513},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fcaching-hugo-builds-in-github-actions\u002F","Caching Hugo Builds in GitHub Actions",".",[40,517,518,521,522,525,526,487,529,532,533,536],{},[275,519,520],{},"Exclude what does not need processing:"," ",[52,523,524],{},"exclude:"," for ",[52,527,528],{},"node_modules",[52,530,531],{},"vendor",", source images and drafts. The site was processing 1,900 files in an ",[52,534,535],{},"assets\u002Fsrc"," directory that were never output.",[40,538,539,542,543,546,547,515],{},[275,540,541],{},"Move asset pipelines out of Jekyll:"," Sass through ",[52,544,545],{},"jekyll-sass-converter"," is fine, but JavaScript bundling and image resizing belong in a separate step before ",[52,548,549],{},"jekyll build",[40,551,552,559,560,563],{},[275,553,554,555,558],{},"Use ",[52,556,557],{},"--incremental"," for writers, not deploys:"," locally, ",[52,561,562],{},"jekyll serve --incremental"," rebuilt an edited post in 4 seconds; for production it can miss pages that list other pages, so deploys stay full builds.",[32,565,567],{"id":566},"measured-impact","Measured Impact",[14,569,570,571,574],{},"GitHub Actions ",[52,572,573],{},"ubuntu-latest",", Ruby 3.3, Jekyll 4.3, median of three runs, output diffed against the original to confirm it was byte-identical apart from the related-posts ordering (which changed from arbitrary to score-sorted, deliberately).",[576,577,578,591],"table",{},[579,580,581],"thead",{},[582,583,584,588],"tr",{},[585,586,587],"th",{},"Change",[585,589,590],{},"Build time",[592,593,594,603,611,621,629,641],"tbody",{},[582,595,596,600],{},[597,598,599],"td",{},"Baseline",[597,601,602],{},"400 s",[582,604,605,608],{},[597,606,607],{},"Related posts via indexed hook",[597,609,610],{},"231 s",[582,612,613,618],{},[597,614,615,616],{},"Archive sidebar + tag cloud via ",[52,617,382],{},[597,619,620],{},"94 s",[582,622,623,626],{},[597,624,625],{},"Exclude unused source dirs",[597,627,628],{},"83 s",[582,630,631,638],{},[597,632,633,634,637],{},"Persist ",[52,635,636],{},".jekyll-cache"," in CI (warm)",[597,639,640],{},"61 s",[582,642,643,646],{},[597,644,645],{},"Local incremental rebuild, one post edited",[597,647,648],{},"4 s",[121,650,651,740],{},[124,652,132,657,132,660,132,663,132,666],{"viewBox":653,"role":127,"ariaLabelledBy":654,"xmlns":131},"0 0 760 260",[655,656],"jks-steps-title","jks-steps-desc",[134,658,659],{"id":655},"Build time after each change",[138,661,662],{"id":656},"Descending bars: baseline 400 seconds, related posts fixed 231, cached includes 94, excluded directories 83, warm cache 61.",[142,664],{"x":144,"y":144,"width":145,"height":665,"fill":147},"260",[149,667,152,668,152,671,152,675,152,677,152,682,152,687,152,691,152,695,152,700,152,707,152,711,152,716,152,721,152,725,152,728,152,730,152,733,152,736,132],{"style":151},[110,669,670],{"x":155,"y":156,"fill":157,"style":158},"From 400 s to 61 s in four changes",[75,672],{"x1":673,"y1":674,"x2":410,"y2":674,"stroke":261,"style":166},"60","210",[142,676],{"x":194,"y":413,"width":194,"height":425,"fill":178,"opacity":179,"stroke":180,"style":181},[110,678,427],{"x":679,"y":680,"fill":157,"style":681},"135","44","font-weight:700;text-anchor:middle",[142,683],{"x":684,"y":685,"width":194,"height":686,"fill":209,"opacity":210,"stroke":211,"style":181},"215","118","92",[110,688,690],{"x":665,"y":689,"fill":157,"style":681},"112","231",[142,692],{"x":693,"y":694,"width":194,"height":229,"fill":238,"opacity":239,"stroke":238,"style":181},"340","172",[110,696,699],{"x":697,"y":698,"fill":157,"style":681},"385","166","94",[142,701],{"x":702,"y":703,"width":194,"height":704,"fill":705,"opacity":706,"stroke":449,"style":181},"465","177","33","#8ac926","0.35",[110,708,710],{"x":709,"y":187,"fill":157,"style":681},"510","83",[142,712],{"x":713,"y":236,"width":194,"height":714,"fill":705,"opacity":715,"stroke":449,"style":181},"590","24","0.5",[110,717,720],{"x":718,"y":719,"fill":460,"style":681},"635","180","61",[110,722,724],{"x":679,"y":723,"fill":261,"style":262},"228","baseline",[110,726,727],{"x":665,"y":723,"fill":261,"style":262},"related index",[110,729,382],{"x":697,"y":723,"fill":261,"style":262},[110,731,732],{"x":709,"y":723,"fill":261,"style":262},"exclude",[110,734,735],{"x":718,"y":723,"fill":261,"style":262},"warm cache",[110,737,739],{"x":155,"y":738,"fill":261,"style":262},"250","seconds, GitHub Actions ubuntu-latest, Jekyll 4.3, median of 3",[265,741,742],{},"The two template fixes delivered most of the gain; caching and exclusions finished the job.",[32,744,746],{"id":745},"keeping-it-fast","Keeping It Fast",[14,748,749,750,753,754,487,756,759,760,762],{},"Build time crept from 90 seconds to 400 over three years on this site without anyone deciding to make it slow; each include was reasonable when written. Two habits keep it from happening again. First, run ",[52,751,752],{},"jekyll build --profile"," in CI on the main branch and store the top ten rows as a build artifact, alerting when total time grows more than 20% over the previous month. Second, review new includes for loops over ",[52,755,118],{},[52,757,758],{},"site.pages"," or collections, and ask whether the result depends on the current page. If it does not, it belongs in ",[52,761,382],{},"; if it does but only through a small key (tag, category, year), it belongs in a hook that computes it once, like the related-posts index above.",[14,764,765,766,768,769,773],{},"GitHub Pages users should note that ",[52,767,368],{}," and custom plugins are not on the Pages allow-list; building in GitHub Actions and deploying the output, as in ",[21,770,772],{"href":771},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fdeploying-to-github-pages-with-actions\u002F","Deploying to GitHub Pages with Actions",", removes that restriction and was a precondition for every fix here.",[32,775,777],{"id":776},"when-jekyll-is-still-too-slow","When Jekyll Is Still Too Slow",[14,779,780,781,784,785,788,789,793],{},"After these fixes, the remaining 61 seconds were mostly Markdown rendering and Liquid execution for 3,400 pages — genuine per-page work. A few more percent is available from ",[52,782,783],{},"kramdown"," options (disabling unused extensions) or switching the Markdown engine to CommonMark via ",[52,786,787],{},"jekyll-commonmark",", which rendered about 30% faster here. Beyond that, Jekyll's per-page cost is simply higher than Hugo's or Eleventy's; the same content built in 9 seconds with Hugo after a migration test. If builds must stay under ten seconds for previews, that is when a migration is justified, and ",[21,790,792],{"href":791},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Feleventy-vs-jekyll-for-markdown-heavy-blogs\u002F","Eleventy vs Jekyll for Markdown-Heavy Blogs"," compares the most common destination.",[32,795,797],{"id":796},"pitfalls-rollback","Pitfalls & Rollback",[37,799,800,810,822,831,837],{},[40,801,802,805,806,809],{},[275,803,804],{},"Optimising without profiling."," Guessing usually targets the wrong template; ",[52,807,808],{},"--profile"," takes one build to answer.",[40,811,812,817,818,821],{},[275,813,814,816],{},[52,815,382],{}," on page-dependent includes."," It caches by include parameters only; an include that reads ",[52,819,820],{},"page.url"," returns the first page's output everywhere. Pass page-specific values as parameters or do not cache.",[40,823,824,830],{},[275,825,826,827,829],{},"Trusting ",[52,828,557],{}," for deploys."," It can miss listing pages; keep production builds full.",[40,832,833,836],{},[275,834,835],{},"Skipping the output diff."," Always compare built output before and after to catch caching mistakes.",[40,838,839,842],{},[275,840,841],{},"Rollback:"," every change is a template or config edit; reverting one restores its behaviour on the next build.",[32,844,846],{"id":845},"conclusion","Conclusion",[14,848,849],{},"Slow Jekyll builds are usually quadratic templates, not a slow generator. Profiling a 3,200-post site found two includes looping over every post on every page; indexing related posts in a hook and caching the invariant includes took the build from 400 to 94 seconds, and exclusions plus a persisted cache brought it to 61. Fix the templates first; migrate only if per-page cost is still the bottleneck.",[32,851,853],{"id":852},"faq","FAQ",[855,856,858],"h3",{"id":857},"how-do-i-find-out-why-a-jekyll-build-is-slow","How do I find out why a Jekyll build is slow?",[14,860,861],{},"Run jekyll build --profile. It prints a table of every template and include with the number of times it was rendered and the total time spent, which usually shows one or two includes or layouts responsible for most of the build.",[855,863,865],{"id":864},"does-jekyll-build-incremental-work-in-production","Does jekyll build --incremental work in production?",[14,867,868],{},"It is marked experimental and can miss dependencies, such as a page that lists other pages. Use it for local writing and previews, and run full builds for production deploys.",[855,870,872],{"id":871},"which-plugins-slow-jekyll-down-most","Which plugins slow Jekyll down most?",[14,874,875],{},"Plugins that touch every page on every build: related-posts calculations, full-site search index generators, SEO and sitemap plugins with expensive per-page logic, and image processing without a cache. jekyll-seo-tag and jekyll-sitemap are cheap; custom generators often are not.",[855,877,879],{"id":878},"is-it-worth-migrating-away-from-jekyll-for-build-speed","Is it worth migrating away from Jekyll for build speed?",[14,881,882],{},"Sometimes, but first fix the templates. Most slow Jekyll sites are slow because of a few Liquid loops over site.pages or site.posts on every page, which are fixable in an afternoon and often cut build time by more than half.",[32,884,886],{"id":885},"related","Related",[37,888,889,897,902,909,916],{},[40,890,891,521,894,896],{},[275,892,893],{},"Parent:",[21,895,24],{"href":23}," — plugins, their costs and alternatives.",[40,898,899,901],{},[21,900,46],{"href":45}," — Jekyll 4's caching needs an upgrade first.",[40,903,904,908],{},[21,905,907],{"href":906},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Frunning-jekyll-on-github-pages-without-plugins\u002F","Running Jekyll on GitHub Pages Without Plugins"," — when plugins are not an option.",[40,910,911,915],{},[21,912,914],{"href":913},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhugo-partialcached-for-faster-builds\u002F","Hugo partialCached for Faster Builds"," — the same idea in Hugo.",[40,917,918,922],{},[21,919,921],{"href":920},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-docs-site-from-jekyll-to-hugo\u002F","Migrating a Docs Site from Jekyll to Hugo"," — the migration when fixes are not enough.",[924,925,926],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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);}",{"title":69,"searchDepth":301,"depth":301,"links":928},[929,930,931,932,933,934,935,936,937,938,939,945],{"id":34,"depth":301,"text":35},{"id":61,"depth":301,"text":62},{"id":270,"depth":301,"text":271},{"id":467,"depth":301,"text":468},{"id":498,"depth":301,"text":499},{"id":566,"depth":301,"text":567},{"id":745,"depth":301,"text":746},{"id":776,"depth":301,"text":777},{"id":796,"depth":301,"text":797},{"id":845,"depth":301,"text":846},{"id":852,"depth":301,"text":853,"children":940},[941,942,943,944],{"id":857,"depth":307,"text":858},{"id":864,"depth":307,"text":865},{"id":871,"depth":307,"text":872},{"id":878,"depth":307,"text":879},{"id":885,"depth":301,"text":886},[947,950,953,954],{"name":948,"item":949},"Home","\u002F",{"name":951,"item":952},"Choosing the Right Static Site Generator for Production","\u002Fchoosing-the-right-static-site-generator-for-production\u002F",{"name":24,"item":23},{"name":5,"item":955},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fspeeding-up-slow-jekyll-builds\u002F","2026-09-18","Profile a slow Jekyll build, find the Liquid loops and plugins that dominate it, and apply caching and template fixes that cut build time by over 80%.","md",[960,961,962,965],{"q":858,"a":861},{"q":865,"a":868},{"q":872,"a":963},{"Plugins that touch every page on every build":964},"related-posts calculations, full-site search index generators, SEO and sitemap plugins with expensive per-page logic, and image processing without a cache. jekyll-seo-tag and jekyll-sitemap are cheap; custom generators often are not.",{"q":879,"a":882},{},true,"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fspeeding-up-slow-jekyll-builds",{"title":5,"description":957},"choosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fspeeding-up-slow-jekyll-builds\u002Findex","article","tIGTisZ1RzAoR-zuc_KN-TqLGcYcfLk5Vg-hQ_YMSPw",[974,977,980,983,986,989,992,995,998,1001,1004,1007,1010,1013,1016,1018,1021,1024,1027,1030,1032,1034,1036,1038,1040,1041,1043,1046,1049,1052,1055,1058,1061,1064,1067,1070,1073,1076,1079,1082,1085,1088,1091,1094,1097,1100,1103,1106,1109,1112,1115,1118,1121,1124,1127,1130,1133,1136,1139,1142,1145,1148,1151,1154,1157,1160,1163,1166,1169,1172,1175,1178,1181,1184,1187,1190,1193,1196,1199,1202,1205,1208,1211,1214,1217,1220,1223,1226,1229,1232,1235,1238,1241,1244,1247,1250,1253,1256,1259,1262,1265,1268,1271,1274,1277,1280,1283,1286,1289,1292,1295,1298,1301,1304,1307,1310,1313,1316,1319,1322,1325,1328,1331,1334,1337,1340,1343,1345,1348,1351,1354,1357,1359,1362,1365,1368,1371,1374,1377,1380,1383,1386,1389,1392,1395,1398,1401,1404,1407,1410,1413,1416,1419,1422,1425,1428,1431,1434,1437,1440,1443,1446,1449,1452,1455,1458,1461,1464,1467,1470,1473,1476,1479,1482,1485,1488,1491,1494,1497,1500,1503,1506,1509],{"path":975,"title":976},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fastro-vs-eleventy-build-times-at-10000-pages","Astro vs Eleventy Build Times at 10,000 Pages",{"path":978,"title":979},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fchoosing-between-astro-and-eleventy-for-large-docs","Astro vs Eleventy for Large Docs (1000+ Pages)",{"path":981,"title":982},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fcontent-collections-vs-eleventy-data-cascade","Content Collections vs the Eleventy Data Cascade",{"path":984,"title":985},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites","Astro vs Eleventy for Documentation Sites",{"path":987,"title":988},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fshortcodes-vs-components-for-docs-authors","Shortcodes vs Components for Docs Authors",{"path":990,"title":991},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fastro-vs-eleventy-for-documentation-sites\u002Fsidebar-navigation-in-astro-and-eleventy","Sidebar Navigation in Astro and Eleventy",{"path":993,"title":994},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fcustomizing-starlight-without-forking-the-theme","Customizing Starlight Without Forking the Theme",{"path":996,"title":997},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fdocusaurus-vs-starlight-for-product-documentation","Docusaurus vs Starlight for Product Documentation",{"path":999,"title":1000},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress","Docs Frameworks: Docusaurus, Starlight and VitePress",{"path":1002,"title":1003},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmdx-vs-markdoc-for-docs-content","MDX vs Markdoc for Docs Content",{"path":1005,"title":1006},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fmigrating-from-mkdocs-to-starlight","Migrating from MkDocs to Starlight",{"path":1008,"title":1009},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fversioned-documentation-with-docusaurus","Versioned Documentation with Docusaurus",{"path":1011,"title":1012},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fdocs-frameworks-docusaurus-starlight-vitepress\u002Fvitepress-for-library-documentation","VitePress for Library Documentation",{"path":1014,"title":1015},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhow-to-benchmark-hugo-vs-astro-build-speeds","How to Benchmark Hugo vs Astro Build Speeds",{"path":1017,"title":914},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fhugo-partialcached-for-faster-builds",{"path":1019,"title":1020},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories","Hugo Build Times for Large Repositories",{"path":1022,"title":1023},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fprofiling-hugo-templates-with-template-metrics","Profiling Hugo Templates With Template Metrics",{"path":1025,"title":1026},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Freducing-hugo-memory-usage-on-ci-runners","Reducing Hugo Memory Usage on CI Runners",{"path":1028,"title":1029},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fhugo-build-times-for-large-repositories\u002Fspeeding-up-hugo-builds-with-render-hooks-and-caching","Speeding Up Hugo Builds with Render Hooks & Caching",{"path":1031,"title":951},"\u002Fchoosing-the-right-static-site-generator-for-production",{"path":1033,"title":792},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Feleventy-vs-jekyll-for-markdown-heavy-blogs",{"path":1035,"title":24},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem",{"path":1037,"title":29},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Freplacing-jekyll-plugins-when-migrating-to-eleventy",{"path":1039,"title":907},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Frunning-jekyll-on-github-pages-without-plugins",{"path":968,"title":5},{"path":1042,"title":46},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fjekyll-plugin-ecosystem\u002Fupgrading-jekyll-and-ruby-versions-safely",{"path":1044,"title":1045},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fconverting-front-matter-at-scale-during-migration","Converting Front Matter at Scale During Migration",{"path":1047,"title":1048},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators","Migrating Between Static Site Generators",{"path":1050,"title":1051},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fkeeping-redirects-working-after-an-ssg-migration","Keeping Redirects Working After an SSG Migration",{"path":1053,"title":1054},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-a-docs-site-from-jekyll-to-hugo","Migrating a Docs Site From Jekyll to Hugo",{"path":1056,"title":1057},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-from-gatsby-to-astro","Migrating from Gatsby to Astro",{"path":1059,"title":1060},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-from-hugo-to-astro-without-breaking-urls","Migrating From Hugo to Astro Without Breaking URLs",{"path":1062,"title":1063},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fmigrating-wordpress-to-a-static-site-generator","Migrating WordPress to a Static Site Generator",{"path":1065,"title":1066},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fmigrating-between-static-site-generators\u002Fporting-shortcodes-and-includes-between-generators","Porting Shortcodes and Includes Between Generators",{"path":1068,"title":1069},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fhandling-dynamic-routes-in-nextjs-static-export","Handling Dynamic Routes in Next.js Static Export",{"path":1071,"title":1072},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites","Next.js Static Export for Content Sites",{"path":1074,"title":1075},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fmigrating-from-gatsby-to-nextjs-static-export","Migrating from Gatsby to Next.js Static Export",{"path":1077,"title":1078},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-app-router-static-export-limitations","Next.js App Router Static Export Limitations",{"path":1080,"title":1081},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Fnextjs-static-export-vs-astro-for-marketing-sites","Next.js Static Export vs Astro for Marketing",{"path":1083,"title":1084},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fnextjs-static-export-for-content-sites\u002Foptimizing-images-in-nextjs-static-export","Optimizing Images in Next.js Static Export",{"path":1086,"title":1087},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fadding-pagefind-to-an-astro-site","Adding Pagefind to an Astro Site",{"path":1089,"title":1090},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fbuilding-a-lunr-index-at-build-time-in-eleventy","Building a Lunr Index at Build Time in Eleventy",{"path":1092,"title":1093},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites","Search for Static Sites",{"path":1095,"title":1096},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Findexing-hugo-sites-with-pagefind","Indexing Hugo Sites with Pagefind",{"path":1098,"title":1099},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fmultilingual-search-on-static-sites","Multilingual Search on Static Sites",{"path":1101,"title":1102},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fpagefind-vs-algolia-docsearch","Pagefind vs Algolia DocSearch",{"path":1104,"title":1105},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fsearch-for-static-sites\u002Fsearch-index-size-budgets-for-large-docs","Search Index Size Budgets for Large Docs",{"path":1107,"title":1108},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fbest-ssg-for-technical-writers-without-coding-experience","Best SSG for Non-Developer Technical Writers",{"path":1110,"title":1111},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fchoosing-an-ssg-for-api-reference-documentation","Choosing an SSG for API Reference Documentation",{"path":1113,"title":1114},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fevaluating-ssg-accessibility-defaults","Evaluating SSG Accessibility Defaults",{"path":1116,"title":1117},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix","SSG Framework Selection Matrix",{"path":1119,"title":1120},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fpicking-an-ssg-for-a-multi-language-documentation-site","Picking an SSG for a Multi-Language Docs Site",{"path":1122,"title":1123},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Fssg-selection-checklist-for-engineering-teams","SSG Selection Checklist for Engineering Teams",{"path":1125,"title":1126},"\u002Fchoosing-the-right-static-site-generator-for-production\u002Fssg-framework-selection-matrix\u002Ftotal-cost-of-ownership-for-static-site-generators","Total Cost of Ownership for Static Site Generators",{"path":1128,"title":1129},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fcache-busting-with-content-hashed-filenames","Cache Busting with Content-Hashed Filenames",{"path":1131,"title":1132},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs","CDN Caching Rules for SSGs",{"path":1134,"title":1135},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fpurging-the-cdn-cache-after-a-static-deploy","Purging the CDN Cache After a Static Deploy",{"path":1137,"title":1138},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fsetting-cache-control-headers-on-cloudflare-pages","Cache-Control Headers on Cloudflare Pages",{"path":1140,"title":1141},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fsetting-up-proper-cache-headers-on-netlify","Proper Cache Headers on Netlify for SSGs",{"path":1143,"title":1144},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcdn-caching-rules-for-ssgs\u002Fstale-while-revalidate-for-static-html","Stale-While-Revalidate for Static HTML",{"path":1146,"title":1147},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Feliminating-layout-shift-from-web-fonts","Eliminating Layout Shift From Web Fonts",{"path":1149,"title":1150},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-cookie-banners","Fixing CLS from Cookie Banners",{"path":1152,"title":1153},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-late-loading-embeds","Fixing CLS From Late-Loading Embeds",{"path":1155,"title":1156},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Ffixing-cls-from-sticky-headers-and-anchor-links","Fixing CLS from Sticky Headers and Anchor Links",{"path":1158,"title":1159},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites","Cumulative Layout Shift Fixes for Static Sites",{"path":1161,"title":1162},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Fmeasuring-cls-in-the-field-with-web-vitals-js","Measuring CLS in the Field With web-vitals.js",{"path":1164,"title":1165},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fcumulative-layout-shift-fixes-for-static-sites\u002Freserving-space-for-images-and-embeds-to-stop-layout-shift","Reserving Space for Images and Embeds",{"path":1167,"title":1168},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Ffont-display-optional-vs-swap","font-display: optional vs swap",{"path":1170,"title":1171},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites","Font Loading Strategies for Static Sites",{"path":1173,"title":1174},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fmetric-matched-fallback-fonts-with-size-adjust","Metric-Matched Fallback Fonts with size-adjust",{"path":1176,"title":1177},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fpreloading-fonts-without-double-downloads","Preloading Fonts Without Double Downloads",{"path":1179,"title":1180},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fself-hosting-google-fonts-to-eliminate-layout-shift","Self-Host Google Fonts to Eliminate Layout Shift",{"path":1182,"title":1183},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Ffont-loading-strategies-for-static-sites\u002Fsubsetting-variable-fonts-for-faster-first-render","Subsetting Variable Fonts for Faster First Render",{"path":1185,"title":1186},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fbuilding-an-image-cdn-pipeline-for-static-sites","Building an Image CDN Pipeline for Static Sites",{"path":1188,"title":1189},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fgenerating-open-graph-images-at-build-time","Generating Open Graph Images at Build Time",{"path":1191,"title":1192},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro","Image Optimization Pipelines in Astro",{"path":1194,"title":1195},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Flazy-loading-images-without-hurting-lcp","Lazy-Loading Images Without Hurting LCP",{"path":1197,"title":1198},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Foptimizing-webp-images-in-hugo-without-plugins","Optimizing WebP Images in Hugo Without Plugins",{"path":1200,"title":1201},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fresponsive-images-with-srcset-in-eleventy","Responsive Images with srcset in Eleventy",{"path":1203,"title":1204},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fimage-optimization-pipelines-in-astro\u002Fserving-avif-with-fallbacks-on-static-sites","Serving AVIF With Fallbacks on Static Sites",{"path":1206,"title":1207},"\u002Fperformance-optimization-core-web-vitals-for-ssgs","Core Web Vitals Optimization for SSGs",{"path":1209,"title":1210},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fastro-islands-vs-full-hydration-performance","Astro Islands vs Full Hydration Performance",{"path":1212,"title":1213},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fdeferring-hydration-with-client-visible-in-astro","Deferring Hydration with client:visible in Astro",{"path":1215,"title":1216},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fhow-to-reduce-bundle-size-in-eleventy-builds","How to Reduce Bundle Size in Eleventy Builds",{"path":1218,"title":1219},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering","JavaScript Hydration & Partial Rendering",{"path":1221,"title":1222},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Fmeasuring-inp-on-static-sites-with-real-user-monitoring","Measuring INP on Static Sites with RUM",{"path":1224,"title":1225},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fjavascript-hydration-partial-rendering\u002Freplacing-react-islands-with-web-components","Replacing React Islands with Web Components",{"path":1227,"title":1228},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Feliminating-render-blocking-css-on-static-sites","Eliminating Render-Blocking CSS on Static Sites",{"path":1230,"title":1231},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Ffixing-lcp-on-text-heavy-documentation-pages","Fixing LCP on Text-Heavy Documentation Pages",{"path":1233,"title":1234},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites","Largest Contentful Paint Optimization for Static Sites",{"path":1236,"title":1237},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Fmeasuring-lcp-subparts-with-devtools","Measuring LCP Subparts with DevTools",{"path":1239,"title":1240},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Foptimizing-lcp-on-astro-with-priority-hints","Optimizing LCP on Astro with Priority Hints",{"path":1242,"title":1243},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Flargest-contentful-paint-optimization-for-static-sites\u002Freducing-lcp-from-hero-images-on-static-sites","Reducing LCP from Hero Images on Static Sites",{"path":1245,"title":1246},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fcomparing-lab-and-field-data-with-crux","Comparing Lab and Field Data with CrUX",{"path":1248,"title":1249},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci","Performance Budgets and Lighthouse CI",{"path":1251,"title":1252},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Freducing-lighthouse-score-variance-in-ci","Reducing Lighthouse Score Variance in CI",{"path":1254,"title":1255},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Frunning-webpagetest-scripts-against-preview-deploys","Running WebPageTest Scripts Against Preview Deploys",{"path":1257,"title":1258},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fsetting-up-lighthouse-ci-for-a-static-site","Setting Up Lighthouse CI for a Static Site",{"path":1260,"title":1261},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Ftracking-bundle-size-per-pull-request","Tracking Bundle Size per Pull Request",{"path":1263,"title":1264},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fperformance-budgets-and-lighthouse-ci\u002Fwriting-a-performance-budget-that-fails-builds","Writing a Performance Budget That Fails Builds",{"path":1266,"title":1267},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fauditing-unused-preloads","Auditing Unused Preloads",{"path":1269,"title":1270},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed","Resource Hints and Navigation Speed",{"path":1272,"title":1273},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Finstant-navigation-with-speculation-rules","Instant Navigation with Speculation Rules",{"path":1275,"title":1276},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fpreconnect-vs-dns-prefetch-on-static-sites","Preconnect vs DNS-Prefetch on Static Sites",{"path":1278,"title":1279},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fprefetching-links-in-astro","Prefetching Links in Astro",{"path":1281,"title":1282},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fresource-hints-and-navigation-speed\u002Fview-transitions-on-multi-page-static-sites","View Transitions on Multi-Page Static Sites",{"path":1284,"title":1285},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fauditing-third-party-scripts-with-lighthouse","Auditing Third-Party Scripts With Lighthouse",{"path":1287,"title":1288},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites","Third-Party Script Performance on Static Sites",{"path":1290,"title":1291},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Flazy-loading-youtube-embeds-on-static-sites","Lazy-Loading YouTube Embeds on Static Sites",{"path":1293,"title":1294},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Floading-google-tag-manager-without-hurting-inp","Loading Google Tag Manager Without Hurting INP",{"path":1296,"title":1297},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Frunning-third-party-scripts-in-a-web-worker-with-partytown","Running Third-Party Scripts in a Web Worker with Partytown",{"path":1299,"title":1300},"\u002Fperformance-optimization-core-web-vitals-for-ssgs\u002Fthird-party-script-performance-on-static-sites\u002Fself-hosting-analytics-to-cut-third-party-requests","Self-Hosting Analytics to Cut Third-Party Requests",{"path":1302,"title":1303},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fautomating-eleventy-deployments-with-cloudflare-pages","Automating Eleventy Deployments on Cloudflare Pages",{"path":1305,"title":1306},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fconfiguring-redirects-on-cloudflare-pages","Configuring Redirects on Cloudflare Pages",{"path":1308,"title":1309},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fcustom-domains-and-tls-on-cloudflare-pages","Custom Domains and TLS on Cloudflare Pages",{"path":1311,"title":1312},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fdeploying-hugo-to-cloudflare-pages-and-workers","Deploying Hugo to Cloudflare Pages and Workers",{"path":1314,"title":1315},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup","Cloudflare Pages Edge Caching Setup",{"path":1317,"title":1318},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcloudflare-pages-edge-caching-setup\u002Fmigrating-from-cloudflare-pages-to-workers-static-assets","Migrating from Cloudflare Pages to Workers Static Assets",{"path":1320,"title":1321},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fchecking-links-in-pull-requests","Checking Links in Pull Requests",{"path":1323,"title":1324},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fdocs-as-code-review-workflow-for-writers","Docs-as-Code Review Workflow for Writers",{"path":1326,"title":1327},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Feditorial-checks-with-vale-in-ci","Editorial Checks with Vale in CI",{"path":1329,"title":1330},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams","Content Workflows for Documentation Teams",{"path":1332,"title":1333},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fscheduling-content-publication-with-cron-triggered-builds","Scheduling Content Publication With Cron-Triggered Builds",{"path":1335,"title":1336},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fcontent-workflows-for-documentation-teams\u002Fwiring-a-headless-cms-to-a-static-build","Wiring a Headless CMS to a Static Build",{"path":1338,"title":1339},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fbuilding-astro-sites-with-github-actions","Building Astro Sites with GitHub Actions",{"path":1341,"title":1342},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fcaching-node-modules-in-github-actions-for-faster-ssg-builds","Caching node_modules in GitHub Actions",{"path":1344,"title":772},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fdeploying-to-github-pages-with-actions",{"path":1346,"title":1347},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fdeploying-to-multiple-environments-from-one-workflow","Deploying to Multiple Environments From One Workflow",{"path":1349,"title":1350},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fhow-to-set-up-github-actions-for-hugo-deployments","GitHub Actions for Hugo Deployments",{"path":1352,"title":1353},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds","GitHub Actions for Automated SSG Builds",{"path":1355,"title":1356},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fgithub-actions-for-automated-ssg-builds\u002Fmatrix-builds-for-multi-site-monorepos","Matrix Builds for Multi-Site Monorepos",{"path":1358,"title":514},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fcaching-hugo-builds-in-github-actions",{"path":1360,"title":1361},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fenabling-incremental-builds-in-eleventy","Enabling Incremental Builds in Eleventy",{"path":1363,"title":1364},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fincremental-builds-in-astro-with-the-content-layer","Incremental Builds in Astro with the Content Layer",{"path":1366,"title":1367},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs","Incremental Builds and Build Caching for SSGs",{"path":1369,"title":1370},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fmeasuring-build-time-regressions-in-ci","Measuring Build-Time Regressions in CI",{"path":1372,"title":1373},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fremote-caching-with-turborepo-for-ssg-monorepos","Remote Caching with Turborepo for SSG Monorepos",{"path":1375,"title":1376},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fincremental-builds-and-build-caching-for-ssgs\u002Fsharing-build-cache-across-ci-runners","Sharing Build Cache Across CI Runners",{"path":1378,"title":1379},"\u002Fproduction-ready-deployment-cicd-workflows","Production-Ready Deployment & CI\u002FCD for SSGs",{"path":1381,"title":1382},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Falerting-on-cache-hit-ratio-drops","Alerting on Cache Hit Ratio Drops",{"path":1384,"title":1385},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fbuilding-a-core-web-vitals-dashboard-from-rum-data","Building a Core Web Vitals Dashboard from RUM Data",{"path":1387,"title":1388},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fcrawling-for-broken-links-on-a-schedule","Crawling for Broken Links on a Schedule",{"path":1390,"title":1391},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production","Monitoring Static Sites in Production",{"path":1393,"title":1394},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Flogging-404s-at-the-edge","Logging 404s at the Edge",{"path":1396,"title":1397},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fmonitoring-static-sites-in-production\u002Fuptime-and-synthetic-checks-for-static-sites","Uptime and Synthetic Checks for Static Sites",{"path":1399,"title":1400},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fconfiguring-vercel-for-hugo-and-eleventy","Configuring Vercel for Hugo and Eleventy",{"path":1402,"title":1403},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies","Netlify vs Vercel Deployment Strategies",{"path":1405,"title":1406},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-build-hooks-for-content-updates","Netlify Build Hooks for Content Updates",{"path":1408,"title":1409},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fnetlify-redirects-and-rewrites-for-static-sites","Netlify Redirects and Rewrites for Static Sites",{"path":1411,"title":1412},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fsetting-up-deploy-previews-on-netlify-for-every-pull-request","Netlify Deploy Previews for Every Pull Request",{"path":1414,"title":1415},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fnetlify-vs-vercel-deployment-strategies\u002Fvercel-isr-vs-static-generation-for-ssgs","Vercel ISR vs Static Generation for SSGs",{"path":1417,"title":1418},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fautomating-preview-deploy-pipelines-with-github-actions","Automating Preview Deploy Pipelines with GitHub Actions",{"path":1420,"title":1421},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fcleaning-up-stale-preview-deployments","Cleaning Up Stale Preview Deployments",{"path":1423,"title":1424},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests","Preview Environments for Pull Requests",{"path":1426,"title":1427},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpassword-protecting-preview-deployments","Password-Protecting Preview Deployments",{"path":1429,"title":1430},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fpreviewing-headless-cms-drafts","Previewing Headless CMS Drafts",{"path":1432,"title":1433},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fpreview-environments-for-pull-requests\u002Fvisual-regression-testing-on-preview-deploys","Visual Regression Testing on Preview Deploys",{"path":1435,"title":1436},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fatomic-deploys-vs-incremental-uploads","Atomic Deploys vs Incremental Uploads",{"path":1438,"title":1439},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Fcanary-releases-for-static-sites","Canary Releases for Static Sites",{"path":1441,"title":1442},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Ffeature-flags-on-static-sites","Feature Flags on Static Sites",{"path":1444,"title":1445},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites","Rollbacks and Deploy Safety for Static Sites",{"path":1447,"title":1448},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frolling-back-a-bad-static-deploy-in-under-a-minute","Rolling Back a Bad Static Deploy in Under a Minute",{"path":1450,"title":1451},"\u002Fproduction-ready-deployment-cicd-workflows\u002Frollbacks-and-deploy-safety-for-static-sites\u002Frunning-smoke-tests-against-a-preview-url","Running Smoke Tests Against a Preview URL",{"path":1453,"title":1454},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fauditing-npm-dependencies-in-ssg-pipelines","Auditing npm Dependencies in SSG Pipelines",{"path":1456,"title":1457},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fenabling-hsts-and-preload-safely","Enabling HSTS and Preload Safely",{"path":1459,"title":1460},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fhash-based-csp-for-inline-scripts-in-astro","Hash-Based CSP for Inline Scripts in Astro",{"path":1462,"title":1463},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites","Security Headers and Hardening for Static Sites",{"path":1465,"title":1466},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsecuring-deploy-credentials-with-github-oidc","Securing Deploy Credentials with GitHub OIDC",{"path":1468,"title":1469},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fsubresource-integrity-for-third-party-assets","Subresource Integrity for Third-Party Assets",{"path":1471,"title":1472},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fsecurity-headers-for-static-sites\u002Fwriting-a-content-security-policy-for-a-static-site","Writing a Content Security Policy for a Static Site",{"path":1474,"title":1475},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fclean-urls-and-trailing-slashes-on-s3","Clean URLs and Trailing Slashes on S3",{"path":1477,"title":1478},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fcloudfront-functions-for-redirects","CloudFront Functions for Redirects",{"path":1480,"title":1481},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fdeploying-a-static-site-to-s3-and-cloudfront","Deploying a Static Site to S3 and CloudFront",{"path":1483,"title":1484},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites","Self-Hosting Static Sites on S3, Nginx and Caddy",{"path":1486,"title":1487},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-caddy","Serving a Static Site with Caddy",{"path":1489,"title":1490},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fserving-a-static-site-with-nginx","Serving a Static Site with Nginx",{"path":1492,"title":1493},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fself-hosting-static-sites\u002Fzero-downtime-deploys-with-symlink-swaps","Zero-Downtime Deploys with Symlink Swaps",{"path":1495,"title":1496},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fadding-a-contact-form-with-cloudflare-workers","Adding a Contact Form with Cloudflare Workers",{"path":1498,"title":1499},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fhandling-form-submissions-on-a-static-site","Handling Form Submissions on a Static Site",{"path":1501,"title":1502},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites","Serverless Functions for Static Sites",{"path":1504,"title":1505},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fnetlify-functions-vs-cloudflare-workers","Netlify Functions vs Cloudflare Workers",{"path":1507,"title":1508},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fprotecting-a-static-site-behind-authentication","Protecting a Static Site Behind Authentication",{"path":1510,"title":1511},"\u002Fproduction-ready-deployment-cicd-workflows\u002Fserverless-functions-for-static-sites\u002Fproxying-third-party-apis-from-an-edge-function","Proxying Third-Party APIs from an Edge Function",1789722848010]