Combining and Compressing JavaScript and CSS During Deployment
One of my favorite things to do is to automate repetitive processes, I have been a proponent of scripted build and deploy systems since I was building them for .NET 1 .1 applications with Nant and CruiseControl.
Recently I introduced a BuildMaster server into my day job. With the growing number of applications I am responsible for managing and the tight deadlines for client work I needed an easy to use and reliable tool to automate both builds and deployments. We selected BuildMaster after building proof of concept deployments with a number of tools and it stood out as one of the easiest to install and implement.
By taking advantage of BuildMaster’s set of extensions I have been able to easily accomplish most of the tasks I needed to accomplish for deploying various .NET and pure HTML applications, however there was one feature missing.
We were building an interactive pure HTML application for a client and ended up with the usual explosion of JavaScript and CSS assets from various third party libraries as well as a number of our own assets. Between the desktop specific, mobile specific and common assets we had over 25 JavaScript files and more than a dozen CSS files. During the course of development I was asked if there was a way that we could reduce the sheer number of files that we were delivering, not just to make the handoff process easier, but also to increase the performance of the application by minimizing the number of requests required to render each page. In addition, while we were using minified versions of many of the third party JavaScript files we still had our own code to deal with as well as lots of wasted bytes in the CSS files.
I looked around and while there were plenty of compression options I didn’t want to bring in an entirely new technology stack for a deployment that mainly consisted of getting files from source control and copying them to a server. I decided that I was going to integrate the asset combination and compression directly into my existing BuildMaster deployment plan by building my own extension. I chose to use the YUI Compressor for .NET project to perform the asset combination and compression.
I wanted the consolidation and compression to happen at build time so that the other developers and designers I was working with did not have to deal with minified files. On the other hand, there are still some things that can break, so I made sure my deployment plan would automatically run and push new builds out to an integration server for immediate testing and feedback.
I could have started off with the documentation for building a custom action in BuildMaster, but since I have already contributed to a number of other extensions I had a pretty good idea of what to do.
After some tweaking work I have what I think is a nice BuildMaster wrapper around the YUI Compressor and I received permission to publish the source code to this extension so that others can take advantage of this action. The source code is up on GitHub, at https://github.com/PrecisionDialogue/bmx-pd-web.
The action is mostly a wrapper around the YUI Compressor but there are a number of settings that allow you to deeply customize what is going to be done to the assets.
The input files for each asset type consist of one or more filespecs, each on their own line. Each line is also interpreted so that you can use wildcards (including the BuildMaster ~\ syntax to represent the working directory). The union of all of the matching files is what will be processed. You can also configure one or more regular expressions to denote filename patterns to be excluded. Each line of the exclusion regular expression is evaluated against the set of files and matching filenames are excluded from being combined, minified and/or deleted.
This action can combine asset files, compress asset files or do both. All activity takes place in the working directory of the files so when combining files I recommend using the “Delete original files” option to remove extraneous files.
The “Preserve subdirectories” option is useful if you use relative paths within your assets and need to preserve that structure. If you are combining files and preserving subdirectories a single file of the output name will be created in every subdirectory that has appropriate content.
If you don’t want to combine files but just need to compress them you can select the “Compress (JS/CSS) files in place” option. This option will ignore the output filename and just compress each matching artifact file. This is useful if you have path or filename dependent code in your scripts.
The rest of the options for each asset are the same as in the YUI Compressor and should work the same.
With this action I am now able to easily combine and minify CSS and JavaScript files reliably and ensure that only the correct compressed versions are promoted into the application environments.
I hope you find this useful and I am always happy to receive feedback.
- Automation Galore
- CodeMash 2014 Door Decorating Competition