In this post I'm going to give a quick example of how to compress and combine CSS and JS files in a build step, and to link these up in your .net application using razor. It's so damn easy that there's no reason why your next project shouldnt use it. I'm going to assume that you already know about MSBuild.
A special note: Since we're dealing with combining files, it is worth noting that your CSS needs to be done right (of course!). If you have overriding styles for certain pages, you'll need to make sure that your CSS targeting is more specific otherwise your pages might look strange.
Lets begin....
First, get YUI:
http://yuicompressor.codeplex.com/documentation
I put YUI under a root tools folder: \Tools\YUI\
MSBuild
The following file will compress all files under \css and \scripts folders, into single files: minified.css and minified.js (respectively). See the properties MinifyCssOutput and MinifyJSOutput if you want to change these file names. You can exclude files using the properties MinifyJsExclusions and MinifyCssExclusions.
The following code should be self explanatory:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="RunAll" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<UsingTask TaskName="CssCompressorTask" AssemblyFile="..\..\Tools\YUI\Yahoo.Yui.Compressor.Build.MsBuild.dll" />
<UsingTask TaskName="JavaScriptCompressorTask" AssemblyFile="..\..\Tools\YUI\Yahoo.Yui.Compressor.Build.MsBuild.dll" />
<!-- Settings -->
<PropertyGroup>
<!-- Define output files -->
<MinifyCssOutput>$(TargetPath)Css\Minified.css</MinifyCssOutput>
<MinifyJsOutput>$(TargetPath)Scripts\Minified.js</MinifyJsOutput>
<!-- Define files to exclude-->
<MinifyJsExclusions>$(TargetPath)scripts\jquery-1.8.2.min.js;$(TargetPath)scripts\somefile.js</MinifyJsExclusions>
<MinifyCssExclusions>$(TargetPath)Css\SomeFolder\*.css;$(TargetPath)scripts\somefile.css</MinifyCssExclusions>
</PropertyGroup>
<Target Name="RunAll">
<Message Text="RunAll"/>
<!-- Ensure output files do not already exist -->
<Delete Files="$(MinifyCssOutput)" />
<Delete Files="$(MinifyJsOutput)" />
<CallTarget Targets="Minify"/>
</Target>
<Target Name="Minify">
<Message text="Compressing JavaScript and CSS files"/>
<!-- Define files to include -->
<CreateItem Include="$(TargetPath)Scripts\**\*.js" Exclude="$(MinifyJsExclusions)" >
<Output TaskParameter="Include" ItemName="JsFiles"/>
</CreateItem>
<CreateItem Include="$(TargetPath)Css\**\*.css" Exclude="$(MinifyCssExclusions)">
<Output TaskParameter="Include" ItemName="CssFiles"/>
</CreateItem>
<!-- Do compression -->
<CssCompressorTask
SourceFiles="@(CssFiles)"
DeleteSourceFiles="false"
OutputFile="$(MinifyCssOutput)"
CompressionType="Standard"
LoggingType="Info"
PreserveComments="false"
LineBreakPosition="-1"
/>
<JavaScriptCompressorTask
SourceFiles="@(JsFiles)"
DeleteSourceFiles="false"
OutputFile="$(MinifyJsOutput)"
CompressionType="Standard"
LoggingType="Info"
LineBreakPosition="-1"
/>
</Target>
</Project>
The file can be called from your main MSBuild file using:
<MSBuild Projects="$(MSBuildStartupDirectory)Build\Minify.msbuild"/>
Note: My MSBuild transform files are in a root build folder: \Build\Transforms\, and my YUI files are under \Tools\YUI\, so you'll notice that my AssemblyFile attributes start with ..\..\Tools\YUI. Change this and any other paths to fit your folder structure.
Modifying your layouts
All you need to do is add the following razor code to your layouts...
Put this in your <head>
@if (HttpContext.Current.IsDebuggingEnabled)
{
@*put your css files here*@
<link href="/css/layout.css" rel="stylesheet" type="text/css" />
<link href="/css/someother.css" rel="stylesheet" type="text/css" />
}
else
{
<link href="/css/minified.css" rel="stylesheet" type="text/css" />
}
Put this in where your javascript files are. I like to put it at the end of <body>. Note: I put jQuery in the <head>. I think this is useful but some may disagree.
@if (HttpContext.Current.IsDebuggingEnabled)
{
@*put your js files here*@
<script src="/scripts/site.main.js" type="text/javascript"></script>
<script src="/scripts/someother.js" type="text/javascript"></script>
}
else
{
<script src="/scripts/minified.js" type="text/javascript"></script>
}
You probably already noticed that when your application is in debug mode, then all the files will be rendered, otherwise only the minified file is rendered.
If you have nested layouts, that's fine. You can have the "if" statement at all levels, just don't include the "else" part in the child layouts.
Conclusion
Minification and combination of CSS and JS files is dead simple! Do it!
Enjoy!