Drupal → Подключение своих js и css файлов в Drupal 8+

29.01.2018

В 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

Как понятно из описания, библиотека jquery.ui.dialog содержит один js файл jquery.ui.dialog.js, один css файл jquery.ui.dialog.css и зависит от другой библиотеки 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:

libraries:
  - mytheme/global-styling
  - mytheme/mylibrary

Чтобы добавить библиотеку только на определённую страницу/страницы, можно воспользоваться препроцессом:

/**
 * Preprocess function for page.twig.html.
 */
function THEMENAME_preprocess_page(array &$vars): void {
  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): void {
  $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(array &$libraries, string $extension): void {
  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 на страницы)
Централизованный способ отключить в рантайме определённую библиотеку

Написанное актуально для
Drupal 8+
Похожие записи

Комментарии

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

Гость
10.12.2019, 15:54

Привет!

Как указано в статье,

{{ attach_library('modulename/libraryname') }}

подключает библиотеку в нужном месте .html.twig, а если я хочу подключить библиотеку js с атрибутом defer - <script src="js/scripts.js" defer></script>, то как это сделать через attach?

libraries.yml

example.js: { attributes: { defer: true } }
Гость
11.12.2019, 15:09

Спасибо! А можно как-то подключить js только для залогинённых пользователей?

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