Features is a Drupal module that allows parts of the site configuration to be exported into modules. These modules can then be used to govern or migrate that configuration on other Drupal sites. As the core of the feature module is just configuration the module can easily look at differences in the configuration items and allows those changes to be imported into the site.
We were recently faced with a task of migrating a content type from one site to another and decided to use Features to extract the configuration in a module.
A single content type can have many configuration files associated with it. This is because the content type, field storage, field configuration, display modes, path settings and more needs to accompany the content type for it to make sense to the system. Trying to unpick the multitude of configuration files that belong to a content type is difficult and time consuming.
In this article I will look at the Features module as well as the problem Features solves.
Let's start with how Drupal modules can automatically install configuration.
Auto installing configuration in modules and profiles
Every module (and install profile) has the ability to install configuration during the installation process. When a module is installed Drupal will look in the config/install and config/optional directories in the module to see if there is any configuration that needs to be installed.
Configuration files in the config/install directory will be automatically installed as the module is installed.
Configuration files in the config/optional directory will be automatically installed if the required dependencies are in place for the configuration to be imported.
As an example, take the following module that contains two configuration files.
When the module is installed the Article content type would be automatically created since that is in the config/install directory. The config/optional directory contains an item of Pathauto configuration, which will only be installed if the Pathauto module is installed.
If you are creating a module that contains configuration it s good practice to provide a default configuration file in your config/install directory. This allows the module to come pre-configured after installation.
There are lots of reasons why you would want to package bits of configuration together like this. Let's look at some example.
Adding configuration of a content type to a module is a good way of transporting content types from one site to another without having to rely on configuration. Whilst using configuration is the best way of packaging and moving the structure of a site this isn't always possible. For example, if you have a large multi-site setup (e.g. with over 100 sites) then configuration deployments aren't actually the best approach and you should rely on module configuration imports like this to add functionality to your sites.
Adding configuration for fields to a module is useful if you want to add a field to an existing fieldable entity provided by another module. For example, Group module is a great way of grouping together users and content, and it is possible to add extra fields to your module configuration to inject new fields into a Group entity to allow for extra functionality.
Distributions are a powerful way of installing a Drupal site with content types any other content entities installed out of the box. Distributions use install profiles and modules to inject configuration into the site so it is set up in the correct way.
What Features does is to look at the dependencies of the configuration items you have selected and collect them together in the configuration directories. This means when you install a Feature module you are using this package configuration feature to inject configuration into your site. Features can also be used to keep that configuration up to date, which is facilitated by using the Configuration Update Manager module.
To install Features you need to first require it into your project using composer.
composer require drupal/features
Once in place you can install the features and features_ui modules.
drush en features features_ui
That's it! You can now visit the features admin page at /admin/config/development/features and start using the module.
When you first open the features configuration page you will see Features suggests creating bundle, but this isn't always necessary.
Exporting configuration using Features
There are a couple of avenues open to us here for exporting the configuration we need.
Features will show us a list of suggested packages we can export in order to capture the different content entities on the site, which is grouped into relevant sections for us.
I had a go at using the auto packaging feature that comes with Features and it does a great job of finding all the random things that might be connected to a content type. I tried tripping the configuration detection code up by adding XML sitemap configuration, view modes, metatags and Views to the configuration and Features detected and exported it all.
There are a couple of missing things in the export that you need to be aware of.
- If you have a field that links to another content entity, like a taxonomy or a media item, then Features won't also export those content entities and their fields.
- If you have any shared fields then Features won't export the field storage configuration for those fields. Each field in Drupal is defined by a field storage configuration and a field instance configuration and the field can't exist without those two pieces of information. If the field is shared between different content entities then Features will only export the field instance configuration.
You'll have to either export these missing items as separate features, or manually add them to your configuration.
The automatic exporter also exported Views connected to the content type I was looking at, which is good to see. The problem was that it also exported the Views block placement configuration for the front end theme of the site. This might not be applicable to the site you want to install the feature onto so it's a good idea to inspect the generated configuration before you do anything with it.
We can, however, opt to create our own feature and package the configuration we want into that Feature. By clicking on the "Create new feature" link on the Features admin page we get a form that allows us to pick and chose the configuration we want.
This can be a little bit fiddly as you need to go through everything and ensure all of the configuration you need has been selected, but it's much better than moving configuration YAML files around. This also takes some of the guesswork out of picking the right configuration as most configuration items are given labels.
Once we are happy with the selection we can either download the module as a zip file, or write it directly to the codebase. This will generate a module that contains all of the configuration we need selected.
The only thing that shows that this module is a feature is the presence of a file called *.features.yml in the root of the module. This file contains a single parameter that controls if features should pick the module up. To disconnect the module from features you can either set the value in this file to false, or delete the file entirely. The module will then act like any other Drupal module but you won't be able to manage the configuration through the features interface.
With this module in hand we can now either move that module to another site or use it to govern the configuration within this site as a Features module. Either way, it's probably a good idea to run a couple of tests to make sure you have captured all of the configuration you need. It's quite easy to forget that content types are normally linked to things like taxonomies and media items and if you don't also include those in your configuration you'll not get the correct result on the other end.
One note of caution here is not to overuse features. The module is not intended to replace configuration management, only augment it. If you have ever used Features in Drupal 6 or 7 then you might remember the pain of some sites exporting everything as a feature and the pain of trying to see why something was overridden in the Features dashboard. In Drupal 8 and above you should use Features to handle specific items of configuration, rather than trying to export everything as a feature.
I have to admit, in the world of Drupal configuration management, I couldn't see a place for Features. It does, however, have a good use case for managing specific configurations and can certainly help with large multi-site setups where configuration management is not possible.