靜態網站在重新發佈時保持上線
以往在 Mythex 重新發佈靜態網站時,會先刪除線上的檔案,再上傳新的建構版本,因此在上傳期間,部分訪客會看到 404 頁面,或是缺少腳本的頁面。上傳失敗的話,網站可能會變成空白,或只有一半是新內容。現在新的建構會覆寫舊的版本,頁面最後上傳,多餘的檔案則會在幾分鐘後移除。第二項修正令重新發佈能在數秒內生效,而不是一分鐘;至於像標誌這類檔案,以往可能要等上一整天。
靜態網站如何提供服務
靜態網站就是純粹的檔案:HTML 頁面、JavaScript、CSS 和圖片。你在 Mythex 發佈時,我們會建構它,把輸出上傳到物件儲存空間中屬於你網站的資料夾,並透過邊緣網絡提供服務——邊緣伺服器位於接近訪客的位置,會從儲存空間取得檔案,並把副本保留一段時間。(如果你對此還不熟悉,我們的指南什麼是 CDN介紹了這個概念。)
有兩件事出了問題:重新發佈時更改檔案的順序,以及舊副本保留的時間。
問題一:上傳時先清空了網站
重新發佈會先刪除網站資料夾中的所有內容,再上傳新的建構版本。在上傳的整段時間裡——在我們本地測試中,一個 250 個檔案的網站需時 12 秒——如果訪客的請求未在邊緣快取中,就會得到 404,或是一個腳本回傳 404 的 HTML 頁面。
上傳失敗的情況更糟。資料夾已經是空的,而且在其中一條上傳路徑上,新的 index.html 可能會先於那個失敗的檔案落地。被標示為失敗的發佈,可能會令一個只有一半是新內容的網站繼續在線上。
修復方法:覆寫、頁面最後、事後清理
- 不要先刪除。 新的建構會覆寫在舊的版本之上。
- 資源先於頁面。 頁面會指明它需要哪些腳本和樣式,因此頁面最後上傳。在新頁面到達之前,訪客拿到的是舊頁面,而它指向的舊資源仍然存在。新頁面到達後,它所指向的新資源早已就位。
- 稍後移除多餘檔案。 上傳之前,我們會列出網站由哪些檔案組成。在成功上傳三分鐘後,清單中新建構沒有重寫的任何檔案都會被刪除。三分鐘比頁面在邊緣和瀏覽器中可能被快取的 60 秒更長,因此仍持有舊頁面的訪客,能找到該頁面指向的資源。
- 拿不準就什麼都不刪。 如果上傳前的列出步驟失敗,就不會進行任何清理。多餘的檔案無害,下一次發佈會清除它們。在不知道裡面有什麼的情況下刪除,正是網站變成空白的原因。
現在,上傳失敗會讓上一個網站保持原狀。
我們在本地端到端測試了這項改動,使用的是真正的上傳腳本、真正的上傳路由和儲存空間提供服務,並以冷邊緣快取的方式模擬訪客。舊程式碼下,重新發佈期間有 91 次中的 55 次造訪出錯,失敗的發佈則有 92 次中的 61 次出錯。新程式碼下,橫跨兩條上傳路徑、一次失敗的上傳以及之後的發佈,大約 3,500 次造訪中零次出錯,而且被清理的恰好是多餘的檔案。
問題二:重新發佈需時太久才顯示
即使上傳順利,變更出現得也很慢。邊緣會把頁面副本保留 60 秒、其他所有檔案保留一天,並告知瀏覽器也這樣做。像 logo.png、字型,或任何來自 public/ 資料夾的檔案,這些固定名稱的檔案在重新發佈後,可能會顯示舊版本長達一天。
修復方法:把檔案副本歸於建構版本之下
當邊緣向我們的 API 查詢網站的位置時,回應現在會包含一個建構標記,每次發佈生效時都會改變。邊緣會把副本歸入該標記之下。因此,一旦邊緣那 30 秒的查詢到期,發佈就會變成一組全新的快取鍵。舊副本永遠不會再被找到,所以邊緣可以保留副本一天,卻永遠不會在被取代的發佈之後仍提供它們。
瀏覽器則採用兩種不同的規則:
- 雜湊過的建構輸出——例如
assets/index-CzLcxDO8.js這類檔案名稱會隨內容改變的檔案——會被快取一年,並標示為 immutable。在該名稱之下,它永遠不會過時。 - 其他一切——頁面和像標誌這類固定名稱的檔案——都標示為
no-cache,即「使用前先檢查」。如果沒有改變,現在我們已遵守瀏覽器的If-None-Match檢查,回應就只是一個很小、沒有內容的304 Not Modified。
區分這兩者需要小心:從 public/assets/ 複製的檔案會保留自己的名稱,如果把 assets/logo.png 快取一年,就會讓舊標誌被釘住一年。因此,只有在建構輸出資料夾中,並且名稱中含有看起來像雜湊的片段(而不是普通字詞)的檔案,才會被視為雜湊檔案。
在本地,新的頁面和標誌在發佈上線後 6 秒內便可見。以前頁面需要 60 秒,標誌則需要一天。
兩項較小的修正
- HEAD 請求導致的空白頁面。
HEAD請求只要求頁面的標頭而不要內容。我們以前會快取這些空回應,因此下一位訪客打開該頁面時會看到空白。現在HEAD回應不再被快取。 - 「這裡沒有任何東西」的真正頁面。 指向沒有應用程式的位址,以前會得到一段純文字「此已發佈的應用程式已離線或找不到連結」,並附帶 502 錯誤代碼。現在它會得到一個正式頁面「這裡沒有應用程式」,附帶 404 狀態,並提供讓擁有者返回 Mythex 的途徑。無法識別的自訂網域也會得到同一頁面。
我們的心得
- 順序本身就是正確性的一部分。 以不同順序上傳同樣的檔案,就是損壞的網站與正常運作的網站之間的分別。
- 延後刪除,而且只刪除你知道的內容。 以上傳前取得的清單進行清理是安全的;清空資料夾然後寄望上傳能順利完成則不然。
- 依版本快取,而不是依時間快取。 到期時間是對內容何時改變的猜測。隨建構改變的鍵則是事實。
相關閱讀:你的已發佈應用程式現在在重新發佈期間仍保持上線。更多發佈相關資訊,請參閱文件。