The Backstory

While talking to @webchick at BADCamp, I (samuel.mortenson) brought up that even with Drupal 8's new Library handling logic, there is still no answer to/best practice for one of the most common Library problems: "Where do I put my external Javascript/CSS files?". I can think of a few approaches to this, but we should standardize as a community on one or more best practices so that contributed module authors know the best methods for handling external libraries.

The stories that need to be worked out in the documentation are:

  1. As a module author, I need to know what best practices to use when including external libraries.
  2. As a module author, I need to deal with duplicate versions of libraries and conflicts with other modules.
  3. As a module author, I need to verify library versions and warn users when libraries are out of date.

Your behaviors—Adding JS/CSS in a module or theme

Best practices for handling External Libraries using Libraries API[3rd]

Ultimately, the goal of the Libraries API is to make the assets added by it shareable between modules and themes, consistently done between projects and developers/sitebuilders — and it is easier to maintain through the lifespan of a site.

    • With the Libraries module (3.x) for Drupal 8. Having contrib modules for each external common JS framework (and then, plugins of that framework), and mark those as a dependency of your module/theme[T].
    • Use hook_libraries_info() to define a new library, use DRUPAL_ROOT/libraries as the general folder to uncompress those packages. Use a subfolder name reflecting that JS framework/plugin (e.g., /libraries/jquery.easing).

      DRUPAL_ROOT is the PHP Constant name for your web root folder where the other files (like index.php) would be found.

    • For multisite projects where you many want to limit to a unique site use DRUPAL_ROOT/sites/[domain]/libraries.
  1. Add [my_module].install file in your module. Use hook_requirements($phase) with a loop for if ($phase=='install'){} to check for proper installation of Library.
  2. Would be best to give as direct a link to the library. (ie if from github give path to the tagged version you know will work with the drupal behaviour that will be triggering it. do not just link to MASTER/HEAD, unless you want a string of issues against your module because the plugin has changed!

Some Aside Notes

  • On Tools of the trade:
    • Have users run a post-install script like "bower install" from your module directory, and include your libraries relative to your module directory. (ex: bower_components/my_library/my_library.js) IE: File Entity Browser.
    • Let's not focus on how a developer/site builder downloaded to their file system, as there is a variety of tools to do so and will change in time. (ie: no one uses MAKE files anymore)
  • Linking from 3rd party Servers: Use a CDN like cdnjs.com to ensure the correct version is being used and reduce install complexity.
    • Not recommending module developers linking CDN's in their *.libraries.yml file. This is a poor development practice, you can't guarantee your module/theme's functionality this way.
    • Problems with 3rd services (CDN's or general linking to other live Servers) with 404 & maintenance realities or just slow load times..
    • Some issues on the effects on js/css caching can occur with CDN use.
  • Why not to include 3rd files in a Drupal Repo[3rd]

    RE: Regarding Software Licenses. Drupal.org's policies and other legal requirements

    Simply, if we use the Libraries API (and only include the JS behaviour and custom CSS in our modules/themes) we will be in compliance with such policies and laws. Making such 3rd code sharable and maintainable in our custom work for clients. As well as then being ready to contribute work back to the Drupal Community.

    Related Issues on Drupal core — Themes[T]:

    1. Add (back) hook_install for themes
    2. Allow themes to declare dependencies on modules

    Comments

    samuel.mortenson created an issue. See original summary.

    awasson’s picture

    I'm porting a wrapper module to D8 and just stumbled across this issue.

    I would like to maintain some sort of consistency and have a goto place to put my libraries. In the pre-D8 days, it was /sites/all/libraries but now that /sites/all is no longer in vogue, perhaps we need to add a libraries folder in the root of the site.

    samuel.mortenson’s picture

    Issue summary: View changes
    joelpittet’s picture

    I'd like to second /libraries as the location of choice. Especially because we don't have any mechanisms in place to download bower components for contrib modules at the moment and may be tricky to get DRUPAL_ROOT path from inside bower easily. (because of nested custom/contrib/features subfolders and now /modules in root)

    skaught’s picture

    Priority: Normal » Critical
    Issue tags: +Libraries, +8.1.x-dev, +8.2.x-dev

    I'm in the process of writing a new module (for D7, at the moment) but am also in the process of writing an 8 branch. As i've been looking at other modules (ie superfish, respondjs, slick) there's clearly no best practice exists -- but needs one now.

    Libraries api 2.x not only supported JS and CSS, but did support PHP as well. i'm not sure it the ability to handle PHP still in sight. Which is a good side issue to it all.

    Drupal 8 includes the /vendor folder. I'm not sure that the best practice suppose to be it when we want to be able to include a php library? JS & CSS could be here as well. Otherwise should the vender folder me in /core? I'm sure conversations about this have been float around.

    To mention: Bower (which would use /node_modules folder complicates things too much. especially as we're not using nodejs.

    tagging, priority -- hopefully others will pay more attention.

    skaught’s picture

    skaught’s picture

    skaught’s picture

    skaught’s picture

    skaught’s picture

    Related issues:

    drupal.org/node/2170763 | Using Libraries API 8.x-3.x (as a module-developer)

    skaught’s picture

    samuel.mortenson’s picture

    As an update to the original issue - File Browser now defaults to using the absolute /libraries path, but conditionally supports the Libraries module using this chunk of code:

    /**
     * Implements hook_library_info_alter().
     */
    function file_browser_library_info_alter(&$libraries, $extension) {
      // Optionally use the Libraries module to determine our library paths.
      if ($extension == 'file_browser' && \Drupal::moduleHandler()->moduleExists('libraries')) {
        $imagesloaded_path = libraries_get_path('imagesloaded') . '/imagesloaded.pkgd.min.js';
        $masonry_path = libraries_get_path('masonry') . '/dist/masonry.pkgd.min.js';
    
        $libraries['imagesloaded']['js'] = ['/' . $imagesloaded_path => ['minified' => 'true']];
        $libraries['masonry']['js'] = ['/' . $masonry_path => ['minified' => 'true']];
      }
    }

    Similar methods are already used in projects like DropzoneJS.

    skaught’s picture

    as for the side issue of /vendor or /node_modules -- which is really composer vs bower. A reminder to all, it's not about how you downloaded it to your file system...it's about sharing these plugins between modules.

    again, other important notes:

    • multisite --what if you do want to limit access to one site
    • jQuery versions -- what if you need to run 2 jquery's. In D7 projects (because jq1.4 in core) i often had to run two at once. How should we handle this now. as many plugins are still written for 1.x...

    @samuel.mortenson
    i've tested through #667058 and have marked it. hopefully wheels will continue to move for this.

    skaught’s picture

    Related issues:
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes

    allowed tag fix

    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Title: Missing best practices for handling external libraries in Drupal 8 » Best practices for handling external libraries in Drupal 8
    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    Issue tags: -8.1.x-dev, -8.2.x-dev +8.x
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    skaught’s picture

    Issue summary: View changes
    Crell’s picture

    SKAUGHT: Please make all your changes elsewhere and then copy back in here once. Every time you post a comment the site sends an email to anyone who's subscribed and configured that way, and it shows up again in in their issue feed, and... :-(

    skaught’s picture

    i hear ya (: true i'm a edit crazy. but the irony of the site not having publishing workflow, nor full wysiwyg. who can we talk to about that?

    awasson’s picture

    The best practice is to make your comment and click the preview button. You can edit and preview as many times as you like and then once satisfied, you can save it. That way the discussion thread is easier to follow.

    krina.addweb’s picture

    Issue summary: View changes
    mr.ashishjain’s picture

    Issue summary: View changes
    natemow’s picture

    Not sure if its by design (or maybe just my own "bad practice"), but I found an interesting/cool way to manage external dependencies using only *.libraries.yml today. See http://cgit.drupalcode.org/supercookie/tree/supercookie.libraries.yml?h=... (noting especially the hardset /library/*.js paths), then the corresponding #attached statement in http://cgit.drupalcode.org/supercookie/tree/supercookie.module?h=8.x-1.x -- no other hooks or setup required.

    skaught’s picture

    it is fine to link to the source, as you are doing. but u do realize, your module is not loading from that source -- i've just tested it. As such, i'll file a related issue on your project as your hook_requirements() isn broken.

    but yes, if your were linking to that server to load it would be on the 'bad practice side' -- but one issue at a time. (:

    johnalbin’s picture

    To mention: Bower (which would use /node_modules folder complicates things too much. especially as we're not using nodejs.

    To clarify: Bower does not use node_modules, npm does. Bower puts things in a bower_components folder unless you override it with .bowerrc.

    it's not about how you downloaded it to your file system...it's about sharing these plugins between modules.

    Agreed.

    Front-end devs have lots and lots of choices on how to download and manage their 3rd party assets. So, if you are building a custom theme, you should choose one of them. Then just write a [theme].libraries.yml to wire them up to the rest of Drupal. That, at least, is obvious. So if you are writing a custom theme, move on; this issue is not about you.

    Given Drupal 8's new /modules and /themes folder, it also seems obvious to me that people who are NOT writing custom themes, should put their 3rd party JS/CSS assets in /libraries. Libraries API module is in desperate need of an official 8.x release to help manage those assets. Until that is released, this issue is stuck IMO.

    PHP components should be managed with composer. Period. Which means they end up in /vendor. That seems pretty obvious too.

    I'm a themer and if I'm ever on a project it is because there is a custom theme, so the other options never apply to me. /unsubscribe and good luck!

    skaught’s picture

    don't tune out just 'cuz your A Themer!

    (: composer: the other kettle of fish.

    When we speak about Libraries API we do limit to JS frameworks and plugins -- generally. I know on the D7 line is does support php packages as well, currently not sure where D8 line stands. but really they are all just 'external libraries'. Regardless of what tool you used to download them.

    Certainly, I'm as interested in a 'best practice for php classes/libraries' (including those that don't need an autoloader/doesn't comply to psr4..) -- but just need a good old required_once() for a library that shouldn't be included in a drupal git repo... I've been trying to find a clear clear document/outline about that on d.org as a module/theme needs to tell a user to 'just setup composer to download it to the vender folder, not the /libraries folder' we have a confusing break.

    Of course, this is all in terms of releasing a contrib module. not what or how you do it for your own client projects, in your own repo. But of course, a good build process (contib ready, or not) makes for a maintainable project.

    Composer is a common tool.. not the only one:
    I can find lots of 'how to use composer' but nothing to clarify a best practice for PHP packages for Contrib modules/themes. After all, that package may not be listed on https://packagist.org for composer to download. OR, the person who has to get that library, may not have composer installed, nor be able to install it..

    Generally speaking, the /vender folders is 'for core assets'. ie:

    • DRUPAL_ROOT/vender is for php assets used by core. (are now part of core)
    • DRUPAL_ROOT/core/assets/vender is where core is putting the JS frameworks used internally.

    if we keep to the idea that you shouldn't 'hack core' then i don't think we should be altering, nor adding to those locations. Keeping them clean from the things we are Extending is a good idea. After all, you wouldn't want a site builder to alter any of the version of composer downloaded files because they think 'it'll be okay'
    I think the /vendor folder should NOT be in root--it's confusing here, for that reason. Making the /libraries folder the best practice to place 3rd libraries any 3rd party PHP need should still included there too. -- and loaded by the Libraries API once defined to \Drupal

    Crell’s picture

    SKAUGHT: The /vendor folder belongs to composer exclusively. Period. If you put something there manually, from any language, you're doing it wrong. As of 8.1, it's not just for core as core no longer has a vendor directory in Git. (It's pre-generated for the tarball for simplicity only.)

    Some of the recommended practices around bridging from a Composer world to the Drupal module world are still evolving. For modules, it starts with them having a composer.json file and referencing their packagist dependencies. If they need a 3rd party repo for now for some reason, they need to document that users of the module need to add that repository to their top-level composer file.

    At this point, any publicly available PHP package (ie, not some company-internal library) that is NOT on Packagist is simply wrong. It's not like Javascript or Go where there are several competing packaging systems. PHP has only one packaging system in 2016, and it's Composer. If there's some 3rd party library you want to use that is on GitHub but not available through Composer, the Drupal-friendly way to handle that is to submit a PR to the project to add a composer.json file and ask the maintainer to add it to Packagist. That's not a situation Drupal can, or should, try to adapt for.

    [Edit: Added a rather important clause to the end of the first sentence of the second paragraph, because the sentence made no sense whatsoever otherwise.]

    skaught’s picture

    Thanks for the clarification Crell

    ==

    adding related link. (still looking for some more issues/doc's.)

    jelle_s’s picture

    This issue seems to put its main focus on JS (and CSS) libraries. What if I want to include a PHP library?

    Where do I put / how do I download (composer, manually, ...) a:

    • PSR-0 compatible library
    • PSR-0 incompatible library

    And how do I load them in code?

    skaught’s picture

    True: the focus here is on JS/CSS, also more specifically toward preparation for module/theme back to Contrib*.

    Assuming this is for your own project/client, from what i can best suggest about PSR incompatible is to use basically the good old require_once() in you module.

    PSR-0 compatible (not PSR-4)
    I might assume that anything installed with composer (into /vendor) can be read and picked up by a use statement ?? i think.. PSR-4 effects drupal modules/theme loading more-so than what's in /vendor

    Please anyone (@Crell) correct me as needed..

    @Jelle_S
    otherwise: coming from what Crell has previously posted..
    --> file a request/issue on that library to conform to PSR4 (yes, wait to see if/when they will complete that work)
    --> OR, fork it yourself an re-work it to become PSR4.

    @DX
    Otherwise, We do need documentation for composer/psr4/non-psr use in core (*not intended for contrib work). In Searching D.org I can only find issue tickets ‘to move to psr4’ and the like.. but nothing more usefully for many of these ’real world’ situations. This is an aside conversation to this direct document..but not disconnected.

    Crell’s picture

    For a 3rd party PHP library available via Packagist, just use Composer. Whether the library uses PSR-0, PSR-4, or a manual classmap is irrelevant; Composer will take care of it and you do not need to worry about autoloading or including anything. For a 3rd party PHP library NOT available via Composer, smack^H^H^H^H work with the developer to get it listed on Packagist. :-)

    For Drupal modules, they are automatically wired up using PSR-4 by virtue of being enabled if you use the src directory correctly. If you aren't, the module simply won't work anyway. :-)

    It's 3rd party JS libraries that are being discussed, because those are the ones that don't have a clear straightforward answer. 3rd party PHP is a more or less solved problem.

    kevinquillen’s picture

    Just to add in here, third party JS plugins or libs aren't strictly front end only. I have a handful of issues risen for a variety of CKEditor plugins who all want maximum flexibility in the location of the plugin in the filesystem (from ckeditor.com). So far, I have received the following feedback:

    • Could be in /libraries (outside core)
    • Could be in profiles/(profile)/libraries
    • Could be in /(not-drupal)/(drupal-root)/sites/all/libraries
    • Could be in sites/all/libraries

    I have advised via install docs to place them in /libraries, but not everyone want to do that, either by preference or technical requirement. It seems kinda silly to me to require LibrariesAPI in a very small module and force that unto others, particularly with no stable release yet.

    I prefer the /libraries approach in the root best, and given how composer downloads to /vendor, this would be consistent behavior to me. Perhaps that's just my bias in doing CKEditor plugins and implementing its getFile method to point at the actual plugin.

    I am sure there is a long and thoughtful history on it, but if there is no way to avoid LibrariesAPI really even for the smallest of modules, is there an initiative to adopt it into core? I really just want to call one function or service and have it detect the library.

    sprite’s picture

    With regard to D8 modules and libraries:

    Increasing, as I experiment to D8 to see if it will be usable at some point in the future, the following serious design problem with the "new" Drupal has become apparent.

    Requiring the command line interface tool "composer" to install components such as modules and libraries into Drupal will severely limit the Drupal CMS user audience.

    Not everyone has SSH access to their Drupal installation environment, not is it easy to obtain from many server providers!

    Turning Drupal into a programmer only oriented tool, just seems really foolish.

    Please return to an design model and module installation system that doesn't involve running CLI shell commands on a unix terminal.

    As an alternative, every such module ought to have a means for installing all the necessary parts without access to SSH or any other CLI environment.

    This direction of forcing Drupal CMS users to have access to command line interface (CLI) environments, and requiring the use of CLI tools seems likely to seriously reduce the number of people who will use Drupal to build websites.

    p.s. you'll notice from my drupal.org profile that I've being developing with Drupal for ten (10) years (not a newbie)

    kevinquillen’s picture

    That is not entirely true.

    You can obtain modules or themes via:

    • Drupal tarballs, downloaded directly from site
    • Drush
    • Drupal Console
    • Composer

    Drush is a CLI that served to boost Drupal rather than hinder it years ago. Drupal Console and Composer will do the same, but they are not required.

    dkre’s picture

    I completely agree with #65

    The lack of determined direction with libraries has led to variable approaches and is made worse by where the state of things were when a contrib module was ported.

    A great example from my experience so far with D8 is address. The documentation states it must be installed (library and module) with composer. That's OK if that was a core requirement to run Drupal and that's really where this is all getting a bit messy.

    I originally picked up Drupal 4 or so years ago because it was very functional without needing to code (although very tricky to learn and understand). I grew into a pretty 'happy hacker', learning php thanks to field preprocessing and templating with D7 and I guess with that experience this craziness with Drupal Console, Drush and Composer are pretty easy to deal with.

    What I mean is that when I started with D8 and was reading docs, tutorials or howtos I knew the alternatives to Composer, DC and Drush when they came up but how is a new user going to see this? Drush and DC are used so often in docs now that they honestly seem like they are requirements to do anything.

    Don't get me wrong, I love drush and composer (I haven't needed DC yet) but this is having build 40 odd Drupal 7 sites and as pointed out, the requirement to need SSH to use a CMS is a hard sell. If it is required, great, provide a clear direction and understanding for users.

    On my first D8 project (current) I have used the following to source/specify libraries and modules:

    1. *.libraries.yml
    2. Composer (packagist)
    3. Composer (Drupal.org)
    4. Libraries Module
    5. Drush
    6. Git
    7. Update

    The frustrating part about all of this is the technical debt. More complexity means more documentation, more training. I chose Drupal 8 as a base platform for my employers websites and services so I need to eventually document the maintenance of this beast. This crazy voodoo is hard to map out.

    Although this is a discussion about js/css specifically I think the whole external library eco-system and Drupal's documentation are pretty well aligned to this.

    jrockowitz’s picture

    As previously mentioned, Composer is to PHP as Bower is to JS and CSS. The problem is Browser is written in node.js.

    What about looking into BowerPHP?

    The best case scenario, is that it just works. The most likely scenario is the Drupal community has to contribute to this project.

    phenaproxima’s picture

    IMHO, Composer is pretty vital to even surviving in the modern PHP ecosystem. As long as drupal.org's build system can be changed to support Composer in order to accommodate the people who are stuck with tarballs (something I discussed in Dublin with @Mixologic, @drumm and @hestenet), I can't think of any particular reason to avoid Composer-based solutions for installing and packaging libraries. Personally, I think the transition to Composer is something everyone will have to do eventually, despite the steep learning curve.

    @webflo told me about this packagist at DrupalCon Dublin: https://asset-packagist.org

    Could we maybe leverage something like that to install front-end dependencies using Composer? This is something Lightning may begin to leverage soon -- we are currently using a rather janky NPM/Bower-based setup that I am itching to be rid of, and this looks like the way forward. Could it work for core and the wider Drupal ecosystem as well?

    skaught’s picture

    As ever, i think it's as important to be using a combination of current tools and methodologies in all our developments. Tools like Composer and Bower are just another part of that.

    A worthy mention: Homebrew | os x package manager -- making installing node/composer (and so much more) a breeze.

    kevinquillen’s picture

    Homebrew is a great way to install all of those packages on Mac.

    As for Bower, there is already a shift moving away from it as npm improves.

    mausolos’s picture

    Not sure how this became a conversation about build/dev tools. Simple question as a long-term D6/D7 guy who just downloaded D8 for the first time: where the f*** do I put my ckeditor/jquery plugins? sites/all/libraries was a simple, straightforward response. Stick it in libraries and forget about it. Seriously, this is basic stuff and should be in core by now.

    What are you folks doing in the wild on production sites? What's the current status quo?

    samuel.mortenson’s picture

    @mausolos I think build and dev tools come into play here because more and more production sites are using Composer - but not all JS libraries are published as Composer packages. So you end up in a sticky situation where you either fork the libraries to add composer.json or only use packaged releases of JS libraries.

    Most people are placing libraries in /libraries or in a site-specific directory like /sites/domain.name/libraries, that hasn't changed much. What developers are running into is a problem where Drupal 8 has provided us with the concept of "Libraries", i.e. groups of CSS/JS that can be included in various places, but didn't add the functionality that Libraries API module provided or address issues around how JS libraries fit in with the Composer ecosystem.

    The user stories that need to be figured out are listed in the issue summary under "stories that need to be worked out in the documentation".

    samuel.mortenson’s picture

    Just to throw another variable into this already complex issue, Drupal 8.3 is going to ship with a package.json file - http://cgit.drupalcode.org/drupal/tree/core/package.json?h=8.3.x

    benjifisher’s picture

    Issue summary: View changes
    cosmicdreams’s picture

    Here's a user story I feel is important:

    As a developer, I want to be able to construct my project so that my dependencies are handled by a package manager.

    As many before me have stated, this doesn't mean composer only. But it would be great to be able to keep things simple and handle all the dependencies. Which could be possible with a little added effort.

    Here's the current composer.json: http://cgit.drupalcode.org/drupal/tree/composer.json?h=8.3.x

    Note the inclusion of a drupal-module, drupal-theme, and even a drupal-profile types. We could add a drupal-library type. Then the relevant section would look like:

    "extra": {
            "_readme": [
                "By default Drupal loads the autoloader from ./vendor/autoload.php.",
                "To change the autoloader you can edit ./autoload.php."
            ],
            "merge-plugin": {
                "include": [
                    "core/composer.json"
                ],
                "recurse": false,
                "replace": false,
                "merge-extra": false
            },
            "installer-paths": {
                "core": ["type:drupal-core"],
                "libraries/contrib/{$name}": ["type:drupal-library"],
                "modules/contrib/{$name}": ["type:drupal-module"],
                "profiles/contrib/{$name}": ["type:drupal-profile"],
                "themes/contrib/{$name}": ["type:drupal-theme"],
                "drush/contrib/{$name}": ["type:drupal-drush"]
            }
        },
    

    Or maybe

    "libraries/{$name}": ["type:drupal-library"],
    

    Then packages could be made to provide that type.

    If you don't like the fact that we would have to embrace and extend a bunch of frontend packages in order to accomplish this we could do something like this instead.

    "extra": {
            "installer-types": [
                "library"
            ],
            "installer-paths": {
                "docroot/core": [
                    "type:drupal-core"
                ],
                "docroot/libraries/{$name}": [
                    "type:drupal-library"
                ],
                "docroot/modules/contrib/{$name}": [
                    "type:drupal-module"
                ],
                "docroot/profiles/contrib/{$name}": [
                    "type:drupal-profile"
                ],
                "docroot/themes/contrib/{$name}": [
                    "type:drupal-theme"
                ],
                "drush/contrib/{$name}": [
                    "type:drupal-drush"
                ],
                "docroot/libraries/<explicit name of library>": [
                    "<packagist name for library>"
                ]
            }
        }

    By doing this we would need to require the use of the "oomphinc/composer-installers-extender": "^1.0", library but it works.

    jaypan’s picture

    I'm the maintainer of the jQuery Colorpicker module, and I tried to set it up to work with composer for version 8 of the module.

    I've finally decided to drop that for two reasons however:

    1) The JS and CSS files in the vendor folder are blocked for some reason. I'm not sure if this is a configuration problem on my system, but I found it to be the case for any css and js file in the /vendor folder.

    2) Going with composer means people who don't have command line access, or don't know how to use it, are cut off from the module.

    So, I'm going with a manual download, and using the /libraries folder.

    It's disappointing that Drupal 8 hasn't come up with a consistent method of how to deal with 3rd party libraries, and actually seems to have regressed from Drupal 7, which had hook_library(), while drupal 8 has dropped it without a proper replacement.

    andypost’s picture

    We use bower to manage libraries for custom themes and I see no reason to change it to composer that about PHP

    zet’s picture

    Using bower to manage external libraries just makes it hard or even impossible in some(most) cases to install Drupal on shared hosting environments, meaning Drupal might loose many of his possible users.

    kevinquillen’s picture

    Thats not true, you can build locally (artifact) and push to remote. You don't need the tools themselves on the production server. A lot of people are already taking this approach since you wind up using Composer with Drupal 8 anyway.

    However, I do see bower fading in popularity - if you look at the commit log, not a lot is happening. Also, people are discussing npm / webpack as a replacement workflow. But that is neither here nor there. As far as losing users... it is almost impossible to theme and do front end work these days without JS workflows and package managers.

    You can leverage something like the Drupal Composer project or Acquia BLT for a build workflow, in which case you can designate build tasks (like run bower install or gulp sass builds) which build the artifact that is pushed. This definitely works on shared hosting.

    geerlingguy’s picture

    See related (possibly duplicate), issue opened as a result of discussions at a Composer BoF at Druplicon Baltimore 2017: #2873160: Implement core management of 3rd-party FE libraries.

    lpalgarvio’s picture

    Forcing external libraries to go where Drupal wants them to be is NOT manageable.
    https://www.drupal.org/node/2873160#comment-12066099

    nod_’s picture

    Issue tags: +JavaScript
    hansfn’s picture

    Added #2873160: Implement core management of 3rd-party FE libraries as related issue. Didn't dare to close this one as a duplicate ;-)

    leewbutler’s picture

    Here's the "centralized front end dependency tracking" approach I plan to take on a pending Drupal 8 project. We'll be using BOWER (could be any other tool) along with "hook_requirements" like so:
    https://gist.github.com/leewbutler/432833a7ed14900778b4248e381e6040

    That is our project's planned standard. But as mentioned, some contrib module devs are making the effort to fit their front end libs into other desirable standards. Like how "chosen" outlines a few contortions to get their's into the "libraries" directory via "composer.json"
    http://cgit.drupalcode.org/chosen/tree/README.txt?h=8.x-2.x

    In light of our project's standards, this raises the potential issue of 2 different dependency tracking jsons (composer & bower) having some overlap. In that case we'll decide which tracker wins, and have the other one do an exclusion. Not too bad but definitely a bit of a cognitive load. A universal standard will be great.

    andypost’s picture

    I faced with a question about library dependencies - looks docs missing to mention about a need to declare each dependencies

    For example theme library depends on jquery.once so it's not clear should I declare dependency on jquery as well or it will be picked from jquery.once

    joegl’s picture

    Are people still going to be able to setup Drupal sites with only FTP access? Is Drupal 8 abandoning all non-composer/package-manager related support? Reading a few of these threads is both daunting and concerning considering the majority of the time I simply want to use a standardized CSS or JS file across two separate modules as a dependency. I love creating modules in D8 as a developer, but I cannot imagine the task of setting up a Drupal 8 site as a beginner. But maybe I am digging too deep/out of touch? I find the posters who are concerned about losing a share of Drupal market-base are resonating with me here.

    I have to agree with Jaypan (#77) here.

    jaypan’s picture

    The JS and CSS files in the vendor folder are blocked for some reason. I'm not sure if this is a configuration problem on my system, but I found it to be the case for any css and js file in the /vendor folder.

    I wrote this over a year ago, and now I've created a solution with the Vendor Stream Wrapper module that creates a vendor:// prefix to allow linking of CSS and JS files in the vendor directory.

    skaught’s picture

    @Jaypan. very nice tool.

    samuel.mortenson’s picture

    @jaypan This is a solution I hadn't thought of before, thanks!

    joykalinfotech’s picture

    Issue summary: View changes
    skaught’s picture

    for composer based library managment I've just been introduced to balbuf/drupal-libraries-installer | github as a great tool for simplifying installing through composer

    rodrigoaguilera’s picture

    I think if we aim to handle the external libraries using composer we should aim for a better experience than the drupal libraries installer plugin that allows to require libraries and update with composer comands if those libraries have dependencies composer will also download with one single require.

    This was proposed as an addition tho the composer project
    https://github.com/drupal-composer/drupal-project/pull/286

    sallybaker’s picture

    Priority: Critical » Normal
    Issue tags: -8.x, -JavaScript +8.x, +JavaScript

    Downgrading priority as it is does not qualify under the Critical definition provided on the Priority levels of issues page: https://www.drupal.org/core/issue-priority

    berdir’s picture

    Note: See https://www.drupal.org/node/3099614, that is now in 8.9, that means it is now possible to drop the libraries.module use case, drupal core will automatically find the library in the defined locations if you use /libraries/.... See the following dropzonejs issue for a backwards-compatible (libraries.module + core) implementation with requirements checks and optional libraries: #3099836: Use new LibrariesDirectoryFinder

    fgm’s picture

    Also, side note about assets-packagist: the naming format it implies is broken by Composer 2.0 which is almost upon us already.

    eelkeblok’s picture

    @fgm Could you elaborate (possibly with a link to a downstream issue, otherwise some more details)?

    fgm’s picture

    I guess this issue is pretty typical: https://github.com/hiqdev/asset-packagist/issues/103 haven't seen @seldaek final decision on this yet.

    eelkeblok’s picture

    Thanks for the context, that helps.

    skaught’s picture

    re #96
    3099614 and 3099836 do change landscape.

    #667058: Add a libraries folder with a README.txt in it to DRUPAL_ROOT should also document this.

    jungle’s picture

    As #474684: Allow themes to declare dependencies on modules just landed in Drupal core.

    I would like to suggest 3rd-party libraries as modules, just like http://drupal.org/project/jquery_ui and its relevant modules.

    Pros:

    • Reusable among themes and module
    • Easy to use, supports both composer way and non-composer way

    Cons:

    Having third party libraries that are hosted elsewhere on the Internet in the Drupal.org repo is strongly discouraged

    From https://www.drupal.org/node/422996

    markhalliwell’s picture

    Short answer: Yes, but not as separate individual modules (like we have been doing; it's not sustainable). We need a singular and authoritative module that can download/install and manage 3rd-party libraries, something like https://www.drupal.org/project/cdn_library and https://www.drupal.org/project/jsdelivr (and other subsequent CDN providers that utilize a singular CDN API).

    Long answer: see #2873160-69: Implement core management of 3rd-party FE libraries (and further, but really the entire issue should be read)

    hazit’s picture

    Of all of these #64 and #65 made the most sense to me.

    On a shared hosting environment it would be great if we could simply maintain libraries in a folder like /Home/[accountname]/Libraries outside of the Drupal root folder.

    An equivalent would be storing private files in a folder like /Home/[accountname]/Files.

    Would this be possible?

    ryan.ryan’s picture

    Webform module is a good case study for how difficult external library management is and how much of an issue it can be. Currently, a D9 site on Drush 10 and Composer 2 following Drupal's best practices will have a difficult time of it. The webform module maintainers are working hard to provide multiple very creative methods for library inclusion, but it's a headache and a lot of code to maintain/update for different use-cases. All that to say, we need to keep this conversation going. External JS/CSS libraries are only going to become more common.

    skaught’s picture

    Issue tags: +outdated

    Certainly this document is outdated now. Perhaps it is time for a new Best practices for handling external libraries in Drupal 9

    issue and retire this.

    Yes, Webform does provide a great general sample of the current best in using composer.libraries.json as part of it's Composer setup.
    https://git.drupalcode.org/project/webform/-/tree/8.x-5.x

    fgm’s picture

    Just as a data point to avoid rushing to that solution, a few months ago only, I had unsolvable issues using the then-current version of Webform with some combination of Drupal / Drush / Console / Webform + patches, precisely due to the peculiarities of their composer.json. Maybe this has been fixed recently, though (I no longer have any site with webform to check).

    skaught’s picture

    #106 - i could only hope that the related causes you are referring to aren't most directly related to how to use composer to 'install' a library but more related to a normal project issue/bug. you could look into that projects issues and patch if you need to post-debug that situation
    in relation to 'Console & drush' - yes, they have both had flux in project lifespan in recent days, i would say..

    aaronmchale’s picture

    Issue tags: -outdated

    Re #105 no need for a new issue, we can still use this one, if it needs to be repurposed/updated then by all means. Also removing "outdated" tag as if an issue is outdated we already have a status for this: Closed (outdated).

    anybody’s picture

    Using hook_requirements to check for the existence of the third party libraries still seems a bit like a hidden secret and requires a lot of boilerplate code, once found. While much of the information needed to determine the existence and source of the library for the status page should be available in the .libraries.yml file already?
    Issues like:
    #2231385: Verify that the library files exist & #3200972: Add checks for 3rd party libraries on Status page. (possible duplicated) aim to solve that, but seem to got stuck.

    Anyway, I think that an out-of-the-box core solution might be better than copying over a lot of boilerplate code for the hook_requirements implementation into every contrib module using libraries? But even for that, I couldn't find good documentation.

    From my perspective, this first needs some core decisions for what is desired. That plan should also include decisions and roadmap for #2873160: Implement core management of 3rd-party FE libraries in my opinion.

    andypost’s picture

    Title: Best practices for handling external libraries in Drupal 8 » Best practices for handling external libraries in Drupal 8/9 and 10

    better title

    avpaderno’s picture

    Issue tags: -8.x
    heilop’s picture

    Title: Best practices for handling external libraries in Drupal 8/9 and 10 » Best practices for handling external libraries in Drupal 8/9/10 and 11

    Include Drupal 11 version to Title.