Пользователь
0,0
рейтинг
10 февраля 2015 в 14:56

Разработка → Еще один способ сжатия CSS файлов из песочницы

image


На изображении выше многие увидят известную картину. Так выглядит большинство CSS файлов на продакшене. Мы все стараемся, чтобы наши веб-страницы загружались быстро; для достижения этой цели используем различные инструменты и техники оптимизации загрузки и рендеринга страниц. Об одном, но редко используемом методе, я бы хотел поговорить и рассказать, как мне удалось сократить размер CSS файла почты mail.ru на 180Кб.

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

Далее мы попробуем выжать все соки из этого файла.

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

image

Прошу обратить внимание на имена классов. Наверное, вы уже догадались, о чем пойдет речь — о сокращении длины этих имен. Потому что с приходом БЭМ и других техник написания CSS названия классов стали весьма длинными, а порой неприлично длинными.

Примеры из жизни


Я провел анализ CSS файлов, некоторых популярных ресурсов и подтвердил свое предположение:

image
На изображение указаны классы, встречающиеся в продакшан версиях CSS файлов указанных сайтов

Наверное, никому не надо объяснять значимость скорости первоначальной загрузки страницы и ее влияние на удовлетворенность пользователей, конверсию, посещаемость сайтов. С приходом мобильных девайсов и мобильного интернета эта проблема стоит очень остро. Например, загрузка 40Кб на 4G интернете в среднем займет 700мс, а если рассмотреть 3G, EDGE, GPRS, WiFi в час пик в кафе или метро, то время загрузки значительно увеличится. Каждые сэкономленные килобайты на вес золота.

Если мы боремся за каждый пробел и перенос строки в CSS файлах, беспощадно вырезая их, то почему бы не сжимать названия классов и идентификаторов до двух или трех символов? Ведь вашим пользователям абсолютно не важно, как будет называться класс блока на странице, но им будет очень важна скорость загрузки страницы. Возможно, именно поэтому ребята из Google используют эту технику (на сайте google.com):

image

От слов к делу


Итак, с тем, зачем это нужно, надеюсь, разобрались. Приступим к делу. Первая проблема в том, что мы не можем просто так взять и сократить классы и идентификаторы в CSS файлах, потому что они используются в верстке, шаблонах и JS файлах. Заменив только в одном месте — все поломается. Становится очевидно, что надо заменить названия во всей связке файлов. В своих проектах для минификации, склеивания и прочих таких задач я использую Grunt.js. Эта система сборки является одной из самых популярных мире фронтенд-разработки. Занимаясь беглым поиском плагинов, реализующих такую задачу, я ничего не обнаружил и решил написать свой велосипед плагин.

grunt-revizor


Так родился grunt-revizor. При его написании я столкнулся с несколькими проблемами. В CSS файлах все просто, синтаксис заранее известен, .name или #name, но в других файлах это может выглядеть иначе. Например, в HTML
<div class="name"></div>
, т.е. name уже без точки или в JS файлах
document.getElementById('name')
тоже без #, что усложняет проблему поиска и замены имен. Что наиболее страшно — можно поломать что-нибудь, например, если имя CSS класса будет ".success" и в JS файле у нас будет переменная «success», заменив ее мы поломаем JS код. А этого мы допустить не можем, поэтому пришлось ввести требования к написанию имен, а именно — имя должно оканчиваться на уникальный префикс, который однозначно даст возможность отличить класс от чего либо другого JS, HTML и других файлах. Например, .b-tabs__title-block--, в данном случае префикс '--'.

Пример таска:

grunt.initConfig({
  revizor: {
    options: {
        namePrefix: '__',
        compressFilePrefix: '-min'
    },
    // Найдет файлы: test/css/style1.css, test/css/style2.css, 'test/js/main.js и др...
    src: ['test/css/*.css', 'test/html/*.html', 'test/js/*.js'], 
    dest: 'build/'
  },
});

