Angular не обновляет страницу с включенным кешем
Я создал веб-сайт angular, который содержит форму "добавить" и "удалить", чтобы манипулировать данными в таблице на той же странице.
Когда я тестирую его локально или с помощью Chrome Dev Console (отключенный кеш), когда я добавляю новый элемент или удаляю его, таблица автоматически обновляется. Когда я тестирую его на сервере производства (IIS Server) моего клиента, он работает только с консолью Chrome Dev Console. В противном случае они должны использовать CTRL + F5 для обновления кеша и отображения изменений на странице.
Это код компонентов:
addProduct() {
this._productsService.addProduct(this.addFormProductItem)
.subscribe(v => {
this._productsService.getProducts().subscribe(
products => {this.products = products, this.onChangeTable(this.config)}
);
});
this.addmodalWindow.hide();
return;
}
onChangeTable(config: any, page: any = {
page: this.page,
itemsPerPage: this.itemsPerPage
}): any {
if (config.filtering) {
Object.assign(this.config.filtering, config.filtering);
}
if (config.sorting) {
Object.assign(this.config.sorting, config.sorting);
}
this.ng2TableData = this.products;
this.length = this.ng2TableData.length;
let filteredData = this.changeFilter(this.ng2TableData, this.config);
let sortedData = this.changeSort(filteredData, this.config);
this.rows = page && config.paging ? this.changePage(page, sortedData) : sortedData;
this.length = sortedData.length;
}
Я предполагаю, что это связано либо с конфигурацией сервера, либо с кодом webpack. Тем не менее, я не знаком с последним, и я просто оставил его, как это было в исходном пакете, который я использовал.
Я создал сущность с веб-пакетом, так как это длинный файл
Изменить 1: После некоторых дополнительных исследований я попытался добавить следующее в файл web.config в корневую папку приложения.
<caching enabled="false" enableKernelCache="false">
<profiles>
<add extension=".css" policy="DontCache" kernelCachePolicy="DontCache" />
<add extension=".html" policy="DontCache" kernelCachePolicy="DontCache" />
<add extension=".js" policy="DontCache" kernelCachePolicy="DontCache" />
</profiles>
</caching>
Тем не менее, у меня все еще такое же поведение. Добавление элемента с закрытой консолью Dev Console не обновляет таблицу. Но если у меня консоль dev открыта и отключена кеш, то она обновляет ее без необходимости обновления.
Изменить 2: Работа с окном инкогнито не устраняет проблему.
Изменить 3: Добавление метатег в index.html еще не исправляет проблему.
<meta http-equiv="Cache-control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
Изменить 4:
getProducts() {
return this._http.get(this.API + '/products/all')
.map((response: Response) => <Product[]>response.json().products);
}
addProduct(product:Product) {
if ( this._loggedInGuard.isLoggedIn() ) {
let token = localStorage.getItem('my.token');
let body = JSON.stringify(product);
let headers = new Headers(
{ 'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token});
return this._http
.post(this.API + "/products/store", body, {headers: headers} )
.map(res => res.json())
.catch(this._responseService.catchBadResponse)
.do(() => this._responseService.success('Success. You added a product!'));
}
}
Изменить 5
Единственное решение, которое я могу найти, - это перезагрузить окно каждый раз, когда я обновляю данные с помощью location.reload(true)
. Но опять же, это работает только на Firefox, а не на Chrome. И я не буду признавать, что вам нужно отказаться от единственной причины иметь одностраничное приложение, чтобы это сработало.
Ответы
Ответ 1
Есть определенные причины, по которым ни одна из вещей, которые вы пробовали, не зафиксировала.
Прежде всего, использование элемента <caching>
в web.config не указывает браузеру, как кэшировать ответ. Он используется для настройки того, как сервер IIS кэширует ответ, чтобы он мог быть повторно использован в будущих запросах. Здесь - это документация, которая объясняет это.
Далее, тэги <meta>
. Обычно управление кешем выполняется с помощью фактических заголовков HTTP. Хотя вы можете использовать теги <meta>
для установки заголовков, которые вообще не указаны в вашем заголовке ответа HTTP, они НЕ будут переопределять заголовки HTTP, которые уже установлены. IIS имеет значения по умолчанию для кэширования в заголовках ответов, тэги <meta>
на самом деле ничего не сделают. Теги <meta>
действительно полезны только при загрузке по URL file:///
.
Чтобы надежно достичь того, что вы пытаетесь сделать, вам нужно фактически заставить сервер отправлять заголовки управления кешем, которые вы хотите использовать. Это может варьироваться в зависимости от того, какие браузеры вы хотите поддерживать, но поскольку вы используете angular, я могу предположить, что вы поддерживаете современные браузеры, что просто. Следующее отключит кеширование для ВСЕХ статических файлов на вашем веб-сайте, что, вероятно, не совсем то, что вы хотите, но может служить в качестве руководства.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<location path=".">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
</system.webServer>
</location>
</configuration>
Однако, первое, что вам нужно сделать, - изучить текущие заголовки ответов, которые IIS отправляет вам! Это можно сделать легко с помощью инструментов разработчиков Chrome. Если вы видите заголовок Cache-Control:
в ответе, это подтвердит мои рассуждения о том, почему тэги <meta>
не работают.
Если вы создаете HTML для своего приложения angular не со статическим .html файлом, а вместо него генерируете его с помощью ASP.NET, лучше всего добавить код в ваш контроллер, который устанавливает заголовок кэша.
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Если вы хотите поддерживать гораздо более старые или взломанные браузеры, есть другие ресурсы, которые описывают, какие дополнительные заголовки вам нужно добавить, что снова можно сделать с помощью кода web.config или ASP.NET. Я просто хочу повторить повтор: если у вас все еще есть проблемы, убедитесь, что вы просматриваете заголовки ответов, отправленные сервером.
Ответ 2
Для страниц ASP.NET вы не хотите кэшировать нигде,
HttpContext.Current.Response.Cache.SetCacheability
(HttpCacheability.Server);
HttpContext.Current.Response.Cache.SetNoStore();
Response.Cache.SetExpires(DateTime.Now);
Response.Cache.SetValidUntilExpires(true);
Это указывает всем кэширующим прокси-серверам, что только серверу разрешено кэшировать страницу и сообщает серверу не кэшировать его. Последние две строки кода просят браузер не кэшировать его. Приведенный выше код приводит к этим трем заголовкам:
Cache-Control:no-cache, no-store
Pragma:no-cache
Expires:-1
Вы также можете добавить что-то уникальное в строку запроса, чтобы предотвратить кеширование браузера.
.post(this.API + "/products/store?unique=milliseconds", body, {headers: headers} )
Ответ 3
Добавить параметр с полной меткой времени или уникальный идентификатор для каждого HTTP-вызова, который вы не хотите кэшировать. Работает как чемпион. Я использовал ту же проблему, используя шаблоны в Angular. Я просто добавил http-перехватчик и добавил временную метку для каждого вызова, и проблема исчезла.