部落格

靜態網站重新發佈時仍維持上線

過去在 Mythex 重新發佈靜態網站時,會先刪除線上的檔案,再上傳新的建置版本,因此在上傳期間,部分訪客會看到 404 頁面,或是缺少腳本的頁面。上傳失敗時,網站甚至可能被清空,或只剩下一半是新的內容。現在,新的建置會直接覆蓋舊的,頁面最後才上傳,殘留的檔案則在幾分鐘後移除。第二項修正讓重新發佈的變更能在幾秒內生效,而不是一分鐘——對於像標誌這類的檔案,過去可能要等上一整天。

靜態網站如何提供服務

靜態網站就是純檔案: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。在該名稱下,它永遠不會過期。
  • 其他所有內容——頁面以及固定名稱的檔案,例如標誌——標記為 no-cache,意思是「使用前先確認」。如果沒有變更,回應就是一個很小的 304 Not Modified,不帶內容,因為我們現在會尊重瀏覽器的 If-None-Match 檢查。

區分這兩種檔案需要小心:從 public/assets/ 複製的檔案會保留它自己的名稱,如果把 assets/logo.png 快取一年,就會把舊標誌固定一年。因此,只有當檔案位於建置輸出資料夾 且 其名稱中有一段看起來像雜湊、而非一般單字的片段時,才會被視為雜湊檔案。

在本機測試中,新的頁面與標誌在發佈生效後 6 秒 就能看到。以前頁面需要 60 秒,標誌則需要一天。

另外兩個較小的修正

  • HEAD 請求造成空白頁面。 HEAD 請求只要求頁面的標頭,不要求內容。我們之前會快取這些空回應,導致下一位訪客看到空白頁面。現在不再快取 HEAD 回應。
  • 「沒有內容」的真正頁面。 指向沒有 App 的位址,以前會回傳純文字的「This published app is offline or the link was not found」,並帶有 502 錯誤碼。現在它會顯示正式的頁面「這裡沒有 App」,狀態碼為 404,並附上回到 Mythex 的連結給擁有者。未知的自訂網域也會顯示同樣的頁面。

我們從中學到什麼

  • 順序也是正確性的一部分。 以不同順序上傳相同的檔案,就是網站壞掉與正常運作之間的差別。
  • 延後刪除,而且只刪除你知道的內容。 使用上傳前的清單進行清理是安全的;清空資料夾然後寄望上傳能順利完成則不安全。
  • 依版本快取,而不是依時間快取。 過期時間是對內容何時改變的猜測。隨建置改變的鍵則是事實。

相關文章:你的已發佈 App 在重新發佈時仍維持上線。更多發佈相關內容請見文件。

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 简体中文 繁體中文(香港)