После запуска этого таска grunt найдет все CSS, HTML и JS файлы, которые соответствуют путям из src, найдет в CSS файлах все имена классов и идентификаторов, оканчивающихся на префикс __, сожмет найденные имена до двух и трех символьных, например .b-tabs--notselected__ -> .zS, после чего сохранит новые файлы, в которых будут заменены все найденные совпадения, и сохранит их в папке build, с именами style1-min.css, index-min.html, main-min.js.

Пример CSS:

/* Original: style1.css */
.b-tabs__title-block-- {
  color: red;
  font-size: 16px;
}
.b-tabs__selected-- {
  font-weight: bold;
}
/* ======================================= */
/* Result: style1-min.css */
.eD {
  color: red;
  font-size: 16px;
}
.rt {
  font-weight: bold;
}

Пример JS:

/* Original: main.js */
var $tabmenu = $('#tabmenu--');
var tabmenu = document.getElementById('tabmenu--');
if ($tabmenu.hasClass('b-tabs__selected--')) {
  $tabmenu.removeClass('b-tabs__title-block--');
};

/* ======================================= */
/* Result: main-min.js */
var $tabmenu = $('#j3');
var tabmenu = document.getElementById('j3');
if ($tabmenu.hasClass('rt')) {
  $tabmenu.removeClass('eD');
};

Такой же принцип и для HTML, template и прочих фалов.

Некоторые особенности плагина:
  • Сначала генерируются 2-х символьные имена. После того, как количество имен перевалит за 2500, начнутся генерироваться 3-х символьные имена;
  • Для генерации имен используются строчные и заглавные буквы латинского алфавита, цифры, символы - и _;
  • Есть проверка на коллизию, т.е. сжатое имя может соответствовать только одному полному имени.


Оптимизации на примерах


Попробуем выяснить потенциальную выгоду такой оптимизации на примере тех же популярных ресурсов. Расскажу, как я буду считать. Конечно же, не буду пропускать CSS файлы через grunt-revizor, потому что в них не используется уникальный префикс. С помощью нехитрого Node файла я буду считать общее количество классов, высчитывать их длину в байтах и из этого высчитывать потенциальный размер файлов. Упрощенная формула выглядит так:

names = ['b-block1','b-block2','b-block3', ....];
saveSize = allNamesSize - (names.length*3)
// allNamesSize - Общая длина всех символов всех найденных классов
// 3 - Итоговое количество символов в сжатом название


Сайт Размер оригинального файла Сжато В процентах
Mail.ru почта (Desktop version) 849 Кб 182,5 Кб 26,4%
hh.ru (Desktop version) два файла 109,8 Кб 30 Кб 27,3%
vk.com (Mobile version) два файла 184,1 Кб 48,5 Кб 26,4%
Яндекс.Такси (Mobile version) 127 Кб 13 Кб 10,3%
2gis.ru (Mobile version) 1293 Кб 172 Кб 13,3%

Использовались обычные файлы, не gzip. Данные оптимизации примерные, потому что по мимо CSS файлов стили иногда были в html странице, соответственно, здесь не учитывались. Использовалась простенькая регулярка для парсинга, которая искала только классы, притом не все возможные, и она не искала идентификаторы. Помимо сжатия CSS будет выигрыш на других файлах, html, шаблонах и т.д., которые здесь тоже не учтены. Отмечу сразу, что некоторые файлы мало подаются такой оптимизации, например, файлы где мало классов или используются короткие имена, или много изображений, вставленных через data:URL, что демонстрируется на файлах 2gis и Яндекс.Такси.

Заключение


Конечно же, я не придумал ничего нового. Этот способ знаком многим, но он используется редко, т.к. в нем есть как минусы, так и плюсы. Например, он вносит трудности в разработку, чистоту кода и т.д. По большому счету gzip частично решает проблему длинных имен и здорово сжимает файлы, но все же определенный выигрыш в размере и времени декомпрессии файлов можно получить и с использованием gzip. Например, оптимизированный сжатый файл mail.ru на 20Кб меньше того же не оптимизированного сжатого файла.

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

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

В общем, есть о чем поговорить и над чем задуматься.

