Drupal 8 integration with composer has been excellent for managing 3rd party PHP libraries with Drupal, as the libraries can be called using PSR-4 namespaces to load the libraries, regardless of the location of the vendor folder. Being able to call these files regardless of the location of the vendor folder is important, as the vendor library folder location is dynamic. Many installations have the vendor folder installed in the webroot, however it is a best practice to place the vendor folder outside the webroot, a practice followed by the Drupal Composer template,
The problem comes with CSS and JS libraries. These can be included using composer, but when the vendor file is outside the webroot, any CSS and JS are unusable, as they are not web-accessible and therefore cannot be included in *.libraries.yml files.
For contributed module developers, this has led to two separate methods of managing 3rd party libraries with Drupal 8. PHP libraries can and are managed with Composer, and module developers can use composer.json files to manage their dependencies. However, modules that use 3rd party CSS/JS libraries have to either use D7 methods of creating a libraries folder, and have users manage the dependencies on their own to place the library in a web-accessible location, or use Composer to manage the dependency, then have users copy the CSS and JS files to a web accessible location. An example of this is the jQuery Colorpicker module, which as of the time of writing of this post requires users to manage the library on their own, downloading it to a /libraries folder, linking to the CSS and JS files using:
library:
version: 1.0.1
css:
theme:
/libraries/jquery_colorpicker/css/colorpicker.css: {}
js:
/libraries/jquery_colorpicker/js/colorpicker.js: {}
dependencies:
- core/jquery
As you can see, the CSS and JS files are linked to from the /libraries folder. In order to ensure system integrity, hook_requirements() has been implemented, informing users of the requirement of downloading the library and providing instructions on how to do so. This is not ideal. The ideal would be to Include a dependency on the library through Composer, managing the 3rd party library in the same manner as PHP libraries are managed.
The solution to the issue of managing 3rd party CSS and JS libraries with Composer is to use the Vendor Stream Wrapper module. This module is essentially a clone of the private stream wrapper functionality of core, but working with the vendor directory rather than the private files directory. It sets up a vendor:// stream wrapper, and adds parsing to *.libraries.yml files, so that the above jquery_colorpicker.libraries.yml file could be converted to this:
library:
version: 1.0.1
css:
theme:
vendor://jaypan/jquery_colorpicker/css/colorpicker.css: {}
js:
vendor://jaypan/jquery_colorpicker/js/colorpicker.js: {}
dependencies:
- core/jquery
The module looks for the vendor folder first in the webroot, then one folder above the webroot. If the vendor folder is in any other location, the location can be set in settings.php.
I think this module should be included into core, to allow for Drupal modules to manage CSS and JS libraries using Composer, unifying 3rd party library management into a single API, rather than having to use D8 methodology for PHP libraries, and D7 methodology for managing CSS and JS libraries. Currently it is a bug that CSS and JS files in a vendor folder that exists outside the webroot are unable to be linked to, and it becomes a security risk if one of the files that is part of the 3rd party library is found to have a security vulnerability. This security vulnerability would not exist for users who have placed their library in a vendor folder that is outside the webroot.