It is not uncommon for a module to depend on a third-party library. In Backdrop, all third-party libraries should be bundled within a module, rather than placed in a separate /libraries
folder (as in Drupal). Backdrop core provides a set of hooks and functions for making libraries available to your and other modules:
NOTE: Some modules may depend upon the Libraries API module, which has similar hooks (such as hook_libraries_info()
). In Backdrop, it is encouraged to bundle 3rd party libraries within a module's codebase so that the module can be installed through the UI using the core Installer module. The most common scenario when the Libraries API module is necessary is when the library being included is not GPL-compatible, and cannot be bundled into a contrib module.
If you have another use case that can’t currently be solved without having to use Libraries API, then please file an issue to address that use case in Backdrop core.
Library bundling
The recommended practice is to include a third-party library within the same module that is making use of its functionality, rather than creating one Backdrop module for the library and another for the Backdrop-specific functionality. When the library is bundled with the integration it provides, it ensures that the version of the library included will always work with the integration provided.
However, there are several cases where a separate library module would be preferred:
- If you are providing multiple modules that need the library but only one of them would likely be used at any given time. An example would be a payment-processor library with Backdrop modules that support several different E-commerce systems.
- If the functionality of the library is likely to be used by other modules that don’t need the Backdrop-specific functionality of your module (this is very rare). An example might be a JS library for working with dates, which could be used in many places.
If your module requires a third-party library that is already used and bundled by another module, then your module should either depend on that other module, or the 3rd party library should be split out of the “parent” module that it used to ship with, and moved into a new contrib library-only module.
A library-only module will be used to hold the library (implementing hook_library_info()
if applicable, e.g., for JS and/or CSS libraries). Then all other contrib modules that require the 3rd party library, should declare the library module as a dependency in their .info files, using dependencies[] = name_of_library_module
.
Where to bundle
When deciding where to bundle the library, user experience should be valued over the preference of the developer. Whenever possible, a person should be able to install a single project to accomplish the task at hand.
Developers often favor a fine-grained bundling strategy (i.e., spreading functionality over several related modules), but it can be frustrating to site architects to have to locate, download, and install 2 or 3 (or more) modules just to accomplish a single goal.
Consider, for example, an image gallery based on an external library.
With the functionality that exists in Backdrop core, we should be able to reduce the installation process to installing a single module that includes the library, rather than making the user find the multiple modules that its functionality is spread over.
Note that if the primary purpose of your library is for building something like an image gallery, it's probable that at least 80% of the time the library is needed, it would be for a views display, and so the views integration for the library should also be included in the module that bundles the library.
It's also possible that people might want to use the library on a field display. Ideally, then, the field integration would also be part of the module that adds the views integration.
If, however, you believe that this feature would be used less than 80% of the time, the next-best location for the field integration wold be in a sub-module that is part of the same project, so that still only one project needs to be installed by the site architect.
The third-best location for the field integration would be in a separate add-on module that can be downloaded and installed separately from the original module, and in this case, the separate module should add the dependencies[]
line to the .info
file, to indicate that the primary module is needed.
The least-best scenario for this image gallery would be to have one project for the library only, a second for the views integration, and a third for the field integration. But this brings us back to the "fractured" user experience that Backdrop CMS is trying to avoid.
As noted above, a library-only module can create version compatibility problems if a library and module must be updated in sync. It can also create a frustrating experience for site architects; after installing a library-only module, many people will search the admin interface for the feature it provides, only to learn (eventually) that the module does not provide any features.
Modules that do not provide any features directly should make this clear in two ways:
- The module's README file should clearly state this early in its description;
- The name of the module should give some indication that this is the case, commonly by adding "API" to the module name.
For example, a module titled "YouTube" should not just implement the YouTube API, but should provide features that support that API. If the library really is just a wrapper for the YouTube API, then a better module name would be "YouTube API".
Be aware that even if the module's README file states that it is library-only, people are not likely to read the project description (or the README file) if the project name exactly matches their expectations. (Telling people that they should have read the README, after the fact, does not negate the frustration they have already experienced.) Anything we can do to eliminate the frustration before it happens, should be attempted; hence the suggested hinting in the module name.
There are, of course, many different types of libraries, and not all of them provide clear examples of which features meet the 80% use case that warrant bundling. In the end, the decision of where to place the library falls to those creating the modules, but the considerations above can serve as a guide to help make that decision.