UDP: Скоро отвечу на все вопросы, приведу конкретные файлы, и сравню выигрыш при использование GZIP.
@atrolov
карма
11,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (79)

  • +2
    Скажите, почему, если mail.ru экономит трафик, он не включает на своих серверах SPDY? Там, в конце концов, много вкусной компрессии и параллелизации из коробки.
    • +32
      Ой, вы так пошутили? Просто они же недавно писали о том, что наконец включили keep-alive.
    • 0
      А уже и смысла особого нет, гугл отказывается от поддержки SPDY.
      • +8
        … в пользу http/2 который является развитием идей spdy. Ок, пусть включают http/2.
  • +33
    А вы проверяли, на сколько сильно сокращается вес, после использования gzip?
    • +1
      Если я правильно понял автора:
      Например, оптимизированный сжатый файл mail.ru на 20Кб меньше того же не оптимизированного сжатого файла.

      • –1
        К я написал в заключении, выигрыш оптимизированного файла при использование gzip, на файле mail.ru составил 20Кб, сжимал через 7zip на стандартных настройках. Но я бы еще обратил бы внимание на время декомпрессии, на desktop'ах оно скорее всего ничтожно мало, но на каких нибудь стареньких андроид аппаратах, оно более ощущаемое, у меня нет конкретных цифр, это всего лишь предположение, но в планах провести конкретный анализ.
        • +2
          > на файле mail.ru составил 20Кб,
          А на остальных не сказали. И файлов не представили, чтобы можно было самим протестировать.

          > через 7zip на стандартных настройках
          На стандартных настройках у 7zip не gzip.
        • +12
          Короче выигрыш, грубо говоря, 10%, и то на хардкорном БЭМ. А проблем по понятным причинам — куча.
          Так что считаю что если вы не гугл — не стоит свеч. И чем дальше в будущее — тем больше не стоит.
        • +1
          на самом деле я чета не очень верю в 10% этих на gzip-е. если оно в plain вон дает 26. пробовать лень) так что если вас не затруднит — добавьте пожалуйста чуть расширенную табличку. вообще странно что там не было сразу gzip-а. это вроде как первое о чем вы должны были подумать.
          also, по ресурсам на старых андроидах — ерунда
        • +33
          Вы как-то не правильно мерили. Я специально скачал ваш плагин и измерил размер до и после css с сайта mail.ru:
          80K mail-min.css
          16K mail-min.css.gz
          98K mail.css
          16K mail.css.gz
          

          Выходит выигрыш 16кб без gzip. Вам стоит разобраться с тем, как работает сжатие, в частности алгоритм Хаффмана и математическое — эти алгоритмы лежат в основе zip, на сколько мне известно. И тогда вам станет понятно, что вы просто делаете работу архиватора.
          • +3
            о, вот и не поленившийся человек)
            я думаю там не совсем ровно получилось. чуть-чуть можно все-таки сэкономить, чисто алгоритмически. процент хотя-бы, не?
            • +5
              Ну чу-чуть там есть превосходство. Дело в том, что нужно хранить то, по чему восстанавливается сжатый текст:
              15950  mail-min.css.gz
              16390  mail.css.gz
              

              То есть 3% выигрыш есть, да. Только как пишут ниже, такая проблема в принципе может быть только у БЭМ-подобной методологии, где названия классов могут быть невероятно большими.
              PS попробовал сжать с лучшей степенью (флаг -9), оба файла стали весить на ~100байт меньше
              • 0
                А если вместо -9 использовать Zopfli все таки речь идет об оптимизации, так почему же не оптимизировать всеми возможными способами?
    • –3
      Предположу, что размер файла в gzip может даже оказаться больше, чем до сокращения имён классов
      • 0
        А почему заминусовали?
        У меня получилось именно так.
        • 0
          можно пример?
          • 0
            пример с цифрами на один коммент ниже.
            Насколько помню, там было несколько тысяч словарей. Коррекция заключалась в том, что имена ключей (осмысленные) заменили на односимвольные.
            • 0
              Может вы еще дополнительно записали словарь, по которому ключи восстановить?
              Просто если у вас есть допустим постоянно повторяющаяся строка key и вы ее меняете на k, то по сути ничего не изменится, кроме того, что словарь для восстановления сжатых данных будет весить на 2 байта меньше. А если вы еще и key запишите где-то 1 раз, то он собственно не пожмется нормально, тк встречатеся только 1 раз.
              • 0
                а зачем их восстанавливать? Оно было целиком под нашим контролем. Как только выкатили в проду — и пофигу, что там написано, читать этот JSON человеком не предполагалось.
                Другое дело, что — как написал выше — никакого ровно эффекта это не дало, так что, решили отказаться.
    • +1
      Я проверял, правда, не на css.
      На одном из проектов на старте грузился массивный JSON, около 200 kb (20 с чем-то кил после gzip). Там, в принципе, тоже самое — можно имена переменных все порезать… Попробовали.
      так вот gzipнутый вариант после обработки получился на пару сотен байт больше!
      но даже если бы был и меньше на столько же — смысла не было никакого.
      допускаю, что надо проверять в каждом случае отдельно.
      • 0
        JSON генерировался каждый раз, или был статический? Если каждый раз, то была бы меньше загрузка CPU из-за уменьшения объёма файла для сжатия.
        • 0
          условно статический — он регенерился асинхронно, параллельным процессом.
          емнип — раз в 10 минут.
          После трамбовался с максимальным сжатием, а nginx отдавал уже готовый gz как статику.
  • +36
    Вангую что после gzip разница будет не так значительна.
  • +10
    А зачем удаляют символы новых строк, если есть gzip?
    • 0
      Потому, что одно другому не помеха.
      • 0
        не помеха, но с gzip оно бессмысленно.
        • +8
          От удаления 0D 0A cловарь архиватора сокращается -> профит.

          А замена ВасяПупкинский на Вася по всему файлу для архиватора монопенисуальна.
        • 0
  • +1
    Каким образом идентификаторы ищутся в HTML и JS-файлах? Например, если у меня используется AngularJS, оно поймет?

    <div ng-class="{'some_very_long_class_name': ctrl.expression}">...</div>
    
    • +5
      А еще сам себе злобный разработчик может склеивать имя класса по частям.
      • +9
        Да, у нас частенько используется такое:

        <span class="glyphicon glyphicon-{{item.icon}}"></span>
        

        В общем, я могу представить себе всего 2 варианта того, как производится замена идентификаторов в побочных файлах — тупой string.replace или умный, учитывающий структуру файла. Оба варианта очень просто напрочь разломать неосторожным движением влево-вправо.
    • 0
      Для этого используется постфикс(как подсказали ниже), например ваш класс будет уже some_very_long_class_name--, тогда регулярка типа /'[A-Za-z0-9_-]+--'/g сможет найти его html, js и других файлах, и если в ваших css файлах был такой класс, то она его заменит на сжатый вариант, если не было, то трогать не будет, таким образом ничего поломаться не должно.
      • 0
        Постдекремент в js отменили? Почему у вас такой странный постфикс?
  • –18
    Считать байты в наш век гигабитного интернета как-то глупо.
    • +8
      Гигабитный интернет, на мобильном, в толстостенной поликлиннике, где даже 3G не пробивает стены, ага.
      • –1
        О как точно вы все описали. Почему то в таких местах, где большие очереди, интернет как раз таки нормально и не работает.
        • 0
          Возможно, именно потому, что большие очереди и большой спрос на связь.
          • 0
            Ключевое слово тут «толстостенные». Не думаю что в очереди в поликлинике или в паспортном столе настолько большая нагрузка на базовые станции.
            • 0
              Думаю, здесь важны обе причины, но та, что назвали вы, — важнее.
    • +2
      Марина Широчкина уже давно проповедует «глупые» принципы, посмотрите
    • 0
      На территории Украины местная Большая Тройка операторов мобильной связи не имеет лицензий на 3G.
  • +13
    1. Префикс — %any%_original_string. Постфикс — original_string_%any%.
    Например, .b-tabs__title-block--, в данном случае префикс '--'
    Как бы немного не корректно.

    2. Как было сказано неоднократно выше — gzip vs usability = gzip win.

    3. Парсинг классов в вашем контексте — дело жутко не благодарное. Я бы сказал, даже слабо тривиальное. А поиск дальнейших возможных ошибок — даже думать не хочется.

    4. Вы ответственно подошли к этому вопросу, и это чертовски здорово! Но, для себя вынес одну мысль «Да, надо следить за длинной классов изначально раз уж на то пошло, и сжатие — наше всё»
  • +4
    Очень опасненько. К слову про эту технику на фейсбук-конфе рассказывали. Но опасненько, конечно. Да и дебаг в проде усложняет.
  • 0
    Решение коллизий это хорошо, но правильно ли я понял что он решает их только при преобразовании? короткие имена не редкость в js. Сможет ли ваше решение перед переименованием определить встречаеться ли замена в остальном коде?
  • +6
    При gzip это не даст большого выигрыша вообще, серъезно.
    Возможно с БЭМ будет чуть лучше.

    зато добавит:
    • геморра при отладке
    • гемора при сборке
    • потенциально трудно отлавливаемые глюки с js


    Пример — в своих проектах у нас максимальная длина имен CSS в районе 5-8 символов.
    Можно посчитать примерно, что это сократит на 4 символа имя, если принять, что с каждого имени экономим 4 байта и в css оно встречается 2 раза и то, что имя встречается обычно в дом 1 раз, и в среднем 100 классов на странице — это даст 4 * 3 = 1200 байт без учета гзипа, стоит ли оно того?
  • +4
    У вас БЭМ неправильный: отражать вложенность в именах элементов не нужно! Уже тут можно не слабо сэкономить.
  • +8
    «Ok, team, css сжали. А теперь давайте подключим AJAX-библиотеку весом в несколько десятков Мб!»

    Серьезно, современные сайты перегружены скриптами до невозможности. Невозможности работы с ними с мобильных устройств. На фоне этого сжатие css не выглядит решением проблемы.
  • 0
    А что, если использовать в классе «i» («i--»), который можно встретить в циклах вроде while? Ситуация, конечно, больше синтетическая, но я просто оставлю это на заметку здесь.
  • 0
    Странно читать в комментариях столько скепсиса и критики данного подхода. На самом деле идея очень хорошая и, действительно, Гуглом активно используется. Но, как многие заметили, в программном коде порой названия классов формируются динамически и этот случай ваш плагин никак не распознает. Поэтому универсального плагина, сокращающего названия css-классов, сделать не получится.

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

    Наличие zip-сжатия с данным методом не вступает в противоречие, т.к. zip сжимает еще много чего, для него работа все равно останется. А вот для владельцев сайтов на виртуальных хостингах, где zip-сжатия обычно нет, этот подход пригодился бы.

    «Считать байты в наш век гигабитного интернета как-то глупо» — да, это верно. Но мобильный Интернет еще далек от века гигабитных технологий. А через мобильные устройства сегодня в Рунете делается каждый четвертый хит.
    • 0
      А вот для владельцев сайтов на виртуальных хостингах, где zip-сжатия обычно нет, этот подход пригодился бы

      Вы серьезно? Этот подход возможно поможет такому гиганту, как google, экономить 0.5кб на запрос, но никак не сайтам, которые хостятся на шаредах. Гуглу нужно экономить трафик, а на шаредах вордпресс и непожатый даже минификатором css.
      • 0
        На виртуальном хостинге это позволит сэкономить время загрузки страницы. Может вы живете в какой-то другой Москве, но на моем Мегафоновском 3G сайты грузятся, как улитки. А по вечерам часто Интернета вообще нет. Т.е. он как бы есть, но его нет :)
        • +2
          Ну уж если честно, если на виртуальном хостинге нет GZIP, может подумать о том, чтобы сменить такой хостинг? А то как в анекдоте — у нас есть буквы Ж О П и А, давайте делать из них слово СЧАСТЬЕ!

          Окей, даже если не менять, сделать скрипт, который будет на ходу сжимать гзипом и складывать в статику и потом отдавать из нее элементарно на любом языке (некий динамик кэш).

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

          И как написали выше — ога 1.5 кб сэкономили и засобачили изображение или библиотечку метра на 1.5.

          Экономия то на спичках получается.
          • 0
            Согласитесь, что вы занимаетесь передергиванием. Конечно, сжатие css нужно не всем. Конечно глупо сжимать css и одновременно подгружать не оптимизированные изображения и т.п. Я согласен. Но ведь есть люди, кому это нужно, кто уже много чего оптимизировал, но все равно пытается выжать максимум там, где это еще возможно. А рассуждения о том, насколько значимы спасенные 1.5Кб — это чисто субъективный момент, у каждого на это свой взгляд.

            И не стоит всех пользователей виртуального хостинга ровнять под одну гребенку. Если твой сайт на виртуальном хостинге, это не значит, что ты не думаешь о производительности и непременно подгружаешь «изображения или библиотечку метра на 1.5».

            Подгружать скриптом заранее сжатый zip-ом статический файл я бы точно не стал. Уж лучше тогда оставить без zip-сжатия. Виртуальных же хостингов с нормальных zip-сжатием я, признаюсь, не встречал.
            • 0
              Я ничего не передергивал — посмотрите большинство проектов, что и как грузится — очень много интересного откроете для себя.

              Если люди хотят выжать максимум не взирая ни на что, ради забавы или рекордов — быть может.

              Если же люди заморачиваются с этим ради продакшена (я хайлоад начал мучать около 4 лет назад — и неплохо о чем народ там думает) — они используют технологии, думая не только о байтах, а комплексно и уж точно не будут променивать 1.5 килобайта ради кучи геморроя — поверьте.

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

              >Подгружать скриптом заранее сжатый zip-ом статический файл я бы точно не стал.

              О, а отсюда по-подробней, почему-это? Так делают почти все. Причем у кого-то это динамически жмется (в момент первого обращения — как я Вам и говорил), а у кого-то сборщиками при выкладывании на продашен (тем-же Grunt-ом например).
              И реализовать это можно даже если у Вас на виртуалке отключен ZIP.
              • 0
                А ну и самое главное — сжатие и минимизации всего что можно сжать и минимизировать нужна ВСЕМ. Так Вы заботитесь о своих пользователях, давая им максимум удобства и информации в максимально малый промежуток времени.
                Часть из этого делается элементарно — та-же стандартная минимизация CSS и JS и их склеивание + GZIP — и делать этот минимум нужно ВСЕГДА.

                Быстрый сайт — это сайт, которым приятно пользоваться, это залог того, что клиенты будут Вашими (по статистике, люди уходят с сайта, грузящегося более 3.5-4 секунд — имеется ввиду время от набора адреса и до появления хотя-бы части контента).

                Причем сделать это можно практически не напрягаясь и на лету.

                Хотя да, если Вам плевать на своих клиентов и на проект и чтобы он «лишь бы был» — то таки да, не заморачивайтесь!
              • 0
                Ладно, я вас понял. Я не хочу более спорить, т.к. этот спор заходит в тупик.

                > И реализовать это можно даже если у Вас на виртуалке отключен ZIP.

                Я хотел бы уточнить насчет предлагаемого вами метода предварительного gzip-сжатия. Как это можно сделать в рамках виртуального хостинга?

                К примеру, мне нужно раздавать сжатый gzip-ом css-файл. Насколько я понимаю, я не могу просто так взять и сослаться на этот файл из html-кода. Чтобы браузер корректно налету распаковал этот архив, нужно послать ему (браузеру) http-заголовок «Content-Encoding: gzip». Это можно легко сделать через, к примеру, php-скрипт, который загрузит с диска сжатый файл, добавит на выход недостающий http-заголовок и далее пошлет файл клиенту. Но php-скрипт для раздачи статики — это уж совсем как-то не рационально.

                Что мне нужно сделать, чтобы мой статический сжатый gzip-ом файл отдавался бы напрямую клиенту с нужным http-заголовком? Проблема актуальна именно для виртуального хостинга, где нет доступа к настройкам веб-сервера.
                • 0
                  По моему очевидное отрицать глупо. Или у Вас аргументы есть? :)

                  Алгоритм:

                  Делается директория, в которой лежат сжатые и не сжатые файлы, к сжатым в конце добавлено расширение .gz (ну или любое другое, главное чтобы оно было одинаково и Вы потом указали правильно content-encoding).

                  Далее с помощью modrewrite и .htaccess определяется лезут ли к файлам, которые могут быть сжаты и есть ли поддержка gzip у клиента.

                  Если есть — отдаем сжатый файл и выставляем соотвественно content-encoding, если нет — не сжатый.

                  При первоначальном запуске при попытке отдать сжатый файл проверяем его наличие — если нет — дергаем скрипт (например на php), который сожмет его и добавив определенное расширение (gz) положит рядом с несжатым и отдаст его клиенту — это если автоматом, а если нет, то при выкате на продакшен преджимаем нужные файлы и кладем их рядом с несжатыми, опять добавив то самое расширение.

                  Это для Apache, если Nginx, то немного по другому.
                  • 0
                    А, да в режиме автомата, чтобы не заморачиваться проверкой в скрипте на поддержку клиентом gzip-а, после того как сжали и положили файл, отдайте клиенту несжатый — и все — пусть первый раз будет так.

                    В следующий раз, когда он обновит страничку, ему придет уже сжатый файл и все будет ок.
                  • 0
                    > По моему очевидное отрицать глупо. Или у Вас аргументы есть? :)

                    Я не отрицаю очевидное. Вы пишете, что сжатие имен css-классов мало кому нужно. Я с вами абсолютно согласен. Но кому-то это нужно и с этим ничего не поделаешь. Я не понимаю сути спора.

                    > отдаем сжатый файл и выставляем соотвественно content-encoding

                    Как вы меняете content-encoding через htaccess?
                    • 0
                      Вообще, я говорил и спорил не про сжатие имен css-классов, а про сжатие CSS вообще — что оно необходимо всегда. Однако, данный вариант сжатия поражает кучу геморроя, а профит дает небольшой — в нем я особого смысла не вижу.

                      Видимо не поняли друг-друга. Окей, замяли.

                      По-поводу content-encoding:

                      Header set Content-Encoding: gzip
                      • 0
                        Спасибо за «Header set Content-Encoding: gzip». Я слышал что-то об этом, но думал, что апачевский модуль Header, который нужен для выполнения данной инструкции, не включен по умолчанию на большинстве хостингов. А сейчас проверил на нескольких — везде работает. Теперь буду пользоваться!
  • +2
    Давно пользуюсь Closure Stylesheets, выигрыш получается не меньший.
    • 0
      sass умеет все тоже, только без java
  • 0
    Автор, вы не пробовали делать название классов короче?

    А что если в шаблонизаторе класс динамически высчитывается? например:

    <div class="element-#{element.status}" >
    
    • 0
      По идее все эти вещи должны выполняться на этапе постпроцессинга темплейтов, когда все строки и т.д. интерполированы и т.д. По сути генерятся рулы о том какие классы в каком случае трансформировать.

      Но если вы не гугл/фэйсбук и для вас не так важно сэкономить пол килобайта на запрос, то gzip эффективнее
      • +3
        Как насчет:
        <div class="profile-#{user.gender}-picture">
        <!-- user.gender - хранится в базе данных -->
        


        Готовый html будет выглядеть так:

        <!-- для мальчиков -->
        <div class="profile-male-picture"> ... </div>
        
        <!-- для девочек -->
        <div class="profile-female-picture"> ... </div>
        

        • 0
          и? Когда у вас будет сформирован HTML — все переходит в какой-нибудь мидлвэр который проходит по всему DOM дереву и заменяет все на минифицированную версию. Возможны какие-то оптимизации, генерация XSLT и т.д. но суть остается та же. Ну а сверху уже можно реверс прокси кэш прикрутить.

          Если это добро потом хэндлится на клиенте — ну тут другой вопрос.
          • 0
            Препроцессинг это хорошо, но в большинстве современных фреймворков такой код и уйдет в продакшн.
            • 0
              Я говорил о постпроцессинге вывода. И тут никакой привязки к фреймворкам нет — можно это даже в виде модуля для nginx запилить.
  • –1
    Пожалуй этот метод можно применять для обсфукации, с целью защиты от кражи, например.
  • 0
    Кто б еще Мегафону рассказал как верстать письма для отчета.
  • +6
    Правильно ли я понимаю, что вы сравнивали на несжатых файлах эффект от вашего подхода?

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

    Если передавать отдельно страницу с ужасными по длине селекторами, и отдельно файл стилей к ней, картина будет чуть менее красивой, но все равно в коде страниц селекторы сожмутся, в тексте css все что можно тоже словарно сожмется — тоже получится неплохо.

    А теперь предлагаю вам подумать чуть шире: когда вы жмете страницу размером 50 Кб, и ужимаете ее до 10 Кб, то на передачу ее клиенту уйдет сколько-то информационных пакетов. Пакеты эти содержат по некоторому количеству полезной нагрузки, плюс накладные расходы. Так вот надо понимать, что ужав страницу не до 10, а до 9.9 Кб, можно испытать чувство радости от уменьшения величины, но число пакетов может измениться, а может и нет — это вопрос кратности числа 10 или 9.9 и размера полезной нагрузки на пакет. И вот во втором случае выигрыш клиента будет совсем небольшой.

    Я к тому, что точить напильником — дело хорошее. Но стоит ли овчинка выделки — нужно решать в каждом случае, и принимать решение, глядя на эти выводы. Грубо говоря, если передача полукилобайта данных не разоряет клиента, может, и не гродить огород, а просто gzip-ом пользоваться, должным образом Expire выставлять (и применять прочие техники улучшения кеширования), применять SPDY и прочие улучшения HTTP — и ориентироваться в оптимизациях именно на эти техники?

    Потому что, простите, когда в код среднего сайта залезаешь, и видишь в нем подключение 20 файликов css, 15 файликов js, зачем-то еще загрузку шрифтов, зачем-то загрузку jquery с неизвестной cdn, да еще приписки вида "?67328157" в конце имени каждого файлика — понимаешь, что все вот это хозяйство и тормозит загрузку, и забивает канал… А вебмастеру пофиг, т.к. сайт он сдал, а заказчику наплел, что это у него хостинг тормозит.
  • +2
    Сlosure Stylesheets — тот самый инструмент, который использует Google

    Также есть Munch
  • 0
    Метод сам по себе интересный, но в цифрах явная ложь.

    2gis css в gzip весит 261 кб, и из них 180 это картинки в base64 — даже если все класснеймы удалить, меньше 180 не будет даже в gzip. Без него будет больше.

    Ну и нет никакой мобильной версии 2gis Online)
    • 0
      Получается 240 кб против 261, причем в моя грязная регулярка удалила (а не заменила) не только все класснеймы вместе с открывающими скобками, но и некоторые свойства.
  • 0
    Если посмотреть на имена классов и имена идентификаторов, то мы видим в них структуру. Но если смотреть также на весь css, то он тоже подлежит определенной структуре. Да и имена свойств тоже строго определенные (width, а не wdith).
    В Microsoft Research чуваки занимались тем, что минимизировали объем передаваемой информации благодаря тому, что хранили бинарное представление AST-дерева JS-кода.
    Но то же самое можно сделать и с css. Т.е. можно написать такой упаковщик-распаковщик css, который будет резко снижать объемы css-трафика за счет превращения css в бинарный формат данных. Если кто не понял — gzip не может упаковать данные меньше чем специализированный упаковщик.
  • 0
    clubs.ya.ru/bem/replies.xml?item_no=746 — уже были идеи сделать нормальный обфускатор для нужд фронтенда, но ничего, по-моему, не выжило. Ну и gzip, мне кажется, победил за счет в разы меньших трудозатрат.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.