Drupal 8: Libraries API (Добавление CSS/JS на страницы). Css drupal
Drupal: 5 способов подключить свой CSS стиль
Важно — нужно сбрасывать кэш после подключения стиля любым способом.
1. В .info файле активной темы или модуля
Добавить в .info файл активной темы или модуля строчку:
stylesheets[all][] = styles.cssСтиль styles.css будет подключаться на всех страницах.
Путь к файлу указывается относительно директории .info файла. Например если стиль расположен в поддиректории css, то путь будет — css/styles.css.
Вместо all можно указать любой валидный медиа тип или выражение в виде screen and (max-width: 600px).
2. В файле template.php
Реализовать в template.php активной темы любую preprocess или process ф-ю, в которой вызвать drupal_add_css(). Единственное условие — ф-я должна выполняться до template_process_html(). Например:
function THEMENAME_preprocess_html(&$variables) { drupal_add_css(path_to_theme() . '/styles.css'); }Вместо THEMENAME прописать системное имя темы.
Пример подключения css файла только на страницах нод:
function THEMENAME_preprocess_html(&$variables) { if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) { drupal_add_css(path_to_theme() . '/styles.css'); } }В drupal_add_css(), во втором параметре можно указывать тип подключаемого стиля (локальный файл, внешний файл, инлайн стиль), указать вес стиля относительно других подключаемых файлов, запретить стилю участвовать в агрегации и прописать conditional comments для Internet Explorer-а. Подробности в манах.
3. В файле модуля
Всё что написано во втором способе актуально и для модулей:
function MODULENAME_preprocess_html(&$variables) { drupal_add_css(drupal_get_path('module', 'MODULENAME') . '/styles.css'); }Плюс можно подключить файл в любом хуке, который вызывается до рендеринга страницы:
function MODULENAME_init() { drupal_add_css(drupal_get_path('module', 'MODULENAME') . '/styles.css'); }4. В параметре #attached рендер массива
Например подключить стиль для формы:
$form['#attached']['css'][] = drupal_get_path('module', 'MODULENAME') . '/styles.css';Ещё пример с формой.
5. C помощью модуля CSS Injector
Подробности в посте Модуль CSS Injector — пишем CSS из админки.
Написанное актуально для Drupal 7 Похожие записиxandeadx.ru
Drupal: Подключение своих js и css файлов в Drupal 8
В Drupal 8 немного усложнился процесс подключения своих стилей и скриптов. Теперь все js и css файлы должны быть объединены в так называемые libraries (библиотеки), описаны в файле *.libraries.yml и подключены одним из способов. Начнём по порядку.
Создание файла *.libraries.yml
В файле *.libraries.yml содержится описание всех библиотек модуля или темы, а так же зависимости этих библиотек.
Библиотека (library) это набор js и css файлов, выполняющих определённую функцию. Примеры встроенных в drupal библиотек — core/jquery, core/jquery.ui.dialog, ckeditor/drupal.ckeditor. Библиотека может состоять всего из одного js или css файла и не иметь никаких зависимостей. Подключать отдельные файлы минуя их описание в *.libraries.yml нельзя.
Пример файла *.libraries.yml с описанием библиотеки jquery.ui.dialog:
jquery.ui.dialog: js: jquery.ui.dialog.js: {} css: theme: jquery.ui.dialog.css: {} dependencies: - core/jquery.uiЕсли какие-то стили нужно подключать на каждой странице и их никак не сгруппировать в отдельную библиотеку, то можно описать их под именем global-styling (актуально для тем):
global-styling: css: theme: css/layout.css: {} css/style.css: {} css/colors.css: {}Так же в *.libraries.yml можно указать дополнительные параметры, такие как версия библиотеки, место подключения (шапка/подвал), порядок подключения и т.д. Пример:
mylibrary: version: 1.0 header: true js: mylibrary-min.js: { minified: true } mylibrary-second.js { preprocess: false, attributes: { async: true } } css: theme: https://example.com/externalcss.css: { type: external } mylibrary.css: { weight: 1 } mylibrary-print.css: { media: print }Подробнее в документации.
Подключение библиотек
В своей теме
Чтобы добавить библиотеку на все страницы сайта, нужно в файле темы *.info.yml прописать параметр libraries с именем библиотеки в формате extension_name/library_name:
Чтобы добавить библиотеку только на определённую страницу/страницы, можно воспользоваться препроцессом:
/** * Preprocess function for page.twig.html. */ function themename_preprocess_page(&$vars) { if ($vars['is_front']) { $vars['#attached']['library'][] = 'core/drupal.ajax'; } }Как видно, подключать библиотеки можно простым добавлением в любой рендер-массив параметра #attached. Отдельной функции для подключения, как это было в Drupal 7, больше нет.
Так же подключать библиотеки можно прямо из *.html.twig файла с помощью функции attach_library():
{{ attach_library('modulename/libraryname') }} <div>Some markup {{ message }}</div>В своём модуле
Для модулей есть отдельный хук hook_page_attachments():
/** * Implements hook_page_attachments(). */ function modulename_page_attachments(array &$page) { $page['#attached']['library'][] = 'modulename/libraryname'; }Хотя способ с препроцессом и twig функцией тоже будет работать.
Изменение файлов библиотек
Модули и темы могут добавлять/подменять/удалять файлы чужих библиотек.
Темы это могут сделать из своего *.info.yml файла:
libraries-override: modulename/libraryname: js: # Подмена файла библиотеки filename.js: myfilename.js # Удаление файла библиотеки filename.js: false # Добавление зависимости к чужой библиотеке libraries-extend: modulename/libraryname: - mytheme/mylibraryМодулям доступен вариант с хуком hook_library_info_alter():
/** * Implements hook_library_info_alter(). */ function modulename_library_info_alter(&$libraries, $extension) { if ($extension == 'other_modulename') { // Удаление файла библиотеки unset($libraries['libraryname']['js']['filename.js']); // Добавление файла в библиотеку $filepath = '/' . drupal_get_path('module', 'modulename') . '/filename.js'; $libraries['libraryname']['js'][$filepath] = []; // Подмена файла библиотеки unset($libraries['libraryname']['js']['filename.js']); $filepath = '/' . drupal_get_path('module', 'modulename') . '/myfilename.js'; $libraries['libraryname']['js'][$filepath] = []; // Добавление зависимости $libraries['libraryname']['dependencies'][] = 'modulename/libraryname'; } }Полезные ссылки:— Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 theme— Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 module— CSS file organization (for Drupal 8)— Drupal 8: Libraries API (Добавление CSS/JS на страницы)— Централизованный способ отключить в рантайме определённую библиотеку
xandeadx.ru
Подключение css и js файлов в шаблон темы. Темизируем Drupal 7.
Многие веб мастера, которые работают с Друпал 7, не умеют грамотно подключать в свой шаблон стили и скрипты. Большинство использует не правильный вариант подключения – через испльзование style в файле страниц темы page.tpl.php. Но в Друпал специально для подключения в шаблон стилей и скриптов есть файл под названием «имяТемы.info». Используя этот файл можно ускорить работу вашего сайта, поскольку друпалу не придется сканировать все фалы темы в поисках подключенных файлов.
Для подключения юзаем код:
scripts[] = ваш_файл.js stylesheets[all][] = ваш_файл.cssВ самом файле .info это выглядит примерно так:
При подключении стилей и скриптов посредством использования данного файла, все они будут не только собраны в одном месте, но и кэшированы. Если подключать эти файлы как указано выше, через page.tpl.php, то кэшироваться они не будут.
Подключить файлы в инфо файл не составляет особого труда. Но в случае, если требуется подключить стиль только к одной странице сайта, то в этом случае подключение надо выполнять посредством использования в фале страницы php-кода.
<?php drupal_add_js(drupal_get_path('theme', 'имяТемы') . '/script.js'); ?> <?php drupal_add_css(drupal_get_path('theme', 'имяТемы') . '/style.css'); ?>Оценок: 5 (средняя 5 из 5)
- 5029 просмотров
Понравилась статья? Расскажите о ней друзьям:
Курсы по Drupal (в открытом доступе)
Уровень сложности:
Начальный
Еще интересное
Libraries API (Добавление CSS/JS на страницы) — Niklan
Алоха! Вот и вышел Drupal 8 rc1, самое время начинать учиться кликать, а кому-то кодить. Постепенно буду что-то изучать и попутно писать об этом. Напоминаю что у меня уже есть статья Drupal 8: Изменения API, где у меня в виде сравнения показано как было и как стало. Там, кстати, данная тема также была задета краешком глаза.
Что же мы имеем в Drupal 7? Для добавления JavaScript и CSS файлов мы имели следующие функции: drupal_add_js() и drupal_add_css(). Также мы могли подцепить их через #attached, особо смелые вставляли прямо в *.tpl.php. Что же мы имеем в Drupal 8? Функции были удалены, а вставлять в темплейт всё также можно, но не нужно. Остался вариант с #attached, но он также подвергся небольшим изменениям. И тут мы приходим к Libraries API. Кто работал с Drupal 7, скорее всего сталкивались с его hook_libraries_info() (это был сторонний модуль), при помощи которого мы могли объявлять свои сторонние либы и хранить их удобно в папочке /sites/all/libraries. Теперь примерный функционал в ядре 8-ки, но очень сильно подвергся изменениям и скомбинирован в одно единое решение, и надо заметить, круто.
У нового подхода есть одна киллер-фича, теперь JS либы подгружаются только на тех страницах, где их запросил какой-то модуль/плагин/элемент и т.д. Например, если на странице ни один модуль не подал запрос на jquery, или для его библиотек он не установлен в зависимости, то на этой странице jquery не будет загружаться вообще, тем самым убирая загрузку бесполезных библиотек. Если jQuery, возможно, будет грузиться везде, так как потребуется многим темам, то вот остальные js уже не будут появляться без необходимости.
Этапы
На самом всё очень просто:
- Объявляем библиотеку;
- Подключаем там где она требуется.
Объявление библиотеки
Как и многие "вещи", в Drupal 8 многие конфигурации вынесли в *.yml файлы, и объявление библиотеки не исключение. Кто-то начнет плюваться, кто-то радоваться, но это единственный способ которым можно это сделать. К слову, многие вещи в 8-ки привели к единственному верному решению. Теперь вариативность сводится к минимуму и не надо запоминать разные способы.
Начнем с того что файл с объявлением библиотек(и) можно создавать как в теме, так и в своём модуле. Синтаксис и подход, как я уже сказал, везде теперь одинаковый. Т.е. теперь даже тема может объявлять свои библиотеки, а модули их использовать.
Файл с объявлением библиотек имеет следующее именование *.libraries.yml. Это значит, что если ваш модуль или тема (напоминаю, что теперь не важно кто объявляет) называется helloworld то файл должен называться helloworld.libraries.yml и находиться в корне темы/модуля.
Я буду показывать объявление библиотеки на примере модуля, следовательно, у вас должен быть объявлен модуль в соответствии с новыми требованиями. Можете объявить сами воспользовавшись моим гайдом по созданию hello world модуля в Drupal 8, или прямо оттуда скачать готовый вариант, на котором я буду всё показывать.
Базовый синтаксис
Для начала давайте разберемся с синтаксисом файла, для этого я приведу простой пример и всё что нужно опишу в комментариях:
niklan.net
Работа с CSS и JavaScript в темах Drupal 8
Эта статья значительно расширяет один из разделов поста «Что нового в темах Drupal 8», в котором я лишь вскользь упомянул о библиотеках для управления стилями и скриптами в темах. Однако, это новшество в Drupal 8 стоит того, чтобы его рассмотреть более детально.
В этой статье мы более подробно остановимся на вопросах работы с библиотеками: управлением зависимостями, подключением сторонних библиотек, переопределением или отключением ненужных библиотек.
Создание библиотек
В восьмой версии Drupal фалы стилей и скриптов добаловаться в темы уже совершенно по-новому. Для того, чтобы добавить CSS или JavaScript вам нужно определить их в файле библиотек mytheme.libraries.yml, который должен находиться в корневой директории вашей темы.
Каждая библиотека должна иметь уникальное (в приделах темы) имя, может иметь произвольное количество загружаемых файлов, перечень зависимостей, а также дополнительную информацию нужную для библиотеки.
Давайте посмотрим на такой пример:
# Файл my_theme.libraries.yml # Задаем имя библиотеки. my-library-name: version: "1.0.x" css: # учитываем категории согласно SMACSS методологии. base: # Путь к фалу CSS. assets/css/base.css: {} theme: assets/css/print.css: { media: print } js: assets/js/myglobal.js {} dependencies: - core/jquery # А здесь мы добавим шрифт от Google fonts. lato: css: base: '//fonts.googleapis.com/css?family=Lato': { external: true }Стоит отметить, что формат .yml используется для вех конфигурационных файлов в Drupal 8.
Имя библиотеки
Как я уже упомянул выше мы должны задать уникальное имя для нашей библиотеке в контексте темы или модуля, которые вызывают библиотеку.
Версия
Не обязательно задавать версию для библиотеки, но лучше сделать это. В дальнейшем, вам будет легче поддерживать код. Особенно важно добавлять версию для внешних библиотек, которая будет соответствовать версии источника.
CSS
Все CSS файлы библиотеки описываются внутри секции css, кроме того, их можно разделить на под-категории. Например:
css: # учитываем категории согласно SMACSS методологии. base: # Путь к фалу CSS. assets/css/base.css: {} theme: assets/css/print.css: { media: print }В этом отрывке кода каждый файл указан в свое под-категории. Для того, чтобы детальнее познакомиться с принципами организации CSS стоить взглянуть на документацию по организации CSS Drupal. Вкратце, скажем, что Друпал использует SMACSS методологию организации файлов стилей. Все файлы условно разбиваться на под-категории: base, layout, component, state, и theme. Примечательно то, что независимо от библиотек, файлы стилей подключаются на странице именно в порядке следования этих под-категорий. То есть, файл из секции base одной библиотеки будет загружаться совместно с файлом из этой секции другой библиотеки.
Дополнительные свойства
Дополнительные свойства для CSS файлов могут быть заданы с помощью фигурных скобок после пути к файлу:
theme: assets/css/print.css: { media: print }Здесь мы передаем кастомные медиа-свойства для файла, в данном случае это print, но мы можем задать и другие медиа-свойства, например установить значения минимальной или максимальной ширины, к которой будут применены правила файла.
JavaScript
Файлы .js добавляются в секции js. Для них нет какой-либо дополнительной структуры, но вы можете добавить кастомные свойства в фигурных скобках после пути файла. Например, вы можете указать значение minified: true, чтобы Drupal минифицировал данный файл при агрегации. Также, перед именем файла вы можете указать регион страницы, куда будет загружен файл. По умолчанию Drupal 8 загружает все скрипты в нижнюю часть страницы, но если вам нужно поместить скрипт вверх, то можно указать header: true и скрипт будет помещен в head документа. Вот пример подключения .js файла в библиотеке:
js-header: header: true js: header.js: { minified: true } js-footer: js: footer.js: { minified: true }Зависимости
Здесь все просто. В конце определения вашей библиотеки вы можете добавить секцию, в которой укажите от каких библиотек она зависит и эта библиотека тоже будет добавлена вместе с вашей. Важно, чтобы эта библиотека существовала, и вы правильно указали бы ее имя и путь. Например:
# ... код библиотеки # Объявляем зависимости. dependencies: - core/jqueryВ данном случае мы объявили зависимость от библиотеки jquery, которая была определена модулем core в его файле библиотек core.libraries.yml.
Внешние файлы
Добавить внешний файл в библиотеку очень просто: укажите полный путь к файлу, а в дополнительных свойствах обязательно скажите, что файл внешний { external: true }. Мы уже добавляли таким образом шрифт в коде в начале поста:
# ... код библиотеки # А здесь мы добавим шрифт от Google font. lato: css: base: '//fonts.googleapis.com/css?family=Lato': { external: true }Прикрепляем библиотеки
Если вы просто перечислите ваши библиотеки в mytheme.libraries.yml, то ничего особенного не произойдет. Чтобы Drupal знал о ваших библиотеках, нужно сказать ему какие и как использовать. У вас есть три способа вызова библиотек: подключить библиотеку глобально через mytheme.info.yml, вызвать библиотеку из Twig-шаблона, а также добавить ее через препроцесс-хук. Рассмотри все три способа детальнее.
Прикрепляем библиотеку глобально
В разделе библиотек просто укажите пути и имена библиотек, которые хотите использовать всюду на сайте. Например:
libraries: - core/normalize - mythemename/my-library-nameПрикрепляем библиотеку к файлу шаблона
Лично мне эта возможность очень нравиться, она позволяет реализовать действительно компонентный подход при разработке тем Drupal 8. В Twig-шаблонах предусмотрена специальная функция attach_library(), которая будет вызывать файлы библиотеки только в том случае, если блок, который использует этот шаблон будет выведен на странице. То есть, вы значительно уменьшаете размер загружаемого кода, используете только то, что вам нужно и когда это нужно. Например:
{# В файле Twig-шаблона node--article--full.html.twig. #} {{ attach_library('mythemename/my-library-name') }}Файлы библиотеки буду загружены только на страницах полного вида нод типа article. Просто супер!
Добавляем библиотеку через препроцесс-хук
Для бэк-энд разработчиков, возможно, привычнее будет добавлять библиотеки через PHP. Например:
function mytheme_preprocess_maintenance_page(&$variables) { $variables['#attached']['library'][] = 'mytheme/cuddly-slider'; }Вы можете использовать любые хуки и логику, главное — это добавить свою библиотеку к массиву ['library'].
Дополнительные действия с библиотеками
Поскольку все файлы стилей и .js теперь подключаться с помощью библиотек, это дает дополнительные возможности разработчикам тем для управления библиотеками на уровне темы. Есть два основных действия, которые вы можете совершать с библиотеками: расширять и переписывать, и делается это методами libraries-extend и libraries-override соотвественно.
Расширяем библиотеки
С помощью использования метода libraries-extend внутри вашего инфо-файла темы вы можете прикрепить собственную библиотеку к любой существующей библиотеке. Если библиотека, которую вы хотите расширить загружается типичным способом, без каких-либо дополнительных манипуляций, то сделать это достаточно просто. Например:
# В файле mytheme.info.yml libraries-extend: # Библиотека форума темы Classy загружается только, когда используется шаблон # forums.html.twig # В это же время будут добавляться и файлы вашей библиотеки. classy/forums: - mythemename/forumsВ комментариях к примеру все довольно понятно написано. Файлы вашей библиотеки будут загружать только вместе с файлами расширяемой.
Переписываем библиотеки
Метод libraries-override дает вам еще более мощные инструменты для управления библиотеками. С его помощью вы можете удалять или замещать файлы определенной библиотеки. Давайте рассмотри все более детально на примерах.
Удаляем файл
# В файле mytheme.info.yml libraries-override: # Указываем имя библиотеки. core/jquery.ui: # Перечисляем CSS-файлы. Обязательно в таком порядке! css: # Категория, согласно методологии SMACSS обязательна. theme: # Путь к файлу. Внимание! Этот путь не относительно вашей темы. assets/vendor/jquery.ui/themes/base/theme.css: falseОбратите внимание на комментарии. При отключении CSS-файла вы должны четко придерживаться порядка, как и при его определении. Только путь к файлу библиотеки указывается так же, как он указан в файле определения библиотеки, а не относительно вашей темы или корня сайта. Приставка core/ перед названием библиотеки указывает на модуль, который инициирует данную библиотеку.
Ну и в конце примера вы видите, что мы добавляем false к пути файла. Именно это говорит Drupal, что файл должен быть исключен из библиотеки при ее использовании.
Заменяем файл
Механизм замены похож на механизм удаления, с той лишь разницей, что после пути файла мы указываем имя файла на который хотим заменить текущий. Например:
# В файле mytheme.info.yml libraries-override: system/maintenance: css: theme: # Заменяем файл system.maintenance.css в модуле System собственным файлом. css/system.maintenance.css: css/maintenance.cssЗдесь есть один интересный нюанс. Поскольку мы заменяем файл существующей библиотеки, то наш файл не должен быть определен в каких-либо наших библиотеках. Также при сборке страницы файл будет вставлен именно в то место, где был заменяемый файл.
Заменяем или удаляем всю библиотеку.
Вы можете заменить или удалить целую библиотеку, сделать это очень просто. Например:
# В файле mytheme.info.yml libraries-override: # Заменяем библиотеку messages темы Classy свой собственной. classy/messages: mythemename/messages # Полностью удаляем библиотеку search results темы Classy. classy/search-results: falseПри замене одной библиотеки на другую, их имена и содержимое не обязательно должны соответствовать.
Заключение
Как я уже говорил ранее, Drupal 8 подошел к вопросу разработки фронт-енда очень основательно и глубоко. Фактически система предлагает современные инструменты для гибкой и компонент-ориентированной разработки, которых сегодня не дает ни одна из популярных CMS с открытым исходным кодом. Наша же с вами задача — правильно и удачно использовать эти инструменты. Успехов!
www.master-web.info
Оптимизация JavaScript и CSS-файлов в Drupal
С чего начинается сайт?
- Для браузера сайт начинается с GET-запроса страницы.
- Сервер на этот запрос высылает HTML-код страницы.
- Браузер разбирает код и начинает загрузку всех внешних файлов (JS, CSS, Flash и др.) в порядке их следования в коде.
- Обычно браузер использует не более 2х потоков для загрузки внешних файлов, а CSS и JS загружаются вообще в одном потоке.
- Время на каждый запрос зависит от размера возвращаемого ответа, загрузки сервера и активности на каждой машине на всем пути между браузером и сервером.
- Чем больше размер файла - тем дольше он будет доставляться браузеру.
- Чем больше количество файлов - тем дольше будет загружаться вся страница.
Таким образом, чтобы увеличить скорость загрузки страницы нужно:
- Уменьшить размеры файлов (оптимизировать графику, JS и CSS-файлы)
- Уменьшить количество файлов (картинки объединяются в спрайты, а JS и CSS аггрегируются)
- Использовать HTTP-сжатие
- Увеличить количество хостов, с которых загружается статика сайта, чтобы браузер мог увеличить лимит одновременных соединений
- Поместить JavaScript в footer страницы, чтобы они загружались последними, а пользователь мог уже пользоваться страницей.
Оптимизация графики и создание спрайтов - работа для дизайнера, а мы займемся оптимизацией JavaScript и CSS-файлов в Drupal.Давайте посмотрим как обстоят дела с этими файлами в Drupal.Анализ ситуацииJavaScriptВ вашем проекте количество и суммарный размер будет другой.Pазмер ваших JS-файлов вы можете сами проверить командой:find . -name '*.js' -exec ls -l {} \; | awk '{s+=$5} END {print s}'
В нашем проекте, кроме файлов ядра, есть ещё более 1300(!) JS-файлов, которые находятся в дополнительных модуляx и темах.Общий размер всех JS-файлов - 14'746'899 байт.В ядре Drupal 6 я нашел следующие Javascript-файлы:
- modules/comment/comment.js
- modules/profile/profile.js
- modules/openid/openid.js
- modules/taxonomy/taxonomy.js
- modules/system/system.js
- modules/block/block.js
- modules/color/color.js
- modules/user/user.js
- misc/autocomplete.js
- misc/drupal.js
- misc/collapse.js
- misc/batch.js
- misc/farbtastic/farbtastic.js
- misc/form.js
- misc/tableselect.js
- misc/ahah.js
- misc/tabledrag.js
- misc/textarea.js
- misc/progress.js
- misc/tableheader.js
- misc/teaser.js
- misc/jquery.form.js
- misc/jquery.js
Хорошо, что они не все загрузаются на одной странице, а некоторые вообще не используются. На совести разработчика модуля правильно настроить условия подключения JS и CSS-файлов на странице, чтобы бесполезный код не уменьшал скорость загрузки страницы.CSS-файлыВ вашем проекте количество и суммарный размер будет другой.Команда для самостоятельной проверки размера CSS файлов:find . -name '*.css' -exec ls -l {} \; | awk '{s+=$5} END {print s}'
В нашем проекте, кроме файлов ядра, есть ещё около 450-ти в дополнительных модулях и темах.Общий размер всех CSS-файлов - 1'674'793 байт.Что касается CSS-файлов в ядре Drupal 6, то вот они:
- modules/locale/locale.css
- modules/aggregator/aggregator-rtl.css
- modules/aggregator/aggregator.css
- modules/update/update.css
- modules/update/update-rtl.css
- modules/poll/poll.css
- modules/poll/poll-rtl.css
- modules/comment/comment-rtl.css
- modules/comment/comment.css
- modules/tracker/tracker.css
- modules/forum/forum-rtl.css
- modules/forum/forum.css
- modules/book/book.css
- modules/book/book-rtl.css
- modules/profile/profile.css
- modules/search/search-rtl.css
- modules/search/search.css
- modules/openid/openid.css
- modules/node/node-rtl.css
- modules/node/node.css
- modules/taxonomy/taxonomy.css
- modules/system/system-menus-rtl.css
- modules/system/admin-rtl.css
- modules/system/admin.css
- modules/system/maintenance.css
- modules/system/defaults-rtl.css
- modules/system/defaults.css
- modules/system/system-rtl.css
- modules/system/system-menus.css
- modules/system/system.css
- modules/block/block.css
- modules/color/color.css
- modules/color/color-rtl.css
- modules/help/help.css
- modules/help/help-rtl.css
- modules/dblog/dblog.css
- modules/dblog/dblog-rtl.css
- modules/user/user.css
- modules/user/user-rtl.css
- misc/print-rtl.css
- misc/farbtastic/farbtastic.css
- misc/print.css
- themes/bluemarine/style.css
- themes/bluemarine/style-rtl.css
- themes/garland/print.css
- themes/garland/style.css
- themes/garland/minnelli/minnelli.css
- themes/garland/color/preview.css
- themes/garland/style-rtl.css
- themes/garland/fix-ie.css
- themes/garland/fix-ie-rtl.css
- themes/pushbutton/style.css
- themes/pushbutton/style-rtl.css
- themes/chameleon/common-rtl.css
- themes/chameleon/style.css
- themes/chameleon/marvin/style.css
- themes/chameleon/marvin/style-rtl.css
- themes/chameleon/common.css
- themes/chameleon/style-rtl.css
Суммарный размер CSS-файлов на порядок меньше, чем размер JS-файлов. Но нужно учесть, что CSS-файлов на странице намного больше, чем JS-файлов - примерно в 2 раза больше. Кроме того, стили, как правило, загружаются для всех страниц (это стили темы) и только стили модулей могут загружаться для определённых страниц. Таким образом и файлы стилей, и скрипты нуждаются в нашем внимании в одинаковой степени.Ограниченный Internet ExplorerБраузер IE 6-8 имеет ограничение на количество и размер CSS-файлов:
- Все теги добавления стилей после первых 31 тегов игнорируются.
- Все CSS-правила после первых 4,095 правил игнорируются.
- На страницах, которые используют правило @import для импорта внешних таблиц стилей, которые импортируют другие внешние таблицы стилей, таблицы стилей с уровнем вложенности больше 3 - игнорируются.
Ограничение протокола HTTPИнтересно есть ли у браузеров ограничение на количество АJAX-соединений?Согласно спецификации HTTP 1.1 браузер должен устанавливать не более 2 одновременных соединений (и это справедливао для IE6/7) к одному хосту. В Firefox и Opera этот параметр настраиваемый и составляет не меньше 4 по умолчанию. По некоторым данным в IE8 - 6 соединений с одним хостом.Источник информации: Raising network.http.max-persistent-connections-per-server?
- Firefox 2: 2
- Firefox 3 beta 4: 4
- Opera 9.26: 4
- Opera 9.5 beta: 4
- Safari 3.0.4 Mac/Windows: 4
- IE 7: 2
- IE 8: 6
Вывод:
- Большинство JS и CSS-файлов не оптимизированы.
- Файлов много и их суммарные размеры значительны.
- Имеем проблемы с браузером IE, который ограничивает количество CSS-файлов на странице.
- Проблемы со скоростью загрузки страницы из-за большого количества внешних файлов и ограничение браузеров на количество одновременных соединений с сервером.
Разберемся с терминологией.Виды оптимизацииМинимизация скрипта — это удаление из кода всех несущественных символов с целью уменьшения объема файла скрипта и ускорения его загрузки. В минимизированном коде удаляются все комментарии и незначащие пробелы, переносы строк, символы табуляции. В случае с JavaScript, это уменьшает время загрузки страницы, так как размер файла уменьшается. Две самых популярных утилиты для минимизации JavaScript — JSMin и YUI Compressor.Обфускация является альтернативным способом сокращения исходного кода. Также, как минимизация, она удаляет пробельные символы и вырезает комментарии, но в дополнение она измененяет сам код. К примеру, во время обфускации имена функций и переменных заменяются на более короткие, что делает код более компактным, но менее читабельным. Обычно этот прием используется для усложнения реверс-инжиниринга программы. Но обфускация помогает также уменьшить код настолько, насколько это не получится сделать одной минимизацией. С выбором средства для обфускации JavaScript не все так ясно, но я думаю, что самая распространенная утилита для этого — Dojo Compressor (ShrinkSafe).Минимизация JavaScript — безопасный и довольно простой процесс. С другой стороны, обфускация из-за своей сложности может вносить в код ошибки. Обфускация также требует правки вашего кода для выделения в нем API-функций и других элементов, которые не должны быть изменены.Аггрегация - это объединение нескольких файлов на странице в один. Аггрегация безопасна также как и минимизация, потому что код не меняется. Иногда "склейка" файлов может давать сбой из-за некорректных комментариев в конце файлов. Аггрегация позволяет уменьшить количество файлов подключаемых на странице. Начиная с Drupal 6 аггрегация CSS и JS-файлов встроена в ядро, а до этой версии нужно было установить дополнительный модуль.HTTP-cжатие - это способ сжать контент (в основном текстовый), который передается с веб-серверов через интернет в браузеры. Основное преимущество сжатия в том, что уменьшается количество байт, которые передаются и таким образом достигается большая производительность. HTTP-сжатие использует общедоступные алгоритмы сжатия, чтобы кодировать HTML, XML, JavaScript, CSS и другие форматы файлов на стороне сервера. Этот метод доставки сжатого контента основан на стандартах и включен в HTTP/1.1 и все современные браузеры поддерживают протокол HTTP/1.1. Таким образом они могут распаковывать сжатые файлы автоматически на стороне клиента. Это означает, что никакого дополнительного ПО или участия пользователя на стороне клиента не нужно.Запрос на сервер без использования сжатия
Запрос на сервер и сервер отдает сжатый контент
Для каскадных таблиц стилей можно применять только минимизацию, аггрегацию и HTTP-сжатие. Обфускация для CSS-файлов не используется. А вот для JavaScript-файлов любой из методов подходит.Обзор существующих Javascript-компрессоров.Сравнить степень сжатия одного и того же файла можно с помощью онлайн-сервиса: JavaScript Compressor and Comparison Utility.
- JSMin - традиционный компрессор, написанный несколько лет назад Дугласом Крокфордом (Douglas Crockford). Утилита безопасна (особенно, если вы перед использованием проверили ваш код с помощью JSLint), потому что утилита не пытается изменять имена переменных.
- Dojo shrinksafe - это очень популярный JavaScript компрессор, написанный на Java. Он парсит кода используя библиотеку rhino и изменяет имена локальных переменных.
- Packer написан Дином Эдвардсом (Dean Edwards). Ещё один очень популярный JavaScript компрессор, который может ещё больше обычного сжатия и также добавляет распаковку "на лету" во время выполнения JavaScript.
- YUI Compressor - это новыейший компрессор, написанный Люлиен Лекомт (Julien Lecomte), который ставит своей целью объединить безопасность JSMin с высочайшим уровнем сжатия, который достигается Dojo Shrinksafe. Подобно Dojo shrinksafe, он написан на Java и основан на библиотеке rhino.
Степень сжатия у всех компрессоров разная, потому как и методы сжатия тоже разные. Сжатие маленьких файлов, как правило, дает очень незначительное сжатие, а файлы больше 10Кбайт сжимаются очень хорошо. На диаграмме ниже показана зависимость степени сжатия от размера файла:Подробности тестирования степени сжания разными компрессорами -- в статье JavaScript: жать или не жать?. Использована диаграмма из этой статьи.
Варианты решения проблемыИтак, у нас есть достаточно большое количество файлов, которые можно сжать и нам нужно разобраться с тем, что Drupal уже может нам предложить (в ядре и в дополнительных модулях) и найти наиболее оптимальное решение.Начнем с анализа того, что мы уже имеем "из коробки".Стандартные возможности DrupalВ ядре Drupal 6 реализованы аггрегация JavaScript и СSS-файлов и HTTP-сжатие.На странице "Performance" ("Производительность" - admin/settings/performance) есть возможность включить/выключить оптимизацию CSS и JavaScript файлов:Если оптимизация CSS и JS-файлов заблокирована - это значит, что кеш аггрегированных файлов не удается записать в файлы. Проверьте верно ли указан путь к папке files и права записи для этой папки на странице File System (Файловая система - admin/settings/file-system).Как работает оптимизация JS и CSS-файлов в ядре Drupal?Чтобы начать пользоваться этой возможностью - нужно включить оптимизацию JavaScript или CSS-файлов на странице настройки производительности.Тогда во время темизации страницы из функции template_preprocess_page() будет вызвана фукнция drupal_get_css(). Именно эта функция и делает основную работу для CSS-файлов.Как работает функция drupal_get_css()?
- Оптимизация CSS не делается, когда сайт находится в режиме Maintenance ("Обслуживание") или запущено обновление (update.php).
- К оптимизированным файлам добавляется строка в виде параметра, которая позволяет контролировать кеширование файлов браузером. Когда запускается update.php или делается полный сброс кеша, - меняется эта строка, что заставляет браузеры перезагрузить новые версии файлов, так как они считают, что URL изменился.
- Будет ли файл участвовать в оптимизации решает 4й аргумент функции drupal_add_css() - $preprocess, который определяет будет ли данный файл участвовать в оптимизации, если она будет включена. По умолчанию файл будет участвовать в оптимизации.
- Сначала формируется 2 списка файлов, которые не участвуют в оптимизации CSS - отдельно (1) для модулей и отдельно (2) для тем.
- Далее создается имя файла, который будет хранить оптимизированный CSS и вызывается функция drupal_build_css_cache(), которая аггрегирует и оптимизирует CSS файлы.
- Полученный файл сохраняется в папке sites/default/files/css (в мультисайтовой установке будет другой путь, но,- я думаю,- что вы и сами знаете где они будут сохраняться).
Что в себя включает оптимизация?
- Все @import инструкции проходят обработку в drupal_load_stylesheet() и заменяются контентом файла, который должен был импортироваться.
- Находятся все комментарии с одиночными и двойными кaвычками и отправляются на обработку в функцию _process_comment(), которая пытается определить можно ли этот комментарий удалить или это хак для IE-Mac.
- Удаляются пробелы вокруг разделителей, но сохраняются вокруг круглых скобок.
Итак, оптимизация, которую нам предлагает ядро Drupal является на самом деле минимизацией с аггрегацией в один файл.Недостатки метода оптимизации в ядре DrupalМетод оптимизации, который используется в ядре Drupal безопасен, то есть он не приводит к ошибкам в коде. Но метод не настолько эффективен, как кажется.Дело в том, что на странице может быть десятка 2 разных скриптов, которые собираются в уникальный файл, который для данной страницы кешируется. Скрипты на странице могут подгружаться в зависимости от прав доступа пользователя или ещё каких-либо условий, что увеличивает количество вариантов для одной-единственной страницы.
Таким образом мы создаем большой файл, который аггрегирует скрипты и браузер его кеширует для данной страницы. Для следующей страницы может добавиться или удалиться несколько скриптов и будет создан новый уникальный файл, который аггрегирует скрипты для данный страницы. Браузер закеширует и его, но в этих 2х больших файлах очень много общего кода, который дваждый передается и кешируется браузером отдельно в файлах с разными именами. Таким образом при эффективном кешировании браузера (если оно включено) этот метод может давать даже увеличение трафика.Оптимизация JavaScript в ядре DrupalОптимизация JavaScript делается подобно оптимизации CSS-файлов.Именно такой способ склейки может породить ошибки в аггрегированном файле, когда в конце скрипта последней строкой был комментарий.При оптимизации JavaScript-файлов они объединяются в один большой файл несколько иначе - после каждого файла добавляется ";\n".Сам код JS-файла никак не изменяется - это можно увидеть в коде функции drupal_build_js_cache(), а просто объединяется в один большой файл.То есть ядро Drupal не делает даже минимизации JavaScript!Использование HTTP-сжатияНа странице настройки производительности ("Perfomance") можно включать и выключать HTTP-сжатие:Фукнция page_set_cache() сохраняет сжатый контент страницы в кеше, если:
- Если выбрано использование сжатия трафика на странице настройки производительности,
- Расширение PHP zlib ) присутствует в системе,
Drupal кеширует контент страницы, а при выполнении условий, указанных выше, сжимает и затем кеширует контент страницы..Если браузер поддерживает HTTP-сжатие, то в запросе страницы он указывает с какими видами сжатия он умеет работать:Accept-Encoding: gzip,deflateA simple online web page compression / deflate / gzip test tool - сервис, который проверяет отдает ли сервер файл с использованием HTTP-сжатия и степень сжатия.Если сервер использует HTTP-сжатие, то он будет сам сжимать и отдавать браузеру сжатую версию контента.Но Drupal может и сам при наличии библиотеки zlib сжимать и кешировать уже сжатую версию HTML-страницы, но не JS и не CSS-файлы.Это значит, что если веб-сервер настроен сжимать контент и браузер поддерживает такое сжатие, то сервер будет "на лету" сжимать JS и CSS-файлы. Но намного эффективнее было бы хранить сжатые копии этих файлов с максимально большой степенью сжатия, а не сжимать их "на лету" (в этом случае по умолчанию используется не максимальная степень сжатия).Дополнительные модулиМодуль JavaScript AggregatorМодуль делает минимизацию JS-файлов, используя JSMinМодуль может сжимать аггрегированные и минимизированные JS-файлы, используя gzip-сжатие. Сжатая копия хранится в файле на сервере и отдается браузеру вместо того, чтобы веб-сервер сжимал этот файл самостоятельно.Пример сжатия:FILENAME SIZE DESCRIPTION6e13ccb6262e06b9f890414db56d3b1f.js 289.558 Bytes > Aggregated by Drupal Core6e13ccb6262e06b9f890414db56d3b1f.jsmin.js 173.243 Bytes > Minified with JSMin6e13ccb6262e06b9f890414db56d3b1f.jsmin.js.gz 47.618 Bytes > Minified and gzippedМодуль CSS Gzip
- Модуль сжимает аггрегированные CSS-файлы, как это делает с JS-файлами модуль Javascript Aggregator.
- Сжимает контент один раз и сохраняет результат -- это уменьшает нагрузку на процессор сервера.
- Использует 9й уровень сжатия так как это нужно сделать только 1 раз для каждого файла, что дает меньший размер файла.
- Требует включенные "Чистые ссылки" (mod_rewrite).
- Требует, чтобы метод скачивания был "Публичный" (см admin/settings/file-system).
- Вошел в ядро Drupal 7.
Модуль Parallel
- Позволяет браузеру параллельно загружать внешние файлы страницы.
- Для этого создается 3 новых поддомена, которые указывают на одну корневую папку сайта.
- Включить модуль Parallel.
- На странице "Производительность" ("Performance") нужно указать эти поддомены.
- Не требует хакать ядро Drupal.
- Модуль Parallel работет только с JavaScript, картинками и CSS.
Модуль IE CSS Optimizer
- Модуль дает возможность разработчикам исключать отдельные файлы модулей, а также CSS-файлы тем, из аггрегации.
- Требует, чтобы метод скачивания был "Публичный" (см admin/settings/file-system).
- В Drupal 7 модуль не нужен: http://drupal.org/node/228818.
- Другие модули могут перезаписать $vars['styles'] и это нейтрализует модуль. Чинится изменением веса модуля.
Модуль IE Unlimited CSS Loader"don’t use @import" -- статья о том, почему использование @import не желательно с точки зрения производительности.Модуль делает примерно тоже самое, что и IE CSS Optimizer, но немного иначе - использует @import, чтобы обойти ограниченность браузера IE в 31 СSS-файл.Модуль CSSTidy
- Модуль автоматически запускает CSSTidy в максимальным уровнем сжатия.
- Можно настроить так, чтобы код оставался читабельным.
- Модуль не совместим с Pressflow.
- Новый CSS3 может вызывать проблемы (см. http://drupal.org/node/763730). Некоторые из них уже решены: http://drupal.org/cvs?commit=432558
Что оптимизируется:
- Цвета типа black или rgb(0,0,0) конвертируются в hex-коды типа #000, когда только возможно. Некоторые hex-коды заменяются их цветовыми именами, если они короче (#f00 -> red).
- a{property:x;property:y;} становится a{property:y;} (все повторяющиеся аттрибуты объединяются).
- margin:1px 1px 1px 1px; становится margin:1px;.
- margin:0px; становится margin:0;.
- a{margin-top:10px; margin-bottom:10px; margin-left:10px; margin-right:10px;} становится a{margin:10px;}.
- margin:010.0px; становится margin:10px;.
- Все не нужные пробелы удаляются.
- Все свойства background: объединяются.
- Все комментарии удаляются.
- Последняя точка с запятой в каждом блоке удаляется.
- Недостающие точки с запятой добавляются, некорректные переносы строк в строках исправляются, неверные цвета (и имена цветов) исправляются.
- property:value ! important; становится property:value !important;
CSS-хаки, которые работают:
Тестирование скорости загрузки страницыБыл проведен замер времени загрузки страницы, чтобы выяснить насколько изменится среднее время загрузки при разных методах оптимизации JS-файлов. Тестовый сайт имеет более 1300 JS-файлов и почти 450-CSS-файлов. Установлено 227 модулей (включая модули ядра). Были исследованы разные методы оптимизации:
- Optimize JavaScript files: Disabled - оптимизация JS-файлов ядром Drupal отключена
- Optimize JavaScript files: Enabled - оптимизация JS-файлов ядром Drupal включена
- Optimize and Minify JavaScript files: Enabled - оптимизация JS-файлов ядром Drupal включена и дополнительно установлен модуль Javascript Aggregator, который сильнее минимизирует JS-код.
Условия проведения тестаНастройки браузера
- Проверяемая страница: главная страница тестируемого сайта
- Браузер: Firefox 3.6.13
- Кеш браузера: 500М
- Инструмент замера: Yslow 2.1.0
- Прокси сервер: не использовался
Настройки сервера
- На сервере используется: Accelerator
- Операционная система: Linux
- Версия ядра: 2.6.29-5
- Архитектура: x86_64
Настройки в Drupal
- Пользователь в Drupal: суперадмин
- Caching mode: Normal
- Minimum cache lifetime: none
- Page compression: enabled
- Block cache: enabled
- Optimize CSS files: enabled
Результаты тестированияСреднее время загрузки страницы
Диаграмма времени загрузки страницы в разных режимах
Анализ результатов тестирования
- Аггрегация уменьшает количество запросов к серверу (при пустом кеше) на 23 штуки.Это значит первая загрузка страницы будет быстрее.
- Использование кеша браузера позволяет снизить количество запросов до 13. Кеш, как правило, включен по умолчанию, но управлять кешированием браузера мы не можем и он может быть просто отключен.
- HTTP-сжатие не дает максимального результата.Аггрегированный JS-файл имеет точно такой же размер, как и суммарный размер всех неаггрегированных JS-файлов страницы. Но при передаче файла в браузер он сжимается плохо и получается больше. Аггрегированный файл на сервере имеет размер 326,9Кбайт, а полученный браузером и сжатый gzip - 108,9Кбайт. При этом сжатие утилитой gzip того же файла на сервере дает размер около 90Кбайт. Причина в том, что библиотека zlib, которая используется для сжатия на сервере имеет по умолчанию степень сжатия (zlib.output_compression_level) равную "-1", хотя максимальная степень сжатия - это "9", а "-1" - это наилучшее быстродействие. Таким образом мы получаем худшее сжатие, но выше быстродействие сервера.
- Использование модуля JavaScript Aggregator вместе с аггрегацией и HTTP-сжатием дает файл меньшего почти в половину(!) размер, чем не аггрегированные файлы.
Таким образом экспериментальным путем было установлено, что оптимизация ядром Drupal JS-файлов не всегда показывает хороший результат. В нашем случае (без применения модуля JavaScript Aggregator) мы получили незначительное увеличение скорости загрузки (за счет сокращения количества запросов) и увеличение (по сравнению с исходными файлами) размера аггрегированного (и сжатого) файла.Учитывая то, на многих страницах загружаются одни и те же JS и СSS-файлы, а добавляются/удаляются только несколько специфичных, то кеширование одного большого файла не даст прироста производительности. При этом кеширование браузером отдельных файлов стилей и скриптов на одной странице даст экономию на загрузке этих файлов на последующих страницах.Пользователь, как правило, не загружает одну и ту же страницу несколько раз, а переходит дальше и дальше ("серфит") и таким образом кеширование браузером небольших файлов скриптов и стилей может быть эффективнее аггрегации в один большой файл. Но это только для пользователя, а для сервера выгоднее иметь как можно меньше запросов и отдавать аггрегированные файлы, вместо кучи небольших файлов.Что можно сделать, чтобы улучшить ситуацию?
- Хранить сжатые JS-файлы с максмальным уровнем сжатия, чтобы не заставлять сервер сжимать их для каждого запроса.
- Использовать более эффективные методы упаковки JS и CSS-файлов.
- Можно использовать выборочную аггрегацию общих для разных страниц сайта скриптов и стилей, а специфичные файлы загружать отдельно, но этот метод трудоемкий.
- Переместить Javascript в footer, чтобы ускорить момент показа страницы пользователю.
- Использовать CDN или модуль Parallel, чтобы увеличить количество одновременных соединений, которые может позволить себе браузер.
Полезные ссылкиКомпрессоры скриптов
HTTP-сжатие
Порядок загрузки элементов страницы браузером
Перенос Javascript в footer
Разное
drupal-bloggers.com