Ответ
Кэширование статических файлов — это механизм, который инструктирует браузер клиента или промежуточные прокси-серверы сохранять копии статических ресурсов (CSS, JS, изображения, шрифты) локально на определенный срок. Это drastically сокращает количество запросов к серверу и ускоряет загрузку повторно посещаемых страниц.
Как работает? Сервер отправляет файл вместе с HTTP-заголовками, управляющими кэшем:
Cache-Control(современный):max-age=3600— кэшировать на 1 час.Expires(устаревший): Указывает точную дату истечения срока действия.ETag/Last-Modified: Для условных запросов (проверка, изменился ли файл).
Настройка в ASP.NET Core:
По умолчанию app.UseStaticFiles() использует кэширование. Настроить его можно через StaticFileOptions.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ...
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
// Кэшировать статические файлы на 1 день (86400 секунд) в public кэше
var headers = ctx.Context.Response.Headers;
headers["Cache-Control"] = "public, max-age=86400";
// Устаревший заголовок для совместимости
headers["Expires"] = DateTime.UtcNow.AddDays(1).ToString("R");
}
});
}
Стратегии кэширования:
-
Агрессивное кэширование (для версионных файлов): Используйте для файлов с хэшем в имени (например,
site.[hash].css). Их содержимое никогда не меняется, поэтому можно кэшировать на очень долгий срок.Cache-Control: public, max-age=31536000 // 1 год -
Умеренное кэширование (для часто изменяемых файлов): Для файлов без версии, которые могут обновляться.
Cache-Control: public, max-age=3600 // 1 час -
Проверка актуальности (использование ETag): Браузер отправляет заголовок
If-None-Matchсо значениемETag. Если файл не изменился, сервер отвечает304 Not Modified(без тела файла), что экономит трафик.
Проблема инвалидации кэша и ее решение:
- Проблема: Вы обновили
site.cssна сервере, но у пользователей в кэше старая версия. - Решение 1 (рекомендуемое): Использовать версионирование имен файлов через систему сборки (Webpack, Gulp) или query-строку (менее надежно). При изменении файла меняется и его имя, браузер запрашивает новый ресурс.
site.css->site.a1b2c3d4.css
- Решение 2: Использовать
Cache-Control: no-cache(не "не кэшировать", а "кэшировать, но проверять с сервером каждый раз") для критичных к актуальности файлов.
**Для файлов, которые часто меняются (например, JSON API), кэширование на стороне клиента обычно не применяется или используется с коротким max-age.
Ответ 18+ 🔞
Да ты посмотри, какие сложности на ровном месте! Кэширование статики, блядь. Ну, в общем, это когда твой браузер или какой-нибудь прокси-сервер не тупо каждый раз тащит с сервера одни и те же картинки и скрипты, а сохраняет их у себя на жёстком диске, как запасливый хомяк. И потом, когда ты снова на ту же страницу заходишь, он не дергает сервер, а достаёт эту хуйню из своих закромов. Скорость загрузки, соответственно, взлетает просто до небес, трафик экономится — красота, ёпта.
Как эта магия работает?
Сервер, отдавая файл, присылает вместе с ним специальные заголовки — инструкции для браузера. Типа, «чувак, держи этот styles.css и не беспокой меня с ним ближайший час». Основные приколы вот эти:
Cache-Control(самый главный сейчас): пишешьmax-age=3600— значит, файл можно спокойно хранить 3600 секунд, то есть час.Expires(старый, но ещё встречается): там прямо дата и время, когда кэш протухнет.ETagилиLast-Modified: это для умных проверок. Браузер потом может спросить: «Эй, а тот файл, который ты мне вчера дал, ещё актуальный?» И если не изменился, сервер ответит «да, актуальный, живи с ним дальше», не пересылая всю ту же портянку заново.
Как это впихнуть в ASP.NET Core?
По умолчанию, когда ты пишешь app.UseStaticFiles(), там уже какое-то кэширование есть. Но если хочешь всё по-своему, настрой через StaticFileOptions.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ... пропустим всякую предварительную хуйню
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
// Вешаем на статику правило: кэшируйся, сука, на целые сутки (86400 секунд) и в публичном кэше
var headers = ctx.Context.Response.Headers;
headers["Cache-Control"] = "public, max-age=86400";
// И на всякий случай старый заголовок для совсем древних браузеров
headers["Expires"] = DateTime.UtcNow.AddDays(1).ToString("R");
}
});
}
А теперь стратегии, их есть у меня:
-
Агрессивная, наглухо (для файлов с версией в названии): Если у тебя файл называется типа
main.abcd1234.js, где этот хеш меняется только когда сам файл поменялся, то его можно кэшировать на овердохуище времени. Год, например. Он же никогда не изменится под этим именем.Cache-Control: public, max-age=31536000 // Год, Карл! -
Умеренная, по-божески (для файлов, которые могут обновиться): Ну,
style.cssбез всяких хешей. Заложил ему час жизни, и ладно.Cache-Control: public, max-age=3600 // Часок поспит в кэше -
С проверкой (с ETag): Браузер хранит файл, но перед использованием такой: «Сервак, а ты не обновил ничего?». Шлёт заголовок
If-None-Match. Если файл прежний, сервер отвечает статусом304 Not Modified(типа, «всё ок, юзай старый»), и по сети летит только этот короткий ответ, а не весь файл. Умно и экономно.
Главная засада и как из неё вылезти:
- Засада: Ты на сервере перезалил новый
script.js, а у пользователя в браузере лежит закэшированный старый. И он, бедолага, видит кривую, неработающую хуйню и пишет тебе в поддержку, что всё сломалось. - Лекарство первое (самое каноничное): Версионирование имён файлов. Меняешь файл — система сборки (Webpack, Gulp) автоматом меняет и его имя, добавляя туда хеш. Старый
script.jsстановитсяscript.5f8a3e.js. Для браузера это совершенно новый файл, он его скачает. Старый кэш никому не мешает. - Лекарство второе (для самых нервных файлов): Ставить
Cache-Control: no-cache. Это не значит «не кэшировать», а значит «кэшируй, но перед использованием всегда спроси у сервера, актуален ли он». Для данных, которые должны быть супер-свежими (например, тот же JSON от API), либо не кэшируешь, либо ставишь очень короткийmax-age.