Laravel 與後端開發

分頁藏起來就別再敲門了:Inertia.js 3.9 讓輪詢懂得休息,還補上「登出後按上一頁」的漏洞

Laravel News 於 2026/10/13 報導 Inertia.js v3.9.0:usePoll() 與 router.poll() 新增 background 選項(throttle/pause/continue),分頁隱藏時可完全停止輪詢,keepAlive 改為不建議使用;navigate 事件加入 type(initial/visit/history),方便在使用者按上一頁時重新載入過期資料;呼叫 clearHistory 時會一併清空預取快取,修正登出後按上一頁仍顯示受保護頁面的問題;另有多項上一頁與 InfiniteScroll 修正。GitHub 上同日釋出的 v3.9.1 讓 XSRF 標頭只送往同源網址、每筆加密歷史改用獨立 IV,2.x 也已回補。本文整理升級重點與實務建議。

扁平插畫:一排瀏覽器分頁中有一個顯示月亮正在休息,下方儀表板視窗中央有暫停按鈕,旁邊是瞇眼微笑的伺服器、帶鎖頭的盾牌與返回箭頭按鈕,淡紫色調,無文字。
分頁藏起來就別再敲門了:Inertia.js 3.9 讓輪詢懂得休息,還補上「登出後按上一頁」的漏洞

Inertia.js v3.9 為 usePoll 與 router.poll 加入 background 選項,分頁在背景時可以完全暫停輪詢;navigate 事件新增 type 可分辨「從歷史紀錄回來」;清除歷史時一併清空預取快取,修掉登出後按上一頁還看得到受保護頁面的問題。同日的 3.9.1 再補兩個安全強化。給 Laravel+React/Vue 團隊的升級筆記。

每家公司都有一位同事,瀏覽器開著 47 個分頁,其中 12 個是公司後台。那些後台頁面每 5 秒就問伺服器一次:「有新訂單嗎?」「有新訊息嗎?」「現在呢?」即使他已經下班、筆電闔上前根本沒切回來看過。

伺服器很有禮貌地每次都回答,然後月底的主機帳單也很有禮貌地變長。

10 月 13 日,Laravel News 的 Paul Redmond 介紹了 Inertia.js v3.9.0。這版的亮點很生活化:讓輪詢在分頁被藏起來時真正休息,同時修好幾個跟「上一頁」按鈕有關、但其實攸關資安的問題。

先複習:Inertia 是什麼?

如果你的團隊用 Laravel 寫後端、用 React 或 Vue 寫畫面,卻不想維護一整套 API,Inertia 就是那座橋:路由和資料仍由 Laravel 控制器處理,前端用元件渲染,換頁時只交換頁面資料,不用整頁重新載入。很多 Laravel 官方起手套件與企業後台都是這樣蓋的。

重點一:背景分頁的輪詢,終於可以按暫停

usePoll() 是 Inertia 內建的輪詢工具,適合儀表板、訂單列表、客服訊息這類需要定時更新的頁面。過去分頁在背景時,輪詢會降頻成每 10 個週期跑一次;除非你設 keepAlive,而且沒有辦法完全停下來。

v3.9 由 Pascal Baljet 加入新的 background 選項,三個值:

  • throttle(預設):維持舊行為,背景時每 10 個週期跑一次。
  • pause:分頁隱藏時完全停止,切回來才恢復。
  • continue:背景也照原本頻率跑,取代已不建議使用的 keepAlive。
import { usePoll } from '@inertiajs/react'

usePoll(5000, {}, { background: 'pause' })

pause 的細節很貼心:切回分頁時,如果藏起來的期間「本來該打一次」,就會立刻發一次請求;否則等目前週期剩下的時間再打。所以使用者快速切來切去,也不會每切一次就送一個請求。這版也修正了「在分頁已經隱藏時才啟動的輪詢」會以完整頻率執行的問題。

怎麼選? 我們的建議:

  • 訂單、庫存、報表儀表板:用 pause。沒人在看就不用更新,回來時馬上補一次。
  • 客服即時訊息、需要背景提醒的頁面:考慮 continue,或乾脆改用 WebSocket 廣播。
  • 不確定時:維持預設 throttle,至少比全速跑省。

文件也提醒,輪詢還有 mode 選項可以處理「上一個請求還沒回來」的情況:overlap(預設,並行)、cancel(取消進行中的請求)、rest(等上一個結束後才開始計時)。後端比較慢的報表頁,搭配 rest 可以避免請求疊羅漢。

算一筆帳:一位同事、十二個背景分頁

用開頭那位同事來試算(以下是示意,不是官方數據):12 個後台分頁、每 5 秒輪詢一次,一小時就是 12 × 720 = 8,640 個請求。預設的 throttle 會把背景請求降到十分之一,大約 864 個;改成 pause,他沒切回來看的那幾個小時就是 0。

如果公司有 30 位同事都這樣開著後台下班,差距就從「一點點」變成「一整台伺服器」。而每個請求背後,可能還有資料庫查詢、權限檢查和 log 寫入。對使用按用量計費主機或雲端方案的團隊來說,這是很實在的成本;對資料庫來說,則是少掉一堆深夜沒人看的查詢。

實務上,我們會建議先在 Laravel 這端觀察:用 Telescope、Pulse 或主機的請求紀錄,找出哪些路由被輪詢打得最兇,再決定哪些頁面最值得先改成 pause。

重點二:知道使用者是「按上一頁回來的」

從瀏覽器歷史紀錄還原的頁面,顯示的是使用者離開時的資料,可能早就過期。v3.9 在 navigate 事件加入 type:首次載入(含重新整理)是 initial、一般 Inertia 換頁是 visit、按上一頁或下一頁還原則是 history。

import { router } from '@inertiajs/react'

router.on('navigate', (event) => {
  if (event.detail.type === 'history') {
    router.reload({ only: ['messages'] })
  }
})

想像客服人員在訊息列表點進一筆對話,處理完按上一頁回到列表;過去列表顯示的是十分鐘前的狀態,現在可以只重新載入 messages 這個屬性,畫面維持原樣、資料變新。

重點三:登出後按上一頁,不該再看到機密頁面

這是本版最值得企業注意的修正。Inertia 有「歷史加密」功能:把頁面資料加密後存進瀏覽器歷史,登出時呼叫 Inertia::clearHistory() 或 router.clearHistory() 輪替金鑰,舊紀錄就讀不出來。

問題在於預取快取沒有一起清。使用者登出後按上一頁,Inertia 會從預取快取拿資料,於是受保護頁面又出現了,直到快取過期為止。v3.9 改成清除歷史時一併清空預取快取,清空當下還在路上的預取請求完成後也不會被存起來,router.flushAll() 同樣適用。這個 PR 被標記為「should be backported」,GitHub 上同日釋出的 2.x 版 v2.3.29 也已回補。

這個情境在台灣其實很常見:門市櫃台的共用電腦、診所掛號台、公司會議室的筆電。前一位同事登出後離開,下一位只要按幾下上一頁,就可能看到客戶名單或訂單明細。這類問題不會出現在功能驗收清單上,卻很容易出現在客訴與資安稽核報告裡。

同一天的 v3.9.1 再補兩項安全強化:XSRF token 標頭只會送往同源網址,以及每一筆加密歷史都使用獨立的 IV(初始化向量)。2.3.29 同樣包含後者。

其他修正:上一頁與無限捲動

  • Mohammed Sohail 修正:延遲屬性、輪詢或部分重新載入的回應剛好在使用者按上一頁時抵達,會蓋掉還原的頁面。現在歷史還原會取消尚未完成的頁面更新。
  • Gianpiero Puleo 修正 useRemember 會把前一頁的狀態帶進新的造訪,例如分頁籤切換後,已清除的選取又跑回來。
  • InfiniteScroll 在換頁後仍在跑的請求會被取消;過去用新排序或篩選換到同網址時,舊回應可能被合併進新列表。

升級與導入建議

  1. 確認版本:3.x 專案直接升到 3.9.1;還在 2.x 的專案至少升到 2.3.29,把登出相關修正拿到手。
  2. 盤點所有 usePoll:搜尋專案裡的 usePoll 和 router.poll,逐一決定 background 策略;把 keepAlive: true 換成 background: 'continue'。
  3. 打開歷史加密:後台、會員中心這類有個資的頁面,可在設定檔把 inertia.history.encrypt 設為 true,或對路由群組套用 EncryptHistory 中介層。注意它依賴 window.crypto.subtle,必須在 HTTPS 環境才能用。
  4. 登出流程加上 clearHistory:在登出回應呼叫 Inertia::clearHistory(),並實測「登出後按上一頁」。
  5. 把行為寫成測試:用瀏覽器測試涵蓋「切到背景再切回來」「登出後按上一頁」兩個情境,未來升級才不會悄悄退化。

你可能會問

Q:不升級會怎樣?
A:輪詢照舊能用,只是背景時無法完全停止;比較需要在意的是登出後的預取快取問題,有會員或後台的網站建議盡快升級。

Q:pause 會不會讓使用者錯過即時資訊?
A:切回分頁時,如果已經該更新,會立刻補打一次請求。真正需要「背景也通知」的情境,建議改用推播或廣播。

Q:後端 Laravel 需要跟著改嗎?
A:background 選項只在前端設定,Laravel 端不用改。不過登出時呼叫 Inertia::clearHistory()、開啟歷史加密,則是在 Laravel 這端設定。

Q:我們用 React 還是 Vue 有差嗎?
A:官方文件中 Vue、React、Svelte 的 usePoll 寫法一致,只是 import 來源不同。

結語

Inertia 3.9 沒有華麗的新框架概念,卻是那種「上線後你會默默感謝」的版本:伺服器不用再陪沒人看的分頁聊天,客服回到列表看到的是新資料,而登出後按上一頁,終於真的什麼都看不到。

好的系統不只要跑得快,還要懂得什麼時候該停,以及什麼東西不該被記住。

來源:Pause Polling in Background Tabs in Inertia.js v3.9(Paul Redmond,Laravel News,2026/10/13)。

延伸參考:Releases · inertiajs/inertia(GitHub,v3.9.0/v3.9.1/v2.3.29,2026/10/09);[3.x] Flush the prefetch cache when clearing history #3307(Pascal Baljet,GitHub);Polling 與 History Encryption(Inertia.js 官方文件)。

← 返回技術文章