有 如此之多 静态网站生成器 (SSG)。 尝试决定从哪里开始令人不知所措。虽然大量有用的文章可能有助于浏览(流行的)选项,但它们并不能神奇地使决策变得容易。
我一直在努力帮助简化这一决策。我的同事 构建了一个静态网站生成器评估备忘单。它提供了许多流行的 SSG 选择的非常好的快照。缺少的是它们在实际操作中的表现。

每个静态网站生成器都有一个共同的功能,即它接收输入数据,将其通过模板引擎运行,然后输出 HTML 文件。我们通常将此过程称为构建。
需要太多的细微差别、上下文和可变性来比较各种 SSG 在构建过程中如何执行以显示在电子表格上——因此我们开始测试以针对流行的静态网站生成器对构建时间进行基准测试。
这不仅仅是为了确定哪个 SSG 最快。 Hugo 已经拥有了这样的声誉。我的意思是,他们在他们的网站上说——构建网站的全球最快框架——所以它一定是正确的!
这是对多个流行 SSG 的构建时间的深入比较,更重要的是,分析这些构建时间为何是这样的。盲目选择最快的或贬低最慢的都是错误的。让我们找出原因。
测试
测试过程旨在从简单开始——仅使用一些流行的 SSG 和简单的数据格式。一个可以扩展到更多 SSG 和更细致数据的基础。今天,测试包括六种流行的 SSG 选择
每次测试都使用了以下方法和条件
- 每个构建的数据源都是 Markdown 文件,具有随机生成的标题(作为前置 matter)和正文(包含三段内容)。
- 内容不包含图像。
- 测试在单台机器上按顺序运行,这使得实际值比它们之间相对比较不那么重要。
- 输出是在 HTML 页面上的纯文本,通过默认启动器运行,遵循每个 SSG 的各自入门指南。
- 每次测试都是冷运行。缓存被清除,Markdown 文件在每次测试中都会重新生成。
这些测试被认为是基准测试。它们使用基本的 Markdown 文件并将未设置样式的 HTML 输出到构建输出中。
换句话说,输出技术上是一个可以部署到生产环境的网站,尽管它并非真正是真实场景。相反,这提供了这些框架之间的基线比较。您作为使用其中一个框架的开发人员做出的选择将以各种方式调整构建时间(通常是使其变慢)。
例如,它不代表现实世界的一种方式是我们正在测试冷构建。在现实世界中,如果您有 10,000 个 Markdown 文件作为您的数据源并且正在使用 Gatsby,您将利用 Gatsby 的缓存,这将极大地减少构建时间(最多减少一半)。
增量构建也可以说相同,它与热运行与冷运行相关,因为它们只构建已更改的文件。我们没有在这些测试中测试增量方法(目前)。
静态网站生成器的两个层级
在我们这样做之前,让我们首先考虑一下实际上存在静态网站生成器的两个层级。让我们称它们为基本和高级。
- 基本生成器(在后台并不基本)本质上是一个命令行界面 (CLI),它接收数据并输出 HTML,并且通常可以扩展以处理资产(我们在这里不做)。
- 高级生成器除了输出静态站点之外,还提供其他功能,例如服务器端渲染、无服务器函数和框架集成。它们往往被配置为开箱即用地更具动态性。
我故意在这个测试中选择了每种类型的生成器中的三种。属于基本类别的是 Eleventy、Hugo 和 Jekyll。其他三个基于前端框架,并附带不同数量的工具。Gatsby 和 Next 基于 React 构建,而 Nuxt 基于 Vue 构建。
基本生成器 | 高级生成器 |
---|---|
Eleventy | Gatsby |
Hugo | Next |
Jekyll | Nuxt |
我的假设
让我们将科学方法应用于这种方法,因为科学很有趣(也很有用)!
我的假设是,如果一个 SSG 是高级的,那么它的性能将比基本 SSG 慢。我相信结果会反映这一点,因为高级 SSG 比基本 SSG 有更多的开销。因此,我们很可能看到两组生成器——基本和高级——捆绑在一起,结果是基本生成器移动得快得多。
让我详细阐述一下这个假设。
线性(ish)且快速
Hugo 和 Eleventy 在较小的数据集上运行速度很快。它们分别是在 Go 和 Node.js 中的(相对)简单的过程,它们的构建输出将反映这一点。虽然这两个 SSG 随着文件数量的增长而速度会变慢,但我预计它们将保持在该类别中的领先地位,尽管 Eleventy 在大规模情况下可能不太线性,仅仅因为 Go 往往比 Node 性能更好。
缓慢,然后快速,但仍然缓慢
高级或与框架绑定的 SSG 将开始并看起来很慢。我怀疑单文件测试包含显着差异——基本文件为毫秒,而 Gatsby、Next 和 Nuxt 为几秒钟。
基于框架的 SSG 都是使用 webpack 构建的,无论它们处理多少内容,都会带来大量的开销。这是我们在使用这些工具时要承担的负担(稍后详细介绍)。
但是,当我们添加数千个文件时,我怀疑我们会看到这两个类别之间的差距缩小,尽管高级 SSG 组将继续落后于某个显着数量。
在高级 SSG 组中,我预计 Gatsby 将是最快的,仅仅因为它没有服务器端组件需要担心——但这只是一个直觉。Next 和 Nuxt 可能已经对此进行了优化,以至于如果我们不使用该功能,它不会影响构建时间。而且我怀疑 Nuxt 会击败 Next,仅仅因为与 React 相比,Vue 的开销要少一些。
Jekyll:特立独行的孩子
Ruby 众所周知速度很慢。它随着时间的推移性能有所提高,但我预计它不会与 Node 扩展,当然也不会与 Go 扩展。然而,与此同时,它也没有框架的负担。
起初,我认为我们会看到 Jekyll 速度很快,甚至可能与 Eleventy 没有区别。但是当我们到达数千个文件时,性能将受到影响。我的直觉是,可能存在 Jekyll 成为所有六个中最慢的点。我们将提升到 100,000 的标记以确保。

