#angular #caching #service-worker #progressive-web-apps #mobile-chrome
#angular #кэширование #service-worker #progressive-веб-приложения #mobile-chrome
Вопрос:
У меня есть веб-приложение Angular 7 Progressive (PWA, Service Worker).
Мое приложение выполняет http-запросы к api для получения данных для страницы. с помощью service worker я кэширую данные, чтобы при следующем входе пользователя на страницу он видел кэшированные данные, пока не получит последние данные из http-ответа.
Проблема в Chrome Mobile на Android. Он продолжает возвращать только кэшированный http-ответ, а не новые данные. Все остальные браузеры и ОС возвращают новые данные.
Вот мой файл ngsw.json:
{
"configVersion": 1,
"timestamp": 1553131016147,
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"updateMode": "prefetch",
"urls": [
"/favicon.ico",
"/index.html",
"/main.888b10bbc9ea06b8a9bf.js",
"/polyfills.9f595158f842acad6b37.js",
"/runtime.2f29e12616932f0ed037.js",
"/styles.d2478451b17ed7e705c5.css"
],
"patterns": []
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"urls": [],
"patterns": [
"https:\/\/maxcdn\.bootstrapcdn\.com\/font-awesome\/4\.7\.0\/css\/font-awesome\.min\.css"
]
}
],
"dataGroups": [
{
"name": "api",
"patterns": [
"\/api"
],
"strategy": "freshness",
"maxSize": 100,
"maxAge": 259200000,
"timeoutMs": 5000,
"version": 1
}
],
"hashTable": {
"/favicon.ico": "7c6a9b4e1370b6ee9386e16fba9ca4738b9e7037",
"/index.html": "fdf70f70c0f37aaa11b990ac0cf32839480b69a4",
"/main.888b10bbc9ea06b8a9bf.js": "abcc804a2ffbd57187d759a7c18b82963ac03d8c",
"/polyfills.9f595158f842acad6b37.js": "4eb96258211620bfe371478144b69844117f5120",
"/runtime.2f29e12616932f0ed037.js": "21109b3561b5a6c3ed51bc3015962f05da8e57b3",
"/styles.d2478451b17ed7e705c5.css": "29fb80dd9fc36fbb4ee107f15fd24dd7400ea255"
},
"navigationUrls": [
{
"positive": true,
"regex": "^\/.*$"
},
{
"positive": false,
"regex": "^\/(?:. \/)?[^/]*\.[^/]*$"
},
{
"positive": false,
"regex": "^\/(?:. \/)?[^/]*__[^/]*$"
},
{
"positive": false,
"regex": "^\/(?:. \/)?[^/]*__[^/]*\/.*$"
}
]
}
Соответствующая часть кода находится в разделе DataGroups, все URL-адреса с /api
префиксом, и, как вы можете видеть, я использую freshness
стратегию, которая в соответствии со страницей конфигурации Angular Service worker:
https://angular.io/guide/service-worker-config
свежесть оптимизирует валюту данных, предпочтительно извлекая запрошенные данные из сети. Только если время ожидания сети истекло, в соответствии с таймаутом, запрос возвращается в кэш. Это полезно для ресурсов, которые часто меняются; например, остатки на счетах.
но, похоже, в этом случае с Chrome Mobile на Android происходит обратное.
Кто-нибудь из вас сталкивался с этим и может указать мне правильное направление?
Ответ №1:
Из того, что я понимаю о том, как работают работники службы angular,:
Если вы указали freshness
стратегию, то сервисный работник будет ждать ответа сети в течение времени, указанного с timeout
помощью ключа (не тайм-аута). если сеть не отвечает в течение указанного времени, ответ будет отправлен из кэшированных данных сервисным работником.
В вашем случае на устройстве Android может быть меньше скорость Интернета, поэтому данные не извлекаются в течение указанного интервала ожидания, поэтому вы получаете кэшированные данные. Проверьте приложение, увеличив время ожидания.
На всякий случай, если вам это нужно.
Я обнаружил, что запросы API кеширования очень ненадежны, у меня не было четкого представления, когда я точно получу обновленные данные. (Да, когда maxSize или maxAge превышают указанные значения или время ожидания превышено, но по-прежнему нет четкого способа, которым я мог бы точно получить свежие данные.).
Всякий раз, когда я хотел получить свежие данные с сервера, я очищал все кэшированные данные из браузера, которые принадлежали ngsw
вызовам api. У меня был этот скрипт, написанный для того же. Посмотрите, если вам это нужно.
caches.keys().then((keys) => {
keys.forEach((eachCacheName) => {
let regExPat = /^(ngsw).*api.*/;
if (regExPat.test(eachCacheName)) {
caches.open(eachCacheName).then((eachCache) => {
eachCache.keys().then((requests) => {
requests.forEach((eachRequest) => { eachCache.delete(eachRequest); });
});
});
}
});
});
Комментарии:
1. текущий тайм-аут, который я использую, составляет 5 секунд, а среднее время отклика http, которое я получаю для вызовов API, составляет 250 мс, что составляет менее 5 секунд … а также страница завершает загрузку с кэшированными данными менее чем за 1 секунду, похоже, она ничего не ждет 5 секунд.
2. @shahaf Хорошо, у меня просто был какой-то шарнир, и это было только предположение. Я не знаю, что может быть причиной этого. Попробуйте открыть браузер в режиме инкогнито и посмотреть, есть ли какие-либо улучшения.