以前キャッシュが残っていたためCache-Control: no-store
をヘッダに設定する対応を行った
しかし、Safariではbfcache
という訪問したページ間の戻る、進むという動作にページのロードをおこなわない機能がCache-Control: no-store
を設定していても効いてしまうらしい
少し古いがSafariのリリースノートに記載されている
Release Notes - Safari Technology Preview - Safari - Apple Developer
Allowed pages served over HTTPS with Cache-Control: no-store header to enter the back-forward cache
実際に挙動をみてみる
問題になった構成に近づけるために以下の構成にした
- expressでAPIサーバを用意
- APIのレスポンスヘッダに
Cache-Control: no-store
を設定 - vueでコンテンツをつくる
- vueのcomputedでfetchを使ってexpressのAPIからデータを取得してvueのdataを更新する
- 2ページ用意し、最初のページに次ページのリンクをつけておく
APIサーバ
'use strict'; // [START gae_node_request_example] const cors = require('cors') const express = require('express'); const app = express(); app.get('/api/message/', cors(), (req, res) => { const now = new Date(); res.header('Cache-Control', ['no-store'].join(',')); res.json({ message: `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`, }); }); // Start the server const PORT = process.env.PORT || 4040; app.listen(PORT, () => { console.log(`App listening on port ${PORT}`); console.log('Press Ctrl+C to quit.'); });
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> {{ message }} </div> <a href="/next.html">next</a> </body> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script> var app = new Vue({ el: '#app', data: { message: 'Hello First Page! - ' }, created() { const _this = this; fetch('http://localhost:4040/api/message') .then(function(response) {return response.json();}) .then(function(data) { _this.message = _this.message + data.message; }) } }) </script> </html>
next.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> {{ message }} </div> </body> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script> var app = new Vue({ el: '#app', data: { message: 'Hello Next Page! - ' }, created() { const _this = this; fetch('http://localhost:4040/api/message') .then(function(response) {return response.json();}) .then(function(data) { _this.message = _this.message + data.message; }) } }) </script> </html>
表示されたページ
変化がわかりやすいように時刻を表示するようにした
Chrome と Safar で比較
操作手順
- First Pageを表示 → nextをクリック
- Next Pageを表示 → ブラウザバック
- First Pageを表示
確かにSafariはCache-Control: no-store
を設定していてもブラウザバックをするとデータが更新されていない模様
対策
pageshow
イベントとpersisted
を使う
https://developer.mozilla.org/ja/docs/Web/API/Window/pageshow_event
https://developer.mozilla.org/ja/docs/Web/API/PageTransitionEvent/persisted
persisted
はWebページがキャッシュからロードされているかどうかの真偽値プロパティ
ただ、これをキャッシュさせたくないページ全てにいれないといけないのは悩ましい