结果出来了!
为这些测试提供支持的代码位于 GitHub 上。还有一个 显示相对结果的网站。
在多次迭代构建这些测试可以运行的基础后,我最终得到了一系列 10 次运行,分布在三个不同的数据集中
- 基础:单个文件,用于比较基础构建时间
- 小型站点:从 1 到 1024 个文件,每个文件加倍到时间(以便更容易确定 SSG 是否线性扩展)
- 大型站点:文件数量从 1,000 到 64,000,每次运行翻倍。我最初想增加到 128,000 个文件,但遇到了一些框架的瓶颈。64,000 个文件最终足以让我们了解到,当站点规模更大时,这些生成器将如何扩展。
点击或轻触图片以查看更大的尺寸。
结果总结
一些结果让我感到惊讶,而另一些则在意料之中。以下是重点:
- 正如预期的那样,Hugo 速度最快,无论站点大小如何。但令我意外的是,即使在基本构建中,它的速度也远超其他任何生成器。
- 从小型站点的结果来看,SSG 的基础组和高级组之间的区别非常明显。这是预料之中的,但令人惊讶的是,Next 和 Eleventy 在 64,000 个文件时表现接近。同样令人惊讶的是,Jekyll 在每次运行中都比 Eleventy 运行得更快。
- 我原本以为 Gatsby 会是高级框架中最快的,并且预计它会更接近基础框架。但Gatsby 却成为了最慢的,产生了最明显的曲线。
- 虽然假设中没有特别提到,但差异的规模比我想象的要大得多。在处理一个文件时,Hugo 的速度大约是 Gatsby 的 250 倍。但在处理 64,000 个文件时,速度差距缩小了——大约快了 40 倍。这意味着,虽然 Hugo 仍然是最快的(显著更快),但随着站点规模的增加,它的构建时间与其他生成器的差距正在缩小。
这一切意味着什么?
当我与这些 SSG 的创建者和维护者分享我的结果时,通常会收到同样的信息。概括来说:
构建时间较长的生成器之所以如此,是因为它们做了更多的事情。它们为开发者提供了更多可用的功能,而构建速度较快的站点(即“基础”工具)则主要专注于将模板转换为 HTML 文件。
我同意。
总结一下:扩展 Jamstack 站点很困难。
在扩展站点时,您(开发者)将会面临的挑战会因您尝试构建的站点而异。这些数据在这里没有被捕捉到,因为它们无法被捕捉——每个项目在某种程度上都是独一无二的。
归根结底是您愿意为了开发体验而等待多久。
例如,如果您要使用 Gatsby 构建一个大型的、图片密集型的站点,您将需要为构建时间付出代价,但同时您也会获得一个庞大的插件网络以及构建一个稳固、组织良好、基于组件的网站的基础。如果您使用 Jekyll 做同样的事情,那么在整个过程中保持组织性和效率将需要付出更多的努力,尽管您的构建速度可能会更快。
在工作中,我通常使用 Gatsby(或 Next,取决于所需的动态交互级别)构建站点。我们与 Gatsby 框架合作,构建了一个核心,以便能够快速构建高度定制的、图片丰富的网站,并包含丰富的组件。随着站点的扩展,我们的构建速度会变慢,但这时我们会发挥创意,通过实施微前端、卸载图像处理、实现内容预览以及许多其他优化来解决问题。
业余时间,我倾向于使用 Eleventy。通常只有我一个人编写代码,我的需求也简单得多。(我喜欢认为自己是一个对自己来说的好客户。)我觉得我对输出文件有更多的控制权,这使得我更容易在客户端性能方面获得 💯 的分数,这一点对我来说很重要。
归根结底,这不仅仅是关于速度快慢的问题。而是关于什么最适合您以及您愿意等待多久。
总结
这仅仅是个开始!这项工作的目标是创建一个基础,以便我们能够共同对流行的静态站点生成器的相对构建时间进行基准测试。
您有什么想法?您能在这个过程中发现什么漏洞?我们如何改进这些测试?如何使它们更接近真实场景?我们是否应该将处理过程卸载到专用机器上?
这些都是我希望您帮助我解答的问题。让我们来讨论一下。
这非常有用,谢谢!我认为如果图表有带标签的 y 轴,它会更有用。为什么不包含标签?
构建时间会根据运行它们的机器显著不同。在这篇文章中,我更希望关注相对比较,而不是纠结于实际值,尤其考虑到这些并不是真正的现实世界(即生产就绪)场景。
也就是说,我收到了很多关于实际值的请求,因此我已在当前的结果集中添加了工具提示,并包含了运行测试的机器规格。
我明白,Gridsome 的流行程度远不及 Gatsby,但看看它在图表中的位置会很有趣。
是的,Gridsome 非常棒,并且可以实现与 Gatsby 几乎相同的功能。
我听说过 Gridsome 的很多好话!不幸的是,我必须在初始集合中停止某个地方。这里的目标是为任何人提供低门槛的方式来添加新的 SSG。我最近做了一些更改,应该可以使此过程更容易。 以下是更新后的说明。
我很想看到 Zola(前称 Gutenberg):https://www.getzola.org/
我认为用 Rust 构建的它会是一个很好的竞争对手。
您是否有兴趣将测试用例放在一起?(以下是说明。)
试试Zola。您会对其优雅的设计和速度感到惊讶。
将此映射到 CI/CD 的每月成本会很有趣。Hugo 可以节省时间和金钱,加入一些 Alpine 和/或 Svelte,所有动态组件都可以轻松到位。
这是一个非常有趣的想法,可能是一篇有趣的后续文章。(将其添加到我的列表中!)
我不得不说,一直在努力寻找一种能够以低成本持续运行这些测试的流程,但这确实很困难。我仍然没有找到一个很好的解决方案。
除了标记 y 轴之外,y 轴也应该以对数方式显示,因为 x 轴是对数的。
对数说明非常有帮助。谢谢!我知道曲线的形状有些不对劲,但我无法确定是什么问题。
我已经在代码中进行了调整,并且结果产生了不同的图像。我已经更新了此处的快照,并相应地调整了一些结论。
我故意省略了 Y 轴上的标签,因为它们对于运行测试的机器来说太具体了。但是我已经添加了工具提示回到交互式图表中,以及机器规格。
为什么实际构建时间没有显示?构建时间轴上没有毫秒。
我真的不确定这种简化的构建有多大帮助。我仍然坚持使用 Hugo,主要是因为我受够了维护数千个 node.js 包的更新(或者不更新,当更新破坏构建时)。
感谢您进行这些测试!我想知道您是否可以将 Svelte 的 Sapper 与其他工具进行比较?
虽然我很乐意看到列表中的所有 SSG,但我不得不停在某个地方。但是,我已经将此项目开源,以便任何人都可以添加新的 SSG 并将其与其他 SSG 进行比较。我已经更新了 README 中关于添加新测试场景的说明,使其过程更容易一些。
https://github.com/seancdavis/ssg-build-performance-tests/blob/main/src/results.json 基于此,我认为图表上的时间单位是秒,而 Gatsby 构建 64k 个文件花费了 100 多秒。
感谢你的文章,Sean。正如你提到的,高级 SSG 构建时间较长的一個原因是,它们首先生成一个应用程序,然后该应用程序才会渲染页面。
Nuxt.js 最近发布了“更快的重新部署”,它缓存了应用程序,并且只有在底层应用程序代码发生更改时才会重新构建有效负载(页面)(https://nuxtjs.org.cn/blog/going-full-static#smarter-nuxt-generate)。有了这样的功能,我很好奇在后续受益于“预热”(缓存)应用程序的生成中,这些基准测试将如何变化。
从一开始我就考虑过冷构建与热构建的想法,但选择将此处的第一次尝试保持为一个非常简单的基线比较。我计划很快在这里引入热构建的概念,允许 SSG 利用其缓存机制。我非常好奇这将如何影响结果。
有趣的想法。我喜欢它不显示绝对构建时间:这些时间在不同机器之间差异太大,没有用,但不同站点大小和不同 SSG 之间的相对比较非常棒且新颖。
我希望能够利用测试基础设施来为我自己的 SSG 建立基准测试(https://soupault.neocities.org),但它“有点”棘手,因为它不使用前置 matter(它从 HTML 本身提取元数据,类似于微格式)。
这让我想到我需要添加一种方法,让用户可以自动从确实使用前置 matter 的 SSG 迁移。
酷,Dan!如果你能让它与 Markdown 协同工作,欢迎你 将你的解决方案添加到组合中。
我同意。越来越多的 SSG(以某种方式)支持 Markdown 以及前置 matter。如果你不打算支持它,你可能需要某种导入器或转换器,以便编辑器能够按照他们已经习惯的方式工作。
您能否告诉我们您的 VPC 的 vCPU + 内存以及构建的内存 + CPU 利用率?
我 在结果站点上添加了一个页面,显示了运行测试的机器规格。我还重新在专用环境中运行了所有内容,尽管我正在寻求进一步简化,因此这可能会继续发生变化。
我很高兴我今年早些时候从 Jekyll 切换到 Hugo。我受不了缓慢的构建时间,我无法想象使用比这更慢的东西。Hugo 的缺点是文档很乱。
这是一个棘手的图表。构建时间之所以如此不同,是因为它们使用的底层结构和要求不同。例如,Gatsby 与 GraphQL 兼容,但 Hugo 不兼容;Hugo是用 Go 编写的,而其他的是用 JS 编写的。要比较的东西太多了,仅仅比较构建速度并不能解释问题。
您在 Eleventy v0.11.1 中是否使用了
--incremental
标志?它似乎快多了。敬请期待 Eleventy v1.0.0……我正翘首以待 Eleventy v1.0!我正在将其用于一些个人网站(包括 此项目的成果网站)。我很乐意在测试中提升版本并在新版本发布后重新运行。
我也在探索将热构建(即增量构建)包含到这里的组合中。目前还没有更新。
所有这些中最有趣的部分是,它实际上并不重要。
构建静态站点将在本地或通过 CI 进行,然后静态文件将部署到您的主机,因此构建时间不会影响任何事情。
您可以争辩说它确实在开发过程中起作用,但所有 SSG 在开发过程中都有实时更新,并且它只构建您更改的文件,因此可以忽略该实时构建时间。
选择 SSG 不是为了速度,而是为了您擅长的语言、喜欢为其代码或构建插件做出贡献,以及它的工作流程和框架。
是的,我唯一学到的是,仅仅基于 Node 与 Ruby 的速度比较,Gatsby 肯定有一个糟糕的代码库,因为它比 Jekyll 慢。
我不同意您在这里提出的大多数观点。
构建时间绝对是重要的因素。它是在推送代码和在生产环境中看到它之间的时间量。使用 Jamstack 站点预览未发布的内容仍然是一个很大的挑战。内容编辑器不想等待半小时才能查看其内容在生产环境中的外观。
当然,“实时更新”是 SSG 开发环境中的一个共同主题。但增量构建绝对不是静态网站生成器的通用属性。这是一个难以解决的问题,并非所有 SSG 都已解决它。以 Eleventy 为例。它在每次更新时都会重新构建整个项目。
我想在这些测试中包含增量构建,但我选择不这样做,因为它们在各个 SSG 中并不相同。我可能会在将来将此添加到项目中,并且随着环境的成熟。
在考虑投资哪些 SSG 时,需要考虑许多因素。您可以自行构建确定其价值的属性列表。如果您认为这是您的列表,那也很好。但我鼓励您将构建性能作为这些考虑因素之一。
首先,很抱歉这是您从本文中唯一学到的东西。我的目标是在研究数据后进行更细致的讨论。
话虽如此,Gatsby 的代码库并不糟糕。在分析这些数据时,我没有得出那个结论。Gatsby 非常复杂。它具有许多可能对开发团队很有吸引力的优势,尽管其构建性能不佳。我发现它如此受欢迎的事实证明,该产品(及其代码库)实际上非常出色——开发人员喜欢使用它,尽管它在大规模构建时存在问题。
在某些情况下,构建时间非常重要。例如,在我的情况下,就像许多其他进入 JAMstack 世界的开发者一样。
我们使用免费的 Netlify 计划,该计划每月仅提供 300 分钟的构建过程。在 Netlify 上使用 Gatsby,每个构建需要 5 到 15 分钟,用于小型测试网站。这限制每天最多构建一次。
相反,在 Netlify 上使用 Hugo,您可以每分钟构建 3 或 4 次。
您好,
感谢您的工作!
但我自己在问,谁会为拥有数千个页面的网站使用 SSG?!
一个真实案例的示例
https://www.smashingmagazine.com/2020/01/migration-from-wordpress-to-jamstack/
https://blog.cloudflare.com/new-dev-docs/
comparing-static-site-generator-build-times 这是一个很棒的想法,感谢您分享,我想了解或想知道如何将一个或多个静态站点(如 Docusaurus)添加到 ssg 文件夹以进行比较和生成报告的步骤?
任何关于这方面的线索都将对我们有很大帮助。
提前感谢。
很高兴您想将其他 SSG 添加到项目中!为此,请按照此处概述的过程进行操作。如果您在某些时候遇到困难,请创建一个问题,说明您遇到困难的地方并分享您的代码。
我进行了Saaze与Hugo与Zola的测试
https://eklausmeier.goip.de/blog/2021/11-13-performance-comparison-saaze-vs-hugo-vs-zola
这表明Zola的表现优于Hugo。
现在已过时…
Blades声称使用Rust代码提高了10倍。
https://github.com/grego/blades