Хабрахабр

[Из песочницы] Сохранение JS и CSS ресурсов в Локальном хранилище браузера

Вопрос, стоит ли хранить javascript и css ресурсы веб-страницы в LocalStorage браузера или позволить ему самому отрабатывать кэширование, не имеет однозначного ответа. Есть плюсы и минусы. С моей точки зрения, основной плюс — скорость загрузки — перевешивает все остальное. Это очень хорошо чувствуют пользователи EDGE и 3G.

Затем советую зайти на что-нибудь типа pingdom.com и увидеть, что непосредственно передача данных во всем времени исполнения запроса занимает проценты. Для поклонников стандартного кэша браузеров, гордо показывающих на слово «Кэшировано» в Средствах разработчика, советую открыть Fiddler и увидеть, что по каждому кэшированному ресурсу за 304 HTTP ответом всё равно идет запрос. То есть толку в абсолютном значении от такого кэширования — кот наплакал, особенно если файлы небольшие.

Предлагаемая схема хранения ресурсов в LocalStorage достаточно проста.

При его изменении ресурс перегружается в локальное хранилище. Во-первых, реализовано отслеживание изменения файлов, для этого используется время последнего изменения файла как его «версия».

Ресурс линкуется следующим образом:

<script type="text/javascript"> <?php include("ls.js"); ?> requireResource( 'mobile.css', 'css', '<?php echo filemtime(__DIR__ . "/css/mobile.css") ?>', '<?php echo "/css/mobile.css?" . filemtime(__DIR__ . "/css/mobile.css") ?>'); </script>

Функции requireResource передается название ресурса (под этим именем он пойдет в локальное хранилище), тип, версия и url ресурса. Логика кода ls.js простая — если ресурс есть в хранилище и версия его совпадает с указанной — инлайнится он. Если нет — грузится заново, помещается в хранилище и инлайнится в HTML код.

function _cacheResource(name, t, version, url) )); } else { console.warn('error loading '+url); } } } xmlhttp.open("GET", url, true); xmlhttp.send(); } function _loadResource(url, type, name, version, callback) { if (type == "js") { document.write('<script id="' + name + '" src="', url, '"><\/script>\n'); } else if (type == "css") { document.write('<link id="' + name + '" rel="stylesheet" href="', url, '" />\n'); } var s = document.getElementById(name); if (s.readyState) { //IE s.onreadystatechange = function() { if (s.readyState == "loaded" || s.readyState == "complete") { s.onreadystatechange = null; _cacheResource(name, type, version, url); if (callback) callback(); } }; } else { //Others s.onload = function() { _cacheResource(name, type, version, url); if (callback) callback(); }; } } function _injectResource(content, url, name, version, callback) { var c = JSON.parse(content); // cached version is not the request version, clear the cache, this will trigger a reload next time if (c.version != version) { localStorage.removeItem(name); _loadResource(url, c.type, name, version, callback); return; } if (c.type == "js") { var s = document.createElement('script'); s.type = "text/javascript"; } else if (c.type == "css") { var s = document.createElement('style'); s.type = "text/css"; } var scriptContent = document.createTextNode(c.content); s.appendChild(scriptContent); document.getElementsByTagName("head")[0].appendChild(s); if (callback) callback();
} function requireResource(name, type, version, url, callback) { var c = localStorage.getItem(name); if (c == null) { _loadResource(url, type, name, version, callback); } else { _injectResource(c, url, name, version, callback); }
}

Есть выбор как инлайнить код — или через document.write(); или через вставку элемента в DOM. В первом случае мы получаем копию того, как если бы ресурс подцеплялся самой страницей. Второй, в свою очередь, логически более правильный, но есть минусы — js код не исполняется, например. Нужно в ручном режиме проводить инициализацию — что несложно, но нужно об этом помнить.

Если нужен определенный порядок, это нужно предусмотреть — или компоновкой ресурсов в этом порядке в один файл, или синхронной загрузкой. Еще один момент — очередность загрузки ресурсов.

В принципе, можно расширить на всё, что можно сериализовать в локальное хранилище браузера. В данном примере используется 2 типа ресурсов — js и css.

Сайт открывается ощутимо быстрей. Результат очевиден — мои css и js файлы больше в Средствах разработки браузера и Fiddler'e не появляются (если не происходит их обновление на сервере). А на девелопмент машине все js и css файлы грузятся по отдельности для удобства работы. Процесс js и css дебага на продакшне затрудняется не сильно.

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

Основа js кода взята с GitHub и доработана.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»