Drupal 8: Attaching Core Libraries and Other Scripts to Your Theme

Drupal 8: Attaching Core Libraries and Other Scripts to Your Theme

Note: all, or parts of this article may be out of date

For the past six months, I've been in the process of porting my contrib theme, Gratis, to Drupal 8. One of the challenges for contrib is Drupal 8 has been a constant moving target in terms of API changes. With every new Alpha of Drupal 8, I've had to adjust many bits of theme code to adhere to these new APIs.

One of the biggest challenges has been figuring out how to add jQuery and other core scripts into the theme. That's because off the shelf, Drupal 8 core themes don't require javascript for anonymous users. This seems like an odd choice by core but my guess is that is was done for Drupal 8 to be more minimalistic and nimble on its feet.

At any rate, if you have a contrib theme, most likely the first thing you'll do is add all of these back in. To add an additional layer of complexity to all this is the fact that the manner in which this is done has changed dramatically in recent weeks. No doubt, that jQuery is missing for anonymous users will be a source of confusion for some front end developers and themers.

Exit nested arrays, enter YAML

At first one added core libraries using hook_library_info which was a mess of PHP nested arrays in your theme's .theme file. Now, in true Drupal 8 fashion, we do this with a .yml or "yaml" (rhymes with camel) file. YAML is an acronym for "Yet Another Markup Language" or "Ain't Markup Language" and has become a core method for streamlining code in Drupal 8.

Here is a basic example of how you can add jQuery to a theme and a few dependencies. You'd do this by creating a *libraries.yml file in the root of your theme. So in my case my theme name is foobar so the file name would be foobar.libraries.yml.

foobar-corescripts:
  version: VERSION
  js:
    js/scripts.js: {}
  dependencies:
    - core/jquery
    - core/drupal.ajax
    - core/drupal
    - core/drupalSettings
    - core/jquery.once
 

With the above code, we'll be adding the core scripts jquery.js, drupal.js, ajax.js and jquery.once.js to our theme. This will make it available for anonymous users. With YAML, indentation spaces are relevant so you'll need to get that bit right. In addition, we are calling a theme relative script in the theme's js folder, scripts.js. The name -corescripts can be anything you want as long as it matches when you go to attach it in your .theme file as outlined below.

Attach the Library

The next step is to attach the library we created with a theme preprocess function in combination with the #attached method. In this case we'll use hook_page_alter. (Note, this tip was given to me by @daveried who pointed out that this is better than hook_preprocess_page where you also need to use drupal_render() for attached to work.)

function foobar_page_alter(&$page) {
  // Render the library as laid out in foobar.libraries.yml
  $page['#attached']['library'][] = 'foobar/foobar-corescripts';
}

Attaching the library above implements provider-namespaced strings i.e. 'foobar/foobar-corescripts' where previously it had an array associated with it. This is new in Drupal 8 Alpha 10 and it threw me off for a while until I found a core issue that documented this change.

Update (7, April)

Recently, a new method of attaching your library can be done by adding the namespace to your theme's .info.yml file with the libraries key so in this case, you could forego using a hook. (Thanks to @Nod_ for this tip.) This is still in Drupal 8 dev and won't appear until the next alpha. This is probably a good method for an off the shelf contrib theme but if you need more granularity, say you only want to add certain scripts for specific conditions or a content type, then a preprocess hook may still be the way to go. You'll be able to do this by adding this code to your theme's .info file. In effect, this replaces the old method where we used to add JS directly in the info file.

core: 8.x
libraries:
  - foobar/foobar-corescripts

What's Next?

In future Drupal 8 related articles, I'll get in to setting custom configuration for your Drupal 8 theme, this comes in real handy and we'll be using YAML with the added addition of using Drupal 8's CMI layer. I'll also talk more about API changes as they relate to themers, it's probably safe to do that now as Drupal 8 is most likely heading toward a beta within the next few months and it seems like many of the major core API changes have been done.

Resources

Tags