用部署后刷新子頁面 404:從路由回退到靜態(tài)目錄索引的排查方法)
很多前端項目在本地開發(fā)時訪問 /about、/faq、/article/xxx 這類地址完全正常但部署到服務(wù)器或?qū)ο蟠鎯笥脩糁苯哟蜷_子路徑、刷新頁面或者將鏈接發(fā)給別人訪問時卻可能得到 404 頁面或者意外回到首頁。這不是前端路由本身失效而是瀏覽器、靜態(tài)服務(wù)器和前端路由對“路徑”的理解不同。本文從請求流程開始說明如何判斷問題屬于哪一層并給出一套可復(fù)用的排查與驗收方法。一、先理解一次子路徑訪問發(fā)生了什么以訪問 /docs/install 為例。在前端開發(fā)服務(wù)器中開發(fā)工具通常會自動把未知路徑回退到入口 HTML隨后由瀏覽器加載腳本再由前端路由識別 /docs/install 并渲染對應(yīng)組件。因此開發(fā)階段很少遇到問題。部署后請求會先到達(dá) CDN、對象存儲或 Web 服務(wù)器。服務(wù)端并不理解 React、Vue 或其他前端路由它只會嘗試尋找實際文件例如/docs/install/docs/install.html/docs/install/index.html如果這些文件都不存在服務(wù)器可能直接返回 404也可能根據(jù)錯誤頁配置返回根目錄的 index.html。因此同一個地址在瀏覽器地址欄里看起來相同實際可能對應(yīng)兩種完全不同的處理方式第一種是靜態(tài)目錄模式。服務(wù)器找到 /docs/install/index.html 并直接返回該文件。第二種是單頁應(yīng)用回退模式。服務(wù)器找不到對應(yīng)文件后統(tǒng)一返回根目錄 index.html瀏覽器再運行 JavaScript 完成路由渲染。兩種方式都可以正常展示頁面但部署要求、首屏內(nèi)容和故障表現(xiàn)并不完全相同。二、最常見的三種故障表現(xiàn)第一種直接訪問子路徑得到 404這是最容易識別的情況。通常說明服務(wù)器沒有把未知路徑回退到入口文件也不存在對應(yīng)目錄或靜態(tài) HTML 文件。例如用戶打開/docs/install服務(wù)器嘗試讀取/docs/install但找不到文件于是直接返回 404。此時需要檢查托管平臺是否支持單頁應(yīng)用歷史路由回退或確認(rèn)構(gòu)建產(chǎn)物里是否應(yīng)該存在 docs/install/index.html。第二種刷新頁面回到首頁這類問題往往更隱蔽。頁面首次通過站內(nèi)點擊進(jìn)入時正常但按刷新后會回到首頁。常見原因是服務(wù)器雖然返回了 index.html但入口 HTML 中默認(rèn)的頁面信息、初始數(shù)據(jù)或腳本邏輯沒有正確識別當(dāng)前路徑。前端代碼可能在客戶端初始化后又主動跳轉(zhuǎn)到了根路徑。排查時不要只看最終視覺結(jié)果而應(yīng)確認(rèn)地址欄是否被改寫、瀏覽器控制臺是否有路由報錯以及初始 HTML 是否與預(yù)期路徑匹配。第三種頁面能打開但標(biāo)題和頁面信息不對這種情況常見于所有路徑都回退到了同一個入口 HTML。頁面渲染完成后瀏覽器標(biāo)簽標(biāo)題可能會通過 JavaScript 更新但首次返回的 HTML 仍然是首頁模板。如果項目使用靜態(tài)預(yù)渲染每個路徑應(yīng)優(yōu)先命中各自目錄下的 index.html例如/about 對應(yīng) /about/index.html/docs/install 對應(yīng) /docs/install/index.html/article/demo 對應(yīng) /article/demo/index.html如果所有路徑始終返回根目錄 index.html那么就需要檢查 CDN 回源規(guī)則、重寫規(guī)則和緩存鍵配置。三、先確認(rèn)構(gòu)建產(chǎn)物是否真的存在排查部署前先查看構(gòu)建目錄而不是先修改服務(wù)器規(guī)則。一個采用靜態(tài)預(yù)渲染的項目構(gòu)建完成后通常會出現(xiàn)類似結(jié)構(gòu)dist/index.htmlabout/index.htmldocs/install/index.htmlarticle/demo/index.html如果構(gòu)建目錄中根本不存在子路徑對應(yīng)的 index.html那么服務(wù)器無論如何配置也無法直接返回該頁面的靜態(tài)內(nèi)容??梢灾痦棿_認(rèn)第一構(gòu)建命令是否真正執(zhí)行成功。第二預(yù)渲染腳本是否包含目標(biāo)路由。第三輸出路徑是否與線上訪問路徑一致。第四部署時是否把整個 dist 目錄完整上傳而不是只上傳了根目錄的 index.html 和靜態(tài)資源目錄。第五托管平臺是否在發(fā)布過程中忽略了嵌套目錄中的 HTML 文件。這一階段的原則很簡單先確認(rèn)文件存在再討論路由規(guī)則。四、兩種部署策略不要混用實際項目中常見的部署策略有兩種。策略一所有未知路徑回退到入口文件這種方式適用于純客戶端渲染的單頁應(yīng)用。服務(wù)器規(guī)則的含義是如果請求的文件不存在就返回根目錄 index.html。其優(yōu)點是配置簡單新增路由后通常不需要調(diào)整服務(wù)器規(guī)則。缺點是服務(wù)端首次響應(yīng)的是統(tǒng)一入口文件路徑頁面所需內(nèi)容要等腳本加載后才能顯示同時若項目存在預(yù)渲染頁面又把所有路徑強制回退到根入口就可能導(dǎo)致預(yù)渲染文件永遠(yuǎn)不會被使用。策略二優(yōu)先返回目錄下的靜態(tài) HTML找不到時再回退入口這種方式適用于已經(jīng)生成多個頁面靜態(tài)文件的項目。規(guī)則邏輯應(yīng)當(dāng)是先查找請求路徑對應(yīng)文件。再查找請求路徑對應(yīng)目錄中的 index.html。只有都不存在時才回退根目錄 index.html。這個順序很重要。若把回退入口放在前面所有請求都會提前命中根入口子路徑中的靜態(tài) HTML 即使已經(jīng)發(fā)布也不會被返回。因此部署前必須明確項目屬于哪一種模式。不要一邊生成大量預(yù)渲染頁面一邊用“所有路徑統(tǒng)一回退首頁”的規(guī)則覆蓋它們。五、如何驗證服務(wù)器實際返回了什么不要只在瀏覽器中看頁面能不能打開。瀏覽器會執(zhí)行 JavaScript最終畫面可能掩蓋首次響應(yīng)的問題。應(yīng)至少檢查以下內(nèi)容請求狀態(tài)碼首頁、核心子頁面和一篇詳情頁均應(yīng)返回 200。響應(yīng)體大小如果不同頁面返回的 HTML 大小幾乎完全一致且都很小可能說明它們返回的是同一個入口模板。首次 HTML 中是否包含頁面標(biāo)題直接查看頁面源代碼確認(rèn) title 是否屬于當(dāng)前頁面。首次 HTML 中是否包含當(dāng)前頁面的主標(biāo)題若頁面是靜態(tài)輸出應(yīng)能在源代碼中找到對應(yīng)頁面的 H1 或正文片段。頁面規(guī)范地址是否與當(dāng)前路徑一致例如訪問 /docs/install 時頁面中的規(guī)范地址應(yīng)是當(dāng)前路徑而不是根路徑。不同路徑是否返回不同的 HTML 內(nèi)容至少對首頁、列表頁、詳情頁分別檢查一次。只檢查首頁無法證明子路徑部署正常。六、緩存會讓排查結(jié)果產(chǎn)生誤判即使源站文件已經(jīng)更新CDN 仍可能緩存舊 HTML。典型現(xiàn)象包括本地構(gòu)建結(jié)果正確線上仍顯示舊標(biāo)題。部分地區(qū)訪問正常部分地區(qū)仍是舊頁面。首頁更新了子頁面沒有更新。普通瀏覽器與無痕窗口返回不同內(nèi)容。此時應(yīng)區(qū)分靜態(tài)資源緩存和 HTML 緩存。JavaScript、CSS、圖片通??梢蚤L期緩存HTML 文件更新頻率更高應(yīng)在發(fā)布后重點刷新頁面路徑的緩存。如果 CDN 使用“忽略查詢參數(shù)”的緩存策略也不應(yīng)只依賴在網(wǎng)址后面添加隨機(jī)參數(shù)來判斷是否刷新成功。更可靠的做法是確認(rèn) CDN 控制臺中的刷新任務(wù)完成并重新請求具體 HTML 路徑。七、一個實用的發(fā)布驗收清單每次部署完成后可以按以下順序檢查第一步確認(rèn)構(gòu)建目錄中存在首頁和關(guān)鍵子路徑的 index.html。第二步確認(rèn)發(fā)布目錄配置指向構(gòu)建產(chǎn)物目錄而不是源碼目錄。第三步分別直接訪問首頁、列表頁和詳情頁。第四步在子頁面按瀏覽器刷新確認(rèn)沒有 404 或錯誤跳轉(zhuǎn)。第五步查看頁面源代碼確認(rèn)當(dāng)前頁面標(biāo)題和主體內(nèi)容已存在。第六步確認(rèn)子頁面的規(guī)范地址沒有錯誤指向首頁。第七步刷新 CDN 中首頁、列表頁、詳情頁對應(yīng)的 HTML 緩存。第八步使用無痕窗口或另一臺設(shè)備再次訪問避免本地緩存干擾判斷。八、結(jié)語單頁應(yīng)用部署問題的關(guān)鍵不在于“頁面最終有沒有顯示出來”而在于“請求到達(dá)服務(wù)器時服務(wù)器究竟返回了哪個文件”。如果項目只依賴客戶端路由就需要保證未知路徑能穩(wěn)定回退到入口 HTML如果項目已經(jīng)生成頁面級靜態(tài)文件就需要保證服務(wù)器優(yōu)先返回對應(yīng)目錄中的 index.html。先厘清構(gòu)建產(chǎn)物再檢查靜態(tài)路由規(guī)則最后處理緩存通常能更快定位刷新 404、跳轉(zhuǎn)首頁和頁面信息錯亂這幾類問題。