Similar presentations:
Как мгновенно загрузить предыдущую страницу. BFCache
1.
BFCache.Как мгновенно
загрузить
предыдущую
страницу
Илья Сидорчик Разработчик
интерфейсов
2.
окно со спикеромСодержание
чтобы знать куда не заходить, но не забудь
удалить
3.
Название глаы
4.
Название глаы
5.
Перелистываниеприложения
6.
Перелистывание
книги
7.
Пример: Маркет—Вайлдбериз.
Подпись: Работает
8.
BFCache работает между сайтами —пригодится, даже если у вас SPA
9.
Статистика Хромапо навигации
Каждый
10-й переход
Каждый
5-й переход
на десктопе
на таче
web.dev/bfcache
10.
BFCache1
2
Ускоряет сервис
Улучшает UX
3
4
Экономит железо
и деньги
Помогает
экологии :-)
11.
BFCache — это новаяэкспериментальная фича?
12.
BFCache — это стандартнаяфункциональность браузера
13.
Что такоеBFCache
Определение, история, поддержка юзер-агентами
14.
Определение
BFCache
Back/Forward Cache (сокр. BFCache) — это браузерная
оптимизация: предыдущая страница замораживается и при
возвращении на неё
моментально восстанавливается.
Особенности:
— Сохраняется вместе с JavaScript Heap
15.
дека гуглапро заморозку
youtu.be/5b4YcLB4DVI?t=346
16.
Определение
BFCache
Back Forward Cache (сокр. BFCache) — это браузерная
оптимизация: предыдущая страница замораживается и при
возвращении на неё
моментально восстанавливается.
Особенности:
— Сохраняется вместе с JavaScript Heap
— Работает в пределах одной вкладки
17.
Видео: Кнопка«Назад» → к старой
вкладке
18.
Определение
BFCache
Back Forward Cache (сокр. BFCache) — это браузерная
оптимизация: предыдущая страница замораживается и при
возвращении на неё
моментально восстанавливается.
Особенности:
— Сохраняется вместе с Javascript Heap
— Работает в пределах одной вкладки
— Хранится в оперативной памяти
19.
Как переходятназад-вперёд
Кнопка «Назад» или «Вперёд»
в браузере
1. Сочетание клавиш: ⌘← или ⌘→
1. Жест на трекпаде и экране:
свайп вправо или влево
1. На Андроиде стандартная кнопка
навигации
1. Из кода: history.back() и history.forward()
1.
20.
Сколько страницхранится
в BFCache
Сколько хватит памяти
21.
Времяжизни
страницы
3 ми
в BFCache
н
−4 %
в Хромиуме
bugs.chromium.org/p/chromium/issues/detail?id=1305878
22.
Времяжизни
страницы
30 мин
1 ми
в BFCache
0 н
−4 %
в Хромиуме
bit.ly/bfcached-page-lifetime-in-chromium
bit.ly/bfcached-page-lifetime-in-safari
в Веб-ките и Файерфоксе
23.
Времяжизни
страницы
30 мин
1 ми
в BFCache
0 н
−4 %
в Хромиуме
bit.ly/bfcached-page-lifetime-in-firefox
в Веб-ките и Файерфоксе
24.
Историяпоявления
BFCache
Back Forward Cache (сокр. BFCache) — это браузерный
кеш, в котором сохраняется предыдущая страница c кучей
задач Javascript в пределах одной вкладки
2002 Page
Cache
2009
Обновление
2019
Ренейминг
2005 Релиз
v1.5
2020 Частично
v86
2021 Релиз
v96
25.
ПоддержкаBFCache
в WebView
26.
BFCache — это стандартнаяфункциональность браузера
27.
Legacy codeBFCache — это стандартная
работа браузера
28.
Почему у васне работает
BFCache и как
его включить
Определение блокеров в инструментах разработчика,
поиск и исправление проблемного кода
29.
Не надо смотреть наполосу загрузки
30.
ИсторияВиктор Хомяков. BFCache, или Туда и обратно
31.
История32.
unload в аудитеЛайтхауса
developer.chrome.com/docs/lighthouse/performance/bf-cache/
33.
ПочемуОбработчик unload
34.
ПочемуBFCache
не работал
на Маркете
The page has an unload handler
in a subframe.
2. Pages whose main resource has cachecontrol:no-store cannot enter back/forward
cache.
3. Pages that use Media Device Dispatcher
are not eligible for back/forward cache.
4. Pages that have requested sensor
permissions are not currently eligible for
back/forward cache.
5. Pages that use SpeechSynthesis are not
currently eligible for back/forward cache.
1.
35.
Почему BFCacheне работал на
Маркете
36.
ПочемуОбработчик unload
Дев-тулзы для BFCache
37.
Причина1. Обработчик
unload
38.
Статистикаиспользования
unload
almanac.httparchive.org/en/2022/performance#fig-35
39.
Как используется unloadСобытие unload вызывается, когда пользователь закрывает
страницу. На unload отправляют аналитику, сохраняют
пользовательские данные, что-то финализируют и чистят
40.
Почему unload мешаетBFCache
C unload всё не так однозначно
41.
Unloadне так страшен
Если
Не мешает в мобильных браузерах
Не мешает в десктопном Сафари
Не будет мешать в будущем:
— BFCache-Opt-In: unload
github.com/fergald/docs/blob/master/explainers/permissions-policy-deprecate-unload.md
— Document-Policy: unload=?0
— Permissions-Policy: unload=()
42.
Что сделать с unloadwindow.onunload
Событие unload вызывается, когда пользователь
закрывает = () => {...};
window.addEventListener('unload',
...)
страницу. Обычно unload отправляет соответствующее
↓
событие в метрику или очищает данные на странице.
window.onpagehide = () => {...};
window.addEventListener('pagehide', ...)
Если вызвать unload при попадании в BFCache,
то залогируется лишнее событие в метрику или страница
может развалиться.
Если не вызвать unload при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
43.
Что сделать с unloadСобытие unload вызывается, когда пользователь закрывает
страницу. Обычно unload отправляет соответствующее
событие в метрику или очищает данные на странице.
Если вызвать unload при попадании в BFCache,
то залогируется лишнее событие в метрику или страница
может развалиться.
Если не вызвать unload при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
Хром для разработчиков. Page Lifecycle API
44.
Причина1. Обработчик
unload
45.
Что сделать с unload// Игнорируем window.onunload
Object.defineProperty(window, 'onunload', {set: function(handler) {}});
if (!window.original_addEventListener) {
window.original_addEventListener = window.addEventListener;
function addEventListener_monkeypatch(event_type, handler, opt) {
// Игнорируем
unload
Событие
unloadобработку
вызывается,
когда пользователь закрывает
if
(event_type
!==
'unload')
{
страницу. Обычно unload отправляет соответствующее
this.original_addEventListener(event_type,
handler,
opt);
событие в метрику или очищает данные на странице.
} else {
// Мы
также можем
за обработчиками
Если
вызвать
unload следить
при попадании
в BFCache,unload
handlers
were
used'); или страница
то console.trace('unload
залогируется лишнее
событие
в метрику
}
может
развалиться.
}
window.addEventListener
addEventListener_monkeypatch;
Если
не вызвать unload =
при
попадании в BFCache, то
}событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
chikamune-cr.github.io/how_to_disable_unload_handlers_by_monkeypatch/
46.
Что сделать с unloadСобытие unload вызывается, когда пользователь закрывает
страницу. Обычно unload отправляет соответствующее
событие в метрику или очищает данные на странице.
Если вызвать unload при попадании в BFCache,
то залогируется лишнее событие в метрику или страница
может развалиться.
Если не вызвать unload при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
47.
Что сделать с unloadСобытие unload вызывается, когда пользователь закрывает
страницу. Обычно unload отправляет соответствующее
событие в метрику или очищает данные на странице.
Если вызвать unload при попадании в BFCache,
то залогируется лишнее событие в метрику или страница
может развалиться.
Если не вызвать unload при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
48.
Как мы заменяли unloadв чужих скриптах
Если
⭐ Уровень Внутри Маркета. GTM
⭐⭐ Уровень Вне Маркета. UXFeedback
⭐⭐⭐ Уровень Вне Яндекса. Adriver
49.
Что сделать с beforeunloadfunction beforeUnloadListener(event) {
event.preventDefault();
Событие unload вызывается, когда пользователь закрывает
return event.returnValue
= 'Are you sure
you want to exit?';
страницу.
Обычно unload отправляет
соответствующее
};
событие в метрику или очищает данные на странице.
window.addEventListener('beforeunload', (event) => {
Если
вызвать unload при попадании
if (pageHasUnsavedChanges())
{ в BFCache,
то залогируется
лишнее событие в метрику или страница
beforeUnloadListener(event);
может
развалиться.
}
});
Если не вызвать unload при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
50.
Что сделать с beforeunloadfunction beforeUnloadListener(event) {
event.preventDefault();
Событие unload вызывается, когда пользователь закрывает
return event.returnValue
= 'Are you sure
you want to exit?';
страницу.
Обычно unload отправляет
соответствующее
};
событие в метрику или очищает данные на странице.
onPageHasUnsavedChanges(() => {
Если
вызвать unload при попадании в BFCache,
window.addEventListener('beforeunload',
beforeUnloadListener);
то залогируется лишнее событие в метрику или страница
});
может развалиться.
onAllChangesSaved(()
=> {
window.removeEventListener('beforeunload',
beforeUnloadListener);
Если не вызвать unload при попадании в BFCache, то
});
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
51.
ПочемуОбработчик unload
52.
Причина 2.Заголовок Cache-Control: nostore
53.
Статистикаиспользования
Cache-Control: nostore
almanac.httparchive.org/en/2022/performance#fig-35
54.
Как используется заголовокCache-Control: no-store
Значение no-store говорит браузеру не хранить ответы сервера в
HTTP-кеше
55.
Почему значение no-storeмешает BFCache
Исторически сложилось, что влияет на BFCache
github.com/fergald/explainer-bfcache-ccns/blob/main/README.md
56.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
almanac.httparchive.org/en/2022/performance#fig-35
27 сен 2019. trac.webkit.org/changeset/250437/webkit/
57.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
almanac.httparchive.org/en/2022/performance#fig-35
2 мар 2020. trac.webkit.org/changeset/257714/webkit/
58.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
almanac.httparchive.org/en/2022/performance#fig-35
12 июня 2020. trac.webkit.org/changeset/262978/webkit/
59.
Что сделать с no-storeСобытие unload вызывается, когда пользователь закрывает
Cache-Control:
no-store
страницу. Обычно unload
отправляет соответствующее
событие в метрику или ↓
очищает данные на странице.
Если вызвать unloadno-cache
при попадании
Cache-Control:
илив BFCache,
maxто
залогируется
лишнее
событие
в
метрику
или
страница
age=0
может развалиться.
Если не вызвать unload при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
almanac.httparchive.org/en/2022/performance#fig-35
developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
60.
ПочемуОбработчик unload
61.
Причина 3.Сложные браузерные АПИ
WebSockets, WebRTC, Web Locks,
IndexedDB
62.
Статистикаиспользования
WebSockets API
chromestatus.com/metrics/feature/timeline/popularity/1149
63.
Как используются сложныеАПИ
Сложные браузерные АПИ помогают делать чаты
и видеотрансляции, хранить данные в браузере и многое другое
64.
Почему сложные АПИмешают BFCache
Проектировались без учёта BFCache
Пока не понятно, что с ними делать
Могут общаться с другими вкладками в браузере
almanac.httparchive.org/en/2022/performance#fig-35
65.
Что сделатьс современными АПИ
66.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
67.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
almanac.httparchive.org/en/2022/performance#fig-35
MDN. Web API. Media Capture and Streams API. MediaDevices
68.
Что сделатьс современными АПИ
Событие unload вызывается, когда пользователь закрывает
страницу. Обычно unload отправляет соответствующее
событие в метрику или очищает данные на странице.
// fp.js
navigator.mediaDevices
Если вызвать unload при попадании в BFCache,
то залогируется лишнее событие в метрику или страница
может развалиться.
Если не вызвать unload при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
69.
Что сделатьс современными АПИ
70.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
71.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
almanac.httparchive.org/en/2022/performance#fig-35
MDN. Web API. Sensor APIs
72.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
almanac.httparchive.org/en/2022/performance#fig-35
MDN. Web API. Permissions API
73.
Что сделатьс современными АПИ
Событие unload вызывается, когда пользователь закрывает
страницу. Обычно unload отправляет соответствующее
событие в метрику или очищает данные на странице.
// fp.js
navigator.permissions
Если вызвать unload при попадании в BFCache,
то залогируется лишнее событие в метрику или страница
может развалиться.
Если не вызвать unload при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
74.
Что сделатьс современными АПИ
Событие unload вызывается, когда пользователь закрывает
страницу. Обычно unload отправляет соответствующее
событие в метрику или очищает данные на странице.
// fp.js
// Не используется. Оставлено
Если вызвать unload при попадании в BFCache,
для
сохранения
длины
логаили страница
то залогируется
лишнее событие
в метрику
может
развалиться.
permissions: (): boolean => true,
Если не вызвать unload при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
75.
Причина 4.Доступ к window.opener
76.
ПочемуОбработчик unload
77.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
78.
Что сделатьс современными АПИ
Событие unload вызывается, когда пользователь закрывает
<head>
страницу. Обычно unload отправляет соответствующее
событие
... в метрику или очищает данные на странице.
<script>
Если
вызвать unload при попадании в BFCache,
то залогируется
лишнее событие в метрику или страница
delete window.Accelerometer;
может развалиться.
delete window.speechSynthesis;
Если
не вызвать unload при попадании в BFCache, то
</script>
событие может никогда не обработаться, например, когда
</head>
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
almanac.httparchive.org/en/2022/performance#fig-35
developer.mozilla.org/en-US/docs/Web/API/Sensor_APIs#permissions_and_permissions_policy
79.
Что сделатьс современными АПИ
Событие unload вызывается, когда пользователь закрывает
страницу. Обычно unload отправляет соответствующее
событие в метрику или очищает данные на странице.
Permissions-Policy:
unload=(),
Если вызвать unload при попадании в BFCache,
accelerometer=(),
то залогируется лишнее событие в метрику или страница
может развалиться.
gyroscope=(),
magnetometer();
Если не вызвать unload
при попадании в BFCache, то
событие может никогда не обработаться, например, когда
пользователь закроет браузер.
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
almanac.httparchive.org/en/2022/performance#fig-35
developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy
80.
ПочемуОбработчик unload
А что делать
с WebSockets?
Может, есть вариант
с IndexedDB?
81.
«Закрываем за собойдверь»
let dbPromise;
function openDB() {
if (!dbPromise) {
dbPromise = new Promise((resolve, reject) => {
const req = indexedDB.open('my-db', 1);
Событие
unload вызывается,
когда пользователь закрывает
req.onupgradeneeded
= () => req.result.createObjectStore('keyval');
req.onerror =Обычно
() => reject(req.error);
страницу.
unload отправляет соответствующее
req.onsuccess = () => resolve(req.result);
событие
в метрику или очищает данные на странице.
});
}
return dbPromise;
Если
вызвать unload при попадании в BFCache,
}
тоОтключаемся
залогируется
лишнее
событие
метрику
или
страница
//
от БД, когда
пользователь
ушёл навдругую
страницу,
переключил
вкладку или окно
window.addEventListener('pagehide',
() => {
может развалиться.
if (dbPromise) {
dbPromise.then(db => db.close());
Если
не =вызвать
unload при попадании в BFCache, то
dbPromise
null;
}
событие
может никогда не обработаться, например, когда
});
пользователь
закроет
браузер.
//
Подключаемся к БД,
когда пользователь
открыл страницу, вернулся или переключился на неё
window.addEventListener('pageshow', () => openDB());
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
82.
ПочемуОбработчик unload
83.
Причина 4.Доступ к window.opener
84.
Статистикаиспользования
window.opener
chromestatus.com/metrics/feature/timeline/popularity/4124
85.
Как используется openerwindow.opener — ссылка на window предыдущей страницы.
С помощью этого получают данные о ней
86.
window.opener позволяет управлять предыдущей страницейalmanac.httparchive.org/en/2022/performance#fig-35
mathiasbynens.github.io/rel-noopener/
87.
Что сделатьс opener
Событие unload вызывается, когда пользователь закрывает
window.open(url)
страницу. Обычно unload отправляет соответствующее
событие
в
метрику
или
очищает
данные
на
странице.
↓
Если вызвать unload приnull,
попадании в BFCache,
window.open(url,
то залогируется лишнее событие в метрику или страница
'noopener')
может развалиться.
или
Если не вызвать unload при попадании в BFCache, то
<a
href={url}
target="_blank"
событие
может никогда
не обработаться, например, когда
пользователь закроет />
браузер.
rel="noopener"
Вызвать unload при закрытии браузера
со страницы в BFCache — сложно.
88.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
almanac.httparchive.org/en/2022/performance#fig-35
Гугл-док. bit.ly/bfcache-not-restored-reasons
89.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
almanac.httparchive.org/en/2022/performance#fig-35
github.com/WebKit/WebKit/blob/main/Source/WebCore/history/BackForwardCache.cpp#L282
90.
Иногда сам интерфейс может блокироватьмоментальный переход назад
91.
причина 5 длякнопки назад
используется ссыл
92.
Добавление onClick ссылкедля моментального возврата
function buildGoBackOnClick() {
if (!document.referrer) return;
return (event) => {
event.preventDefault();
history.back();
};
}
93.
Добавление onClick ссылкедля моментального возврата
function buildGoBackOnClick(prevPathnames) {
if (!document.referrer) return;
const refPathname = new URL(document.referrer).pathname;
const wasReferrerActualPreviousPage = prevPathnames.some(
(prevPathname) => refPathname.includes(`/${prevPathname}`)
);
if (wasReferrerActualPreviousPage) {
return (event) => {
event.preventDefault();
history.back();
};
}
}
94.
Почему у васперестал
работать сайт
из-за BFCache
Странные данные на предыдущей странице,
полезные хелперы для решения проблем
95.
load → pageshow вновых скриптах,
когда нужно.
96.
Чиним актуализациюпосле возвращения на чекаут
fromEvent(window, 'load').pipe(
map(() => actualizeCartGroup({cartGroupId})),
);
↓
fromEvent(window, 'pageshow').pipe(
map(() => actualizeCartGroup({cartGroupId})),
);
97.
старое значение вполе поиска
98.
Добавление onClick ссылкедля моментального возврата
// RxJS-хук для старта эпика,
// когда страница досталась из BFCache
export const bfcache: () =>
Observable<PageTransitionEvent> = () =>
fromEvent(window, "pageshow").pipe(
filter((event) => event.persisted)
);
99.
ДобавлениеonClick
ссылке
// Пример использования RxJS-хука
export
constмоментального
onSetActualTextFromBFCache = () => возврата
для
bfcache().pipe(
switchMap(() => {
const urlParams = new URLSearchParams(window.location.search);
const text = urlParams.get('text');
input.value = text;
return of(changeText({text}));
});
);
100.
старое значение вполе поиска
101.
Добавление onClick ссылкедля моментального возврата
// React-хук для обновления данных,
// когда страница досталась из BFCache
export const useUpdateAfterBFCache = (doSmth: () => void): void => {
useEffect(() => {
const handlePageshow = (event: PageTransitionEvent) => {
if (event.persisted) {
doSmth();
}
};
window.addEventListener('pageshow', handlePageshow);
return () => {
window.removeEventListener('pageshow', handlePageshow);
};
}, []);
};
102.
при разлогине сИзбранного
а если у вас банк,
103.
при разлогине сИзбранного
а если у вас банк,
104.
/*** Перезагружаем страницу,
* если пользователь вышел из аккаунта и вернулся назад
*
* Объяснение
* На предыдущей странице состояние JavaScript без изменений,
* поэтому оно только говорит, что юзер был авторизован (wasAuth).
* Актуальная проверка на авторизацию — по куке или запросу к TVM
*/
const checkLogout = () => {
const isAuthAfterBFCache = document.cookie.match(/my-login/);
if (wasAuth && !isAuthAfterBFCache) {
document.body.innerHTML = '';
location.reload();
}
}
useUpdateAfterBFCache(checkLogout);
Добавление onClick ссылке
для моментального возврата
105.
при разлогине сИзбранного
а если у вас банк,
106.
при разлогине сИзбранного
а если у вас банк,
107.
при разлогине сИзбранного
а если у вас банк,
108.
Как используется заголовоки почему он мешает
BFCache
Значение no-store говорит браузеру, не хранить ответы сервера
в HTTP-кеше
Cache-Control: no-store
↓
Cache-Control: no-cache или Cache-Control: max-age=0
almanac.httparchive.org/en/2022/performance#fig-35
github.com/WebKit/WebKit/blob/main/Source/WebCore/history/BackForwardCache.cpp#L282
109.
Что делать,чтобы
не сломали
BFCache
Автотест, график, рассказ коллегам
110.
Сквозной (e2e) тест// bfcache.test.js
await this.browser.yaOpenPage('product', data);
await this.browser.waitUntil(async () => {
const readyState = await this.browser
.execute(() => document.readyState)
.then(({ value }) => value);
return readyState === "complete";
});
111.
Сквозной (e2e) тест// Продолжение bfcache.test.js
await this.browser.yaOpenPage('product-reviews');
await this.browser.execute(() => history.back());
112.
Сквозной (e2e) тест// Продолжение bfcache.test.js
await this.browser.yaOpenPage('product-reviews');
await this.browser.execute(() => history.back());
// Проверяем, что страница досталась из BFCache
113.
Сквозной (e2e) тест// Продолжение bfcache.test.js
await this.browser.yaOpenPage('product-reviews');
await this.browser.execute(() => history.back());
// Проверяем, что страница досталась из BFCache
// ?
const navigationType = await this.browser
.execute(() => performance.getEntriesByType(
"navigation"
)[0].type)
.then(({ value }) => value);
114.
Сквозной (e2e) тест// Продолжение bfcache.test.js
await this.browser.yaOpenPage('product-reviews');
await this.browser.execute(() => history.back());
// Проверяем, что страница досталась из BFCache
// Будет всегда возвращать "back_forward"
const navigationType = await this.browser
.execute(() => performance.getEntriesByType(
"navigation"
)[0].type)
.then(({ value }) => value);
Navigation Timing Level 2. NavigationTimingType enum
115.
Сквозной (e2e) тест// Продолжение bfcache.test.js
await this.browser.yaOpenPage('product-reviews');
await this.browser.execute(() => history.back());
// Проверяем, что страница досталась из BFCache
await this.browser.waitUntil(
async () => this.browser
.execute(() => window._isPageFromBFCache)
.then(({ value }) => Boolean(value)),
5000,
"Страница не открылась моментально из BFCache. " +
"Cм. bit.ly/bfcache-not-restored-reasons"
);
116.
Сквозной (e2e) тест// App.js
// Готовим проверочное поле для теста
const markBFCache = () => {
window._isPageFromBFCache = true;
};
useUpdateAfterBFCache(markBFCache);
117.
Ручной тест— Расписанный по шагам тест-кейс: A → B → A
— Еженедельный регресс
— Регресс внешними асессорами
118.
График хитов119.
Добавление onClick ссылкедля моментального возврата
/**
* Отправить метрику, что страница из BFCache
* @see https://web.dev/bfcache/
*/
function sendBFCacheStatus() {
window.addEventListener('pageshow', (event) => {
if (event.persisted) {
sendCounter('bfcache');
}
});
}
120.
BFCache notRestoredReasonsAPI
function returnNRR() {
const navEntries = performance.getEntriesByType("navigation");
for (let i = 0; i < navEntries.length; i++) {
console.log(`Navigation entry ${i}`);
let navEntry = navEntries[i];
console.log(navEntry.notRestoredReasons);
}
}
developer.chrome.com/docs/web-platform/bfcache-notrestoredreasons/
121.
Плагин для линтераgithub.com/ilyasidorchik/eslint-plugin-bfcache
122.
Рассказколлегам
support.apple.com/ru-ru/HT204948
123.
Плагин для линтера124.
Рассказ для коллег125.
Плагин для линтера126.
Рассказ для коллег127.
Как BFCacheвлияет
на метрики
Ухудшение и адаптация продуктовых и скоростных метрик
128.
Продуктовые метрикипросядут
−6
%
визитов корзины
−4
%
визитов чекаута
129.
ДобавлениеonClick
ссылке
// Отправляем визит страницы
при первой
загрузке
gtag("event",
"page_view");
для
моментального
возврата
window.addEventListener("pageshow", (event) => {
// Отправляем ещё один визит страницы
// при восстановлении из BFCache
if (event.persisted) {
gtag("event", "page_view");
}
});
130.
Скоростные метрикитоже просядут
131.
Скоростные метрикитоже просядут
Navigation Timing Level 2. NavigationTimingType enum
132.
Адаптируем FCP и LCPпод BFCache
onBFCacheRestore((event) => {
metric = initMetric('FCP'); // Также для LCP
report = bindReporter(onReport, metric, FCPThresholds);
doubleRAF(() => {
metric.value = performance.now() - event.timeStamp;
report(true);
});
});
github.com/GoogleChrome/web-vitals/blob/main/src/onFCP.ts
133.
Адаптируем CLSпод BFCache
onBFCacheRestore(() => {
metric = initMetric('CLS', 0);
report = bindReporter(onReport, metric, CLSThresholds);
doubleRAF(() => report());
});
github.com/GoogleChrome/web-vitals/blob/main/src/onCLS.ts
134.
Адаптируем CLSпод BFCache
youtu.be/mdB-J6BRReo?t=469
135.
мб скриншот GoogleSearch Console
support.google.com/webmasters/answer/9205520
136.
Видео: страницаоткрывается в новой
вкладке
137.
Видео: страницаоткрывается в новой
вкладке
138.
Видео: страницаоткрывается в новой
вкладке
139.
BFCacheБыстро, удобно, экономно
Стандартная функциональность браузера
Инструменты разработчика в Хроме
Замените unload на pagehide, no-store на
no-cache, отпишитесь от лишнего при
pagehide
Адаптируйте сайт под BFCache
Напишите тест, сделайте график,
расскажите коллегам
Адаптируйте метрики
140.
141.
Спасибо!Илья Сидорчик, разработчик интерфейсов
Презентация в канале: t.me/sidorchikdev