Service Worker 和非 CORS(不透明)響應
Service Worker 攔截非 CORS 響應并使用 Cache API 將其緩存為不透明響應。這些響應會以狀態(tài)碼 0 被攔截符相。由于其不透明特性,JavaScript 無法檢查這些響應勾缭,使得 Service Worker 無法根據(jù)狀態(tài)碼、頭部或其他條件對這些響應進行有條件緩存。
Workbox 緩存策略和不透明響應
Workbox 建議(并默認為)在“優(yōu)先緩存”策略中僅緩存狀態(tài)碼為 200 的響應颠通。這意味著在這種情況下蚓庭,不透明響應不會被緩存致讥。然而,“stale-while-revalidate”(舊緩存優(yōu)先器赞,再重新驗證)策略會緩存狀態(tài)碼為 200 和 0 的響應垢袱。
將不透明響應用作頁面資源
通過 HTML 元素的 src
屬性加載的資源(如 img
、video
等)默認作為 no-cors
請求發(fā)出港柜,因此它們的響應會是不透明的请契。在瀏覽器允許非 CORS 跨域資源的情況下,不透明響應可用作網(wǎng)頁資源夏醉。以下是可以使用非 CORS 跨域資源(即不透明響應)的元素子集:
<script>
<link rel="stylesheet">
-
<img>
姚糊、<video>
和<audio>
-
<object>
和<embed>
<iframe>
可以通過添加 crossorigin
屬性將這些元素的請求變?yōu)?CORS。
需要注意的是授舟,不透明響應對字體資源無效救恨。
要確定是否可以將不透明響應用作頁面上的特定類型資源,可以查閱相關(guān)規(guī)范释树。例如肠槽,HTML 規(guī)范解釋了非 CORS 跨域(即不透明)響應可用于 <script>
元素,但存在一些限制奢啥,以防止泄露錯誤信息秸仙。
不透明響應的限制
- 檢查:Service Worker(或 JavaScript 通常情況下)無法檢查不透明響應,包括其大小桩盲。
-
訪問頭部和主體:不能從
Response
類的大多數(shù)屬性中獲取有效信息寂纪,例如headers
,也不能調(diào)用Body
接口中的json()
或text()
等方法。
重寫 no-cors 請求以檢查不透明響應
作為應對不透明響應限制的解決方法捞蛋,可以在 Service Worker 中攔截 no-cors
請求并將其重寫為 CORS 請求孝冒。這樣可以檢查并根據(jù)狀態(tài)碼有條件地緩存這些響應。
例如拟杉,使用 Workbox 可以這樣實現(xiàn):
const forceCorsRequestPlugin = {
requestWillFetch: async ({ request }) => {
// 如果請求不是 no-cors庄涡,則不修改請求(例如包含憑證的請求)。
if (request.mode !== "no-cors") {
return request;
}
return new Request(request, { mode: "cors", credentials: "omit" });
},
};
不透明響應與 Cache Storage API
關(guān)于 Cache Storage API(Service Worker 用于處理緩存的 API)行為的一個小細節(jié):當使用不透明響應時搬设,add()
和 addAll()
方法會拒絕狀態(tài)碼不在 2XX 范圍內(nèi)的響應穴店。因此,使用 add()
或 addAll()
方法將無法將不透明響應添加到緩存中拿穴。要解決此問題泣洞,可以顯式執(zhí)行 fetch()
請求,然后使用 put()
方法存儲不透明響應默色。
不透明響應與 navigator.storage API
為防止跨域信息泄露球凰,瀏覽器在計算存儲配額限制時會對不透明響應的大小進行顯著填充。在 Google Chrome 中该窗,單個緩存的不透明響應對總體存儲使用的最低貢獻大小約為 7 MB。請記住這一點蚤霞,以便在決定緩存多少不透明響應時避免超出存儲配額限制酗失,這樣可能會比預期更快達到上限。