Pull to refresh

Проверка включенного кэширования у браузера

Reading time4 min
Views18K
Про то, что клиентское кэширование использовать можно и нужно, за последние несколько лет узнали многие, а вот о том какие проблемы это вызывает — каждый узнает на своем опыте. Поэтому спешу поделиться своим опытом и проблемой, возникшей с пользователями, у которых кэш браузера выключен. Пользователи не знают, что у них выключен кэш и жалуются на медленную скорость загрузки страниц.

Предыстория (можно пропустить)


На проекте, в котором мне довелось работать, была проблема большого количества java-script файлов (около 40 штук — использовались 2 js библиотеки + десяток самописных компонентов). Такое количество последовательно подгружаемых файлов вызывало долгую загрузку страницы. Я, как человек знакомый с трудами товарища sunnybear, предложил склеить все эти файлы в один и закэшировать его.

В итоге сайт залетал, и мы уже было хотели расслабиться, как вдруг появились сообщения от пользователей, которые по прежнему сообщали о проблеме долгой загрузки страницы. После непродолжительных поисков было обнаружено, что это пользователи, у которых по тем или иным причинам отключен браузерный кэш.

Итак, задача заключалась в определении пользователей с отключенным кэшем и своевременном их информировании. По счастью первая страница проекта уже содержала список проверок на блокировку всплывающих окон, рабочий js и flash. Поэтому добавление проверки на кэш браузера было вполне логичным, и не портило существующую концепцию.

Как проверить кэш браузера из js?


Любопытно, что задав этот вопросу гуглу, я получил список форумов с какими-то сумасшедшими идеями подсчета времени запроса и прочими невнятными идеями. Поэтому алгоритм проверки рабочего кэша пришлось придумать:
  1. Отправляем запрос на сервер
  2. Получаем ответ с неким содержимым и заголовками кэширования этого запроса
  3. Изменяем содержимое на сервере
  4. Отправляем второй запрос на сервер
  5. Сравниваем полученное содержимое. Если кэш работает, то содержимое второго запроса будет соответствовать первому, если нет — мы получим измененное содержимое с сервера


Реализация алгоритма на PHP


Пример реализации я упрощаю до двух php файлов + jquery. Суть решения из него ясна, так что адаптацию для вашего фреймфорка или языка сможете сделать сами.

Листинг файла ajaxCacheChecker.php — этот файл мы и будем запрашивать дважды
  1. <?php
  2. $etag = 'cacheChecker';
  3.  
  4. if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $_GET['s'] || trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
  5.         header('HTTP/1.1 304 Not Modified');
  6. } else {
  7.         $maxAge = 60;
  8.        
  9.         header('Last-Modified: ' . gmdate('r', $_GET['s']));
  10.         header('Etag: ' . $etag);
  11.         header('Pragma: private');
  12.         header('Cache-Control: private');
  13.         header("Expires: " . date("r", $_GET['s'] + $maxAge));
  14.        
  15.         echo microtime();
  16. }
  17. ?>


Листинг файла index.php — этот файл как бы и есть наше приложение
  1. <?php $timeStamp = time(); ?>
  2. <html>
  3. <head><script type="text/javascript" src="js/jquery.js"></script></head>
  4. <body>
  5. <div id="cacheCheck">checking cache</div>
  6. <script>
  7.         var cacheCheck1 = "";
  8.         var cacheCheck2 = "";
  9.                
  10.         function checkBrowserCache() {
  11.                          $.get("ajaxCacheChecker.php?s=<?=$timeStamp?>", function(data){
  12.                                  cacheCheck1 = data;
  13.                                  $.get("ajaxCacheChecker.php?s=<?=$timeStamp?>", function(data2){
  14.                                          cacheCheck2 = data2;
  15.                                          checkBrowserCacheResults();
  16.                                  });
  17.                          });                     
  18.         }
  19.  
  20.         function checkBrowserCacheResults() {
  21.                         if (cacheCheck1 != cacheCheck2) {
  22.                                 $('#cacheCheck').text('cache disabled. Please enable browser cache...');
  23.                         } else {
  24.                                 $('#cacheCheck').text('cache enabled!');
  25.                         }
  26.         }
  27.  
  28.         checkBrowserCache();   
  29. </script>                      
  30. </body>
  31. </html>


Недостаток


Решение не работает в Opera и Safari
Если вы знаете, как добавить поддержку этих браузеров — напишите комментарий

Заключение


Надеюсь, что мои изыскания помогут и вам разрешить свои споры с клиентами и пользователями по поводу долго загружающейся страницы.

Данное решение не подразумевает, что проверка будет происходить на каждой странице. Если вы хотите внедрить проверку везде, то используйте логику, приведенную в комментарии товарища maghamed

UPD: cпасибо товарищам tenshi и TheShock за избавление от сессий в алгоритме
UPD2: учтены комментарии товарища zerkms. Найдена ошибка работы в Opera и Safari
Tags:
Hubs:
Total votes 67: ↑59 and ↓8+51
Comments50

Articles