Using the new asset management system

New to Drupal 8 is the asset management system. The asset management system allows modules and themes to register libraries. Libraries define CSS stylesheets and JavaScript files that need to be loaded with the page. Drupal 8 takes this approach for the frontend performance. Rather than loading all CSS or JavaScript assets, only those required for the current page in the specified libraries will be loaded.

In this recipe, we will define a libraries.yml file that will define a CSS stylesheet and JavaScript file provided by a custom theme.

Getting ready

This recipe assumes that you have a custom theme created, such as the one you created in the first recipe. When you see mytheme, use the machine name of the theme that you have created.

How to do it...

  1. Create a folder named css in your themes base directory.
  2. In your css folder, add a style.css file that will hold the theme's CSS declarations. For demonstration purposes, add the following CSS declaration to style.css:
    body {
        background: cornflowerblue;
    }
  3. Then, create a js folder, and add a scripts.js file that will hold the themes JavaScript items.
  4. In your theme folder, create a mytheme.libraries.yml file and edit it, as shown in the following screenshot:

    How to do it...

  5. Add the following YAML text to define the global-styling library for your theme that will load the CSS file and JavaScript file:
    global-styling:
      version: VERSION
      css:
        theme:
          css/style.css: {}
      js:
        js/scripts.js: {}
  6. This tells Drupal that there is a global-styling library. You have the ability to specify a library version and use the VERSION defaults for your themes. It also defines the css/styles.css stylesheet as part of the library under the theme group.
  7. Edit your mytheme.info.yml, and we need to add the declaration to our global-styling library:
    libraries:
      - mytheme/global-styling
  8. Themes are able to specify a libraries key that defines the libraries that should always be loaded. This YAML array lists libraries to be loaded for each page.
  9. Go to Configuration and then to Development to rebuild Drupal's caches.
  10. With your theme set to the default, go to your Drupal site.
  11. Your theme's global-styling library will be loaded and the page's background color will be styled appropriately:
    How to do it...

How it works...

Drupal aggregates all the available library.yml files and passes them to the library.discovery.parser service. The default class for this service provider is DrupalCoreAssetLibraryDiscoveryParser. This service reads the library definition from each library.yml and returns its value to the system. Before parsing the file, the parser allows themes to provide overrides and extensions to the library.

Libraries are enqueuers as they are attached to rendered elements. Themes have the ability to generically add libraries through their info.yml files via the libraries key. These libraries will always be loaded on the page when the theme is active.

CSS stylesheets are added to the data, which will build the head tag of the page. JavaScript resources, by default, are rendered in the footer of the page for performance reasons.

There's more…

We will explore the options surrounding libraries in Drupal 8 in more detail.

CSS groups

With libraries, you have the ability to specify CSS by different groups. Drupal's asset management system provides the following CSS groups:

  • base
  • layout
  • component
  • state
  • theme

Stylesheets are loaded in the order in which the groups are listed. Each one of them relates to a PHP constant defined in /core/includes/common.inc. This allows separation of concerns when working with stylesheets. Drupal 8's CSS architecture borrows concepts from the SMACSS system to organize CSS declarations.

Library asset options

Library assets can have configuration data attached to them. If there are no configuration items provided, a simple set of empty brackets is added. This is why, in each example, files end with {}.

The following example, taken from core.libraries.yml, adds HTML5shiv:

assets/vendor/html5shiv/html5shiv.min.js: { weight: -22, browsers: { IE: 'lte IE 8', '!IE': false }, minified: true }

Let's take a look at the attributes of html5shiv.min.js:

  • The weight key ensures that the script is rendered earlier than other libraries
  • The browser tag allows you to specify conditional rules to load the scripting
  • You should always pass minified as true if the asset has already been minified

For CSS assets, you can pass a media option to specify a media query for the asset. Reviewing classes which implement DrupalCoreAssetAssetCollectionRendererInterface.

Library dependencies

Libraries have the ability to specify other libraries as dependencies. This allows Drupal to provide a minimum footprint on the frontend performance.

Note

jQuery is only loaded if a JavaScript library specifies it as a dependency. Refer to https://www.drupal.org/node/1541860.

Here's an example from the Quick Edit module's libraries.yml file:

quickedit:
  version: VERSION
  js: 
    ...
  css:
    ...
  dependencies:
    - core/jquery
    - core/jquery.once
    - core/underscore
    - core/backbone
    - core/jquery.form
    - core/jquery.ui.position
    - core/drupal
    - core/drupal.displace
    - core/drupal.form
    - core/drupal.ajax
    - core/drupal.debounce
    - core/drupalSettings
- core/drupal.dialog

The Quick Edit module defines jQuery, the jQuery Once plugin, Underscore, and Backbone, and selects other defined libraries as dependencies. Drupal will ensure that these are present whenever the quickedit/quickedit library is attached to a page.

A complete list of the default libraries provided by Drupal core can be found in core.libraries.yml, which is in core/core.libraries.yml.

Overriding and extending other libraries

Themes have the ability to override libraries using the libraries-override and libraries-extend keys in their info.yml. This allows themes to easily customize the existing libraries without having to add the logic for conditionally removing or adding their assets when a particular library has been attached to a page.

The libraries-override key can be used to replace an entire library, replace selected files in a library, remove an asset from a library, or disable an entire library. The following code will allow a theme to provide a custom jQuery UI theme:

libraries-override:
  core/jquery.ui:
    css:
      component:
         assets/vendor/jquery.ui/themes/base/core.css: false
      theme:
         assets/vendor/jquery.ui/themes/base/theme.css: css/jqueryui.css

The override declaration mimics the original configuration. Specifying false will remove the asset or else a supplied path will replace that asset.

The libraries-extend key can be used to load additional libraries with an existing library. The following code will allow a theme to associate a CSS stylesheet with selected jQuery UI declaration overrides, without always having them included in the rest of the theme's assets:

libraries-extend:
  core/jquery.ui:
- mytheme/jqueryui-theme

Using a CDN or external resource as a library

Libraries also work with external resources, such as assets loaded over a CDN. This is done by providing a URL for the file location along with selected file parameters.

Here is an example to add the FontAwesome font icon library from the BootstrapCDN provided by MaxCDN:

mytheme.fontawesome:
  remote: http://fontawesome.io/
  version: 4.4.0
  license:
    name: SIL OFL 1.1
    url: http://fontawesome.io/license/
    gpl-compatible: true
  css:
    base:
      https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css: { type: external, minified: true }

Remote libraries require additional meta information to work properly:

  remote: http://fontawesome.io/

The remote key describes the library as using external resources. While this key is not validated beyond its existence, it is best to define it with the external resource's primary website:

  version: 4.4.0

Like all libraries, a version is required. This should match the version of the external resource being added:

  license:
    name: SIL OFL 1.1
    url: http://fontawesome.io/license/
    gpl-compatible: true

If a library defines the remote key, it needs to also define the license key. This defines the license name, the URL for the license, and checks whether it is GPL compatible. If this key is not provided, a DrupalCoreAssetExtensionLibraryDefinitionMissingLicenseException will be thrown:

  css:
    base:
      https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css: { type: external, minified: true }

Finally, specific external resources are added as normal. Instead of providing a relative file path, the external URL is provided.

Manipulating libraries from hooks

Modules have the ability to provide dynamic library definitions and alter libraries. A module can use the hook_library_info() hook to provide a library definition. This is not the recommended way to define a library, but it is provided for edge use cases.

Modules do not have the ability to use libraries-override or libraries-extend, and need to rely on the hook_library_info_alter() hook. The hook is documented in core/lib/Drupal/Core/Render/theme.api.php or at https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Render!theme.api.php/function/hook_library_info_alter/8.

Placing JavaScript in the header

By default, Drupal ensures that JavaScript is placed last on the page. This improves the page, load performance by allowing the critical portions of the page to load first. Placing JavaScript in the header is now an opt-in option.

In order to render a library in the header, you need to add the header: true key/value pair:

js-library:
  header: true
  js:
    js/myscripts.js: {}

This will load a custom JavaScript library and its dependencies into the header of a page.

See also

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset