How To

Packaging and Shipping Resource Folders

No, I don’t mean resources to get help.

Have you ever opened a plugin or theme and seen a folder that says bower_components or node_modules? Yeah, I hate those. I don’t hate Bower or Node, I use them quite a lot. I hate how people use them in their plugins.

What Are Those Folders? What Are Those Folders?

In order to make life easier, Bower is a package manager that lets you install libraries that your plugin needs. Making a plugin that needs AWS SDK?

bower install aws-sdk-js

Boom. And you can easily upgrade it too with bower update – which I love. This is a great idea.

$ bower install aws-sdk --save
bower aws-sdk#*                 cached git://
bower aws-sdk#*               validate 2.2.28 against git://*
bower aws-sdk#~2.2.28          install aws-sdk#2.2.28

aws-sdk#2.2.28 bower_components/aws-sdk

But notice that last line? bower_components/aws-sdk is where it saved my files. And if I go in there, the JS file I need is bower_components/aws-sdk/dist/aws-sdk.min.js and that is surrounded by other files:

Deep down the bower rabbit hole

Now as a developer you have a couple choices here. You can leave the file where it is and just call it from there or you can move it. If you move it, you want to make a simple way of updating it. After all, the whole point of using Bower here is to make life easier. Personally I use Grunt for these things. I talked about it last year but my basic idea is to use Bower to download the latest and greatest versions, and then Grunt takes care of (a) updating the Bower packages and (b) copying the files to where I need them.

Okay, but what if I have something a little more complex?

Top ↑

What Resources Do I Need? What Resources Do I Need?

This seemingly innocuous question is surprisingly deep. It’s not just ‘what package/library am I trying to manage’, but how do I manage it and with what? What if, instead of the javascript, I wanted to use the PHP AWS SDK instead? Well, the AWS SDK for PHP is not available in Bower! Instead it uses Composer.

Here’s where things get weird. Composer is a package manger. Grunt is a package manager. Node and Bower are too. This means I have to stop and think hard. Which one do I need? Why do I need it? What am I going to be managing?

It’s time to ask this:

Top ↑

What Are My Packages For? What Are My Packages For?

Within Node there are two kinds of packages:

  • “dependencies”: these packages are required by your application in production
  • “devDependencies”: these packages are only needed for development and testing

Take a moment to think what you need to dev and what you need to run. Your test code doesn’t need to be in your release, does it? No, of course not. It would make perfect sense to have in your Git or personal repository, but the WordPress SVN repository is not actually for your own code management. It’s a release management tool. That’s another post for another time. Just keep in mind that you should really only be pushing your code to SVN when it’s a version ready for use (be that beta testing or releases).

Back to what things are for. When talking about the AWS SDK javascript, I’m talking about front end packages. So that’s a dependancy. But Bower? It’s a devDependency. The users don’t need to know (or care) that I’m using Grunt and Bower to package things up. That means they shouldn’t be installed in my plugin!

In the case of my AWS SDK a ‘devDependency’ is Composer. I only need it to build my packages.

My dependencies are as follows:

    "require": {
	    "aws/aws-sdk-php": "2.*",
	    "doctrine/orm": "*",
	    "monolog/monolog": "*"

Adding that to my composer.json file is a simple thing and now I can just run composer update to get everything I need!

Top ↑

Where Should My Packages Live? Where Should My Packages Live?

This is generally pre-destined. If you use Node they go in node_modules and Bower likes bower_components and Composer uses vendor and so on and so forth. You can, of course, customize these. I often make a folder called ‘assets’ or ‘assets-dev’ so I can easily ignore it in my version control. Frankly I don’t need them and neither do my users and it’ll help save space.

There’s a cool thing about composer. If you use composer init then it asks, at the end “Would you like the vendor directory added to your .gitignore [yes]?” This is great, because if you looked at the folder vendor you would see a lot of folders and files you don’t really want. I actually only want one folder vendor/aws/aws-sdk-php/src/Aws/ and I want that folder to be located in aws/Aws please and thank you. Composer adds this into .gitignore for you.

You’ll still have to add that into your SVN ignore file, which is a little more annoying. To ignore all composer.* files it’s this:

svn propset svn:ignore "composer.*" .

And if you want to ignore multiple files or folders use the following command to bring up the text editor:

svn propedit svn:ignore . 

For SVN I would ignore composer.json, composer.lock, and the vendor folder.

Top ↑

How Do I Move Folders? How Do I Move Folders?

Remember I want to move things to another folder? I use Composer’s scripts to do this. I admit this is ugly code. I have this in my composer.json:

	"scripts": {
        "post-update-cmd": [
	        "rm -rf aws/Aws",
	        "cp -r vendor/aws/aws-sdk-php/src/Aws aws/",
	        "rm -rf aws/Doctrine",
	        "cp -r vendor/doctrine/common/lib/Doctrine aws/",
	        "rm -rf aws/Guzzle",
	        "cp -r vendor/guzzle/guzzle/src/Guzzle aws/",
	        "rm -rf aws/Monolog",
	        "cp -r vendor/monolog/monolog/src/Monolog aws/",
	        "rm -rf aws/Psr",
	        "cp -r vendor/psr/log/Psr aws/",
	        "rm -rf aws/Symphony",
	        "mkdir -p aws/Symphony/Component/EventDispatcher",
	        "cp -r vendor/symfony/event-dispatcher/* aws/Symphony/Component/EventDispatcher/"

This runs whenever I run composer update in this folder and it copies everything where I need it to be. I did tell you it was ugly, right? But it does work.

Top ↑

The Result? The Result?

The result is my vendor code is never uploaded to’s SVN, my users never see the stuff they don’t care about, and I have a faster way to update my plugins when I need to make sure all the packages are right.