博客

静态网站在重新发布时保持在线

以前在 Mythex 上重新发布静态网站时,会先删除线上的文件,然后再上传新构建,因此在上传期间,一些访客会看到 404 页面,或是缺少脚本的页面。上传失败时,网站可能被清空,或者只更新了一半。现在,新构建会覆盖旧构建,页面最后写入,多余的文件会在几分钟后删除。第二项修复让重新发布的更改能在几秒内生效,而不是一分钟——对于 logo 这类文件,则是最多一天。

静态网站如何提供服务

静态网站是纯文件构成的网站:HTML 页面、JavaScript、CSS、图片。在 Mythex 上发布时,我们会构建它,把输出上传到对象存储中你网站专属的文件夹,然后通过边缘网络提供服务——边缘服务器靠近访客,从存储中获取文件,并在一段时间内保存它们的副本。(如果你对此还不熟悉,我们关于什么是 CDN的指南涵盖了这个概念。)

当时有两个问题:重新发布时文件变更的顺序,以及旧副本被保留的时间。

问题一:上传前先清空了网站

重新发布会先删除网站文件夹中的所有内容,然后再上传新构建。在上传所用的时间里——在我们的本地测试中,一个 250 个文件的网站需要 12 秒——如果访客的请求尚未在边缘缓存中,就会得到 404,或者得到一个脚本返回 404 的 HTML 页面。

上传失败的情况更糟。文件夹已经被清空,而且在两条上传路径之一中,新的 index.html 可能先于失败的那个文件落地。一次被报告为失败的发布,可能会让一个半新半旧的网站继续在线。

修复方案:覆盖写入,页面最后写,之后再清理

  1. 不要先删除。 新构建直接上传到旧构建之上。
  2. 资源先于页面。 页面会声明它需要的脚本和样式,因此页面最后上传。在新页面落地之前,访客拿到的是旧页面,而旧页面引用的是旧资源,这些资源仍然存在。新页面落地后,它们引用的新资源早已就位。
  3. 稍后删除残留文件。 上传前,我们会列出网站包含的文件。成功上传三分钟后,列表中新构建没有覆盖的文件会被删除。三分钟比页面在边缘和浏览器中可以缓存的 60 秒更长,因此仍持有旧页面的访客,也能找到它引用的资源。
  4. 不确定时,什么都不删。 如果上传前的文件列表获取失败,就不做任何清理。残留文件无害,下一次发布会清除它们。在不知道原先有什么的情况下删除,正是网站变空的原因。

现在,一次失败的上传会让之前的网站保持原样。

我们在本地进行了端到端测试,使用了真实的上传脚本、真实的上传路由和存储服务,并模拟了边缘缓存为冷的访客。使用旧代码时,重新发布期间有 91 次访问中的 55 次出现故障,失败的发布期间则为 92 次中的 61 次。使用新代码后,在约 3,500 次访问中,0 次出现故障,覆盖了两条上传路径、一次失败上传,以及之后的发布;而且恰好只清理了残留文件。

问题二:重新发布生效太慢

即使上传顺利完成,更改也要过很久才会显示。边缘会把页面缓存 60 秒,其他所有文件缓存一天,并告诉浏览器也这样做。使用固定文件名的文件——logo.png、字体,以及 public/ 文件夹中的任何内容——在重新发布后可能会显示旧版本,最长达一天。

修复方案:在构建下生成文件副本

当边缘向我们的 API 询问某个网站位于何处时,回答现在会包含一个构建标记,每次发布成功时都会变化。边缘会按该标记存放副本。因此,一旦边缘 30 秒的查询缓存过期,一次发布就会变成一整套全新的缓存键。旧副本再也不会被找到,所以边缘可以保留副本一整天,而永远不会提供超过取代它的那次发布的内容。

浏览器则适用两种不同的规则:

  • 带哈希的构建产物——例如 assets/index-CzLcxDO8.js 这样的文件,其名称会随内容变化——缓存一年,并标记为 immutable。在该名称下,它永远不会过期。
  • 其他所有内容——页面以及 logo 这类固定名称的文件——标记为 no-cache,意思是「使用前先检查」。如果没有变化,现在我们已经支持浏览器的 If-None-Match 检查,回应只是一个很小的 304 Not Modified,没有正文。

区分这两者需要小心:从 public/assets/ 复制的文件会保留它自己的名称,如果把 assets/logo.png 缓存一年,就会把旧 logo 固定一年。因此,只有当文件位于构建输出文件夹中**,并且**其名称中有一段看起来像哈希的部分(而不是普通单词)时,才算作带哈希的文件。

在本地,新页面和新 logo 在发布上线后 6 秒即可看到。之前,页面需要 60 秒,logo 则需要一天。

另外两个较小的修复

  • HEAD 请求导致的空白页面。 HEAD 请求只获取页面的响应头而不获取正文。我们之前会缓存这些空响应,因此下一位访问该页面的访客会看到空白页。现在不再缓存 HEAD 响应。
  • 「没有内容」时的真实页面。 访问一个没有对应应用的地址,过去会返回一段纯文本「此已发布应用处于离线状态或未找到链接」,并带有 502 错误码。现在它会显示一个正式页面「这里没有应用」,状态码为 404,并附带返回 Mythex 的链接,方便网站所有者。未知的自定义域名也会显示同样的页面。

我们的收获

  • 顺序本身就是正确性的一部分。 以不同顺序上传相同的文件,就是网站损坏与正常运行之间的区别。
  • 延后删除,并且只删除你知道的内容。 使用上传前获取的列表进行清理是安全的;清空文件夹并寄希望于上传能够完成,则不安全。
  • 按版本缓存,而不是按时间缓存。 过期时间只是对内容何时变化的猜测。随构建变化的键才是一个事实。

相关阅读:你的已发布应用在重新发布时仍保持在线。更多关于发布的内容,请参阅文档。

Mythex · Pricing · 用 AI 构建任何东西 · 网站和应用模板 · Mythex 对比 · AI 应用构建术语表 · 免费的 AI 应用构建工具 · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 繁體中文(香港) 繁體中文(台灣)