Ресурсы в архиве или как уменьшить количество подгружаемых файлов

от автора

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

Очень часто веб-разработчики сталкиваются с проблемой большого количества мелких файлов. Картинки, скрипты, css — неудобно, все дела. Нужно как-то бороться с этим. import, спрайты, блаблабла — это хорошо, но можно попробовать и иначе. Мой вариант — упаковка всех необходимых ресурсов в архив на стороне сервера(реализация — на php), получение данных на клиенте, установка ресурсов в нужных местах.

Проблемы на данный момент: не придумал толком, как кешировать полученный архив, таким способом не стоит паковать динамический контент или большие файлы.
Для распаковки архива на клиенте использована библиотека , для удобства — jQuery.

Итак, посмотрим на код.

ziplogic.php:

class ZipLogic extends ZipArchive{         public $filename;         public function __construct() {             $filename = "current/latest.zip";             $this->filename = $filename;             if(file_exists($filename))                                 unlink($filename);                          if ($this->open($filename, ZIPARCHIVE::CREATE)!==TRUE) {                 $error = error_get_last();                 echo $error["message"];                 return null;             }         }                  public function pack($url){             $this->addFile($url);         }     } 

Этот класс наследуется от ZipArchive и нужен только для чуть более удобной работы с архивом.

Теперь — код для упаковки нужных ресурсов:

index.php:

    include "ziplogic.php";     $zpack = new ZipLogic();     if($zpack==null)     {         echo 'wrong data';         return;     }     $zpack->pack('img/screen.png');     $zpack->pack('img/screen_1.png');     $zpack->pack('img/screen_2.png');     $zpack->pack('css/alotofstyles.css');     $zpack->pack('js/cooljs.js');     $zpack->close();     include 'content.html'; 

Тут, собственно, тоже нет ничего особо интересного: создаем объект ZipLogic, перечисляем все ссылки на ресурсы, которые нужно упаковать, закрываем объект, подключаем конечную html’ку. В результате в папке current создается архив latest.zip, который содержит в себе все нужные ресурсы(см. ziplogic.php).
По хорошему, использовать его нужно перед публикацией страницы, каждый раз генерировать нет смысла.

Ну и на закуску — сама html’ка. Верстку не критиковать, пожалуйста — ее здесь нет.

content.html:

<script src="js/jquery-1.9.1.js"></script> <script src="js/jszip.min.js"></script>  <link type="text/css" zpack="css/alotofstyles.css" rel="stylesheet"> <script zpack="js/cooljs.js"></script> <style>     body{margin: 0;} </style>  <div id="loader" style="position: absolute; width: 100%; height: 100%;background: rgba(148, 148, 148, 1);">     <img src="" style="         position: relative;         top: 50%;         left: 50%;         height: 25px;         width: 250px;         margin-left: -125px;         margin-top: -12.5px;     "> </div>   <img zpack="img/screen.png"/> <img zpack="img/screen_1.png"/> <img zpack="img/screen_2.png"/>  <script>     function getBinary(url, callback){         var oReq = new XMLHttpRequest();         oReq.open("GET", url, true);         oReq.responseType = "arraybuffer";          oReq.onload = function (oEvent) {           var arrayBuffer = oReq.response;           if (arrayBuffer) {             var byteArray = new Uint8Array(arrayBuffer);             callback(byteArray);           }         };          oReq.send(null);        }          function unpackResources(data){         var pack = new JSZip();         pack.load(data);                  $.each(pack.files, function(k, v){             var blob = new Blob([pack.file(k).asArrayBuffer()], {type: 'application/octet-binary'});             var url = URL.createObjectURL(blob);             $('[zpack="'+k+'"').each(function(){                 switch($(this).prop("tagName").toLowerCase())                 {                     case 'img' :                         $(this).attr('src', url);                         break;                     case 'script' :                         $(this).attr('src', url);                         break;                        case 'link' :                         $(this).attr('href', url);                         break;                       case 'a' :                         $(this).attr('href', url);                         break;                                            }              });         });     }          $(document).ready(function(){         getBinary('current/latest.zip', function(data){                 unpackResources(data);                 $('#loader').hide();         });     }); </script> 

Тут стоит описать чуть подробнее.
Функция getBinary, если не ошибаюсь, честно сперта со stackoverflow. Скачивает архив и передает полученный массив байт в callback.
Функция unpackResources, собственно, и делает основную часть работы: обрабатывает содержимое архива, вытаскивает пути, находит все элементы, ресурсы в которых помечены через zpack, создает соотв. blob и подгружает его в нужный элемент.
Пока все это добро не подгрузится, висит загрузчик.

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

Спасибо за внимание, комментарии и идеи крайне приветствуются, критика без использования слов «идиот» и «криворукий ламер» — тоже.

ссылка на оригинал статьи http://habrahabr.ru/post/232823/


Комментарии

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

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