Pregunta

I've got hold of the Ajax minifier in order to minify some JS and CSS files as part of a build/package/deploy process. It's a great tool and does exactly what we need. However, integrating this into our build/deploy process is proving very difficult.

Ideally, we want to run this tool only when we execute one of our TFS 2010 builds (i.e. NOT a local (Ctrl+Shift+B jobbie) build on a dev machine). Also, we want to replace our currently 'non-minified' files in this scenario with the minified ones (i.e. under the same file name) rather than having a load of additional files named '.min.js' etc.

After a lot of reading I think the key is for a custom build task within the workflow - but I've no idea on how to approach this - espeically as I'm looking to minify files that will have been pulled down directly from our release branch in TFS (i.e. not in someone's local workspace) as part of a TFS 2010 build.

This is the closest discussion I've found to what I'm trying to achieve: Microsoft Ajax Minifier - TFS 2010 Workflow - AjaxMin in the TFS Build

I beleive I will need a custom code activity within the build workflow but have no idea on how to create one to solve this problem. Can anyone shed any light on a process which will allow minification prior to deployment?

¿Fue útil?

Solución

OK - thanks to these answers and a lot of research... I came to the following solution :)

Starting with custom code activities, I tried to run the minifier from C# code and then called the activity as part of the workflow. This didn't work as the .dll version of the minifier exposes a couple of methods for compressing both .js and .css files and then makes you open up a StreamWriter of some kind and re-write the file with the compressed string returned from the method (if you're wanting to overwrite your existing files). Pretty intensive opening up and closing files all the day so I wasn't massively happy with that solution. Using the process class to run the .exe with the -clobber option on (for overwriting files) isn't ideal either and produced some odd results (not correctly minifying the files and writing some garbage at the head of each file).

So, you ask, the solution I settled on was to write a PowerShell script (the beginnings of which I got from here - which I then modified slightly to take a command-line parameter - which would be the root folder of your project. The script recursively goes through each file (and each sub-directory's files) and minifies the .css and .js inside. Pretty neat. The bones of which looks something like this:

$ScriptDirectory = $args[0]
Write-Host "Validating directory parameter: $ScriptDirectory"
Write-Host ""

if ((Test-Path -path $ScriptDirectory) -ne $True)
{
     #Throw an error of some kind (the parameter passed in isn't a valid directory).
}

$Minifier = “C:\Program Files\Microsoft\Microsoft Ajax Minifier 4\AjaxMin.exe”

get-childitem $ScriptDirectory -recurse -force -include *.js, *.css -exclude *.min.js, *.min.css | foreach-object {&$Minifier $_.FullName -out $_.FullName -clobber}

So we go through each child item of the root folder with an extension of .js or .css (ignoring extensions of .min.* as these have already been compressed).

In TFS, all we need to do is add an InvokeProcess step to execute the PowerShell script in TFS. You can pass your parameter in (the directory to start minifiying) using the Arguments property of the InvokeProcess activity.

To get the directory that TFS build is using to compile your code before it is released (the temporary workspace, if you like), you can use the SourcesDirectory variable available to you in the Run On Agent sequence of the build. This is the location that your files are compiled and packaged up by the TFS build process so anything that gets minified here will end up in the final deployment package.

P.S - the SourcesDirectory is quite high up - you might not want to drill all the way from there to get to your .js and .css files so you mgiht need to specify something like:

SourcesDirectory + "/" + "MyProjectFolder/Scripts"

Make sure you add this InvokeProcess step before your code is deployed in the workflow and hey-presto - you'll have minified .js and .css files, which keep the original file names only as part of a TFS build and not a local one.

Many thanks to all who answered and pointed me in the right direction. I hope this helps someone along the way!

Otros consejos

Doing this as a custom code activity is certainly doable, but you'll have to put some effort in it. My suggestion would be:

  1. First follow the TFS 2010 customisation blog from Ewald Hofman at http://www.ewaldhofman.nl/post/2010/04/29/Customize-Team-Build-2010-e28093-Part-4-Create-your-own-activity.aspx to learn aboutr creating custom activities
  2. Then take a look at http://www.ewaldhofman.nl/post/2010/06/01/Customize-Team-Build-2010-e28093-Part-10-Include-Version-Number-in-the-Build-Number.aspx from the same series to implement a mechanism to find all files that conform to a certain pattern. In that example, assemblyInfo.cs files are indexed and their content changed. Replace that by searching for your *.js files.
  3. Release the power of Ajax Minifier on your file selection and replace the original file with the minified one.
  4. Build the activity, include it as a step in the build process template you use in TFS 2010 (also described in the same blog posts) and fine tune it to the point you are satisfied with it.

Alternatively, you can ask the author of the post you have included in your question to share the Minifier TFS activity he created with us :-)

Please, let me know how that works out for you.

You need to implement an Invoke Process Activity so that Minifier gets executed during your TFS builds.

To this purpose you will also have to install the minifier in the Server(s) doing your builds, so so-called Build-Agent(s). By doing that you 'll be ensuring that the Minifier gets invoked only during your TFS-Builds (as opposed to local VS-Builds).

In order to rename your generated output files (*.min.js) you need to implement another custom activity just for that. Overwritting your checked-in files needs you to first make them writable, this means yet another custom activity (I 've provided in another answer a snippet for that).

The whole choreography is
Invoke Minifier with InvokeProcess --> make checked in files writable --> overwrite checked in files with renamed minified files.

The right way to do this in TFS build is to wrap them in a Sequence.

A good introductory blog post about how to implement an Invoke Process is to be found here.
I have also found the series by E.Hofman of real value.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top