Directory Structure with Multiple Vendor Directories

Package managers are quite useful fucking awesome. However, I’ve started to notice that building any serious application with just a single vendor directory is becoming a rare thing. My usual workflow for a PHP web app these days involves Composer, npm and Bower.

I like to browse my code using the directory tree so having a sensible and coherent directory structure is important to me. Even though the vendor directories aren’t committed to the project repository, they’re still there strewn among the app, bin, public, etc directories.

The following is an example directory structure for a very basic PHP app:

- app
- public

Here is how it looks once packages are installed using Composer, npm and Bower:

- app
- bower_components
- node_modules
- public
- vendor

My gut instinct is to rename these directories to be grouped together within the tree eg have them all prefaced by vendor-.

Renaming Vendor Directories

The only progress I’ve made towards this in an active project has been to rename the bower_components directory to vendor-frontend. This can be achieved by creating a file called .bowerrc in the root project directory and configuring it like this:

{
    "directory": "vendor-frontend"
}

You can read more about the .bowerrc file on the Bower website. With this, the directory structure changes to:

- app
- node_modules
- public
- vendor
- vendor-frontend

Next up: the node_modules directory. What can I do there? Apparently, nothing. According to the npm FAQ the string node_modules is hardcoded “151 times in 53 separate files in npm and node core”. That doesn’t seem sensible to me, but I guess Node is still in pre-release so I can only hope they clear that up before version 1.0.

What about Composer? Changing the name of the vendor directory is simple enough. I can set up the composer.json file as follows:

{
    "config": {
        "vendor-dir": "vendor-backend"
    }
}

This will give us the following directory tree:

- app
- node_modules
- public
- vendor-backend
- vendor-frontend

Vendor Directory Naming Conventions

I’ve yet to settle on a naming convention for my newly configured vendor directories. The one above uses broad terms and I’m not sure I like it that much. I could instead be explicit about which language the packages are written in:

- app
- node_modules
- public
- vendor-js
- vendor-php

Again, I’m not sure that I like this one. If I ever figured out a workaround for the npm directory, what would I call that? It’s JS as well after all. I could also be completely explicit about where the packages came from:

- app
- node_modules
- public
- vendor-bower
- vendor-composer

This would future-proof it against the addition of package managers in existing languages. I could rename the npm directory to vendor-npm, if that possibility ever arose. I can also more easily link these mentally with their configuration files in the root directory: .bowerrc, bower.json and composer.json.

Another option would be to put them into a single vendor directory rather than just group them together:

- app
- node_modules
- public
- vendor
  - bower
  - composer

This would clean up the root directory a bit more. However I think I prefer keeping them in the root directory. It is one less click/tab when you need to look at the vendor code.

I’ll close with my ideal directory structure for a project, even if some of it isn’t implementable yet (or ever). Any thoughts on structuring vendor directories are welcome.

- app
- bin
- database
- lib
- public
- resources
- tests
- vendor-bower
- vendor-composer
- vendor-npm