Packer for .NET

Recognition

It was great to see that Scott Hanselman has placed Packer for .NET on his annual list.

Included Packages

What is it?

Packer for .NET is a tool derived from Packer which reduces the size of JavaScript files. The changes made with Packer for .NET include a command-line version which uses the same classes included with the official Packer download. This command-line tool can take multiple filenames to compress them all together into a single packed output. The existing WinForms version limited the amount of text allowed in the input window and did not take filenames as input. This re-packaged version makes it easier to automate build and deployment tasks.

Packer for .NET also supports a mode to use JSMin. It uses a different process which simply strips comments and whitespace from the source scripts. In the cases where the Packer mode is unable to transform a script it may be possible to use JSMin instead.

Packer versus JSMin?

The merits of Packer and JSMin can be measured in file size and time to interpret. While Packer can created a much smaller output file it can be more problematic with packing JavaScript that does not conform to a strict syntax. JSMin still prefers that you use semicolons at the end of each line, but it tends to have fewer problems with parsing and minifying the output. Beyond file size, the time it takes interpret a packed/minified JavaScript file should also be a consideration. Resig ran a series of tests with Packer and JSMin and determined that JSMin appears to give you the best of compression and time for interpretation while Packer does have a performance hit when it has to be unpacked and interpreted.

One tool to assist with ensuring JavaScript works well with Packer and JSMin is JavaScript Lint which integrates well with Visual Studio. See the links below.

CSSMin

You can now shrink your CSS Files with the new CSSMin mode. You simply select this new mode and your comments will be stripped and various optimizations will be run on your stylesheets. More Info

Combine

One new mode added in version 4.1 is Combine which simply appends each of the specified files into a single file. This can be useful if you wish to take all of your stylesheets and combine them into one for use in a Production environment after using them as separate files which are easier to maintain with multiple developers during development.

Command-line Usage

Usage: Packer [-?|-h] [-o <filename>] [-m <packer | jsmin | cssmin | combine>] <file1> <file2> ...

 Options:
  -h or -?              Help
  -o <filename>         Output Filename
  -m <packer | jsmin>   Mode

MSBuild Usage

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Import Project="$(MSBuildExtensionsPath)\SmallSharpTools.Packer\MSBuild.Packer.Targets" />

  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Environment Condition=" '$(Environment)' == '' ">Production</Environment>

    <PackerOutputFileName>packer.msbuild.js</PackerOutputFileName>
    <JSMinOutputFileName>jsmin.msbuild.js</JSMinOutputFileName>
    <CSSMinOutputFileName>cssmin.msbuild.css</CSSMinOutputFileName>

    <WebConfigPath>$(SampleFilesDir)\Web.config</WebConfigPath>
    <WebConfigOutputPath>$(SampleFilesDir)\Output\Web.config</WebConfigOutputPath>

    <!-- Development -->
    <AppSettings Condition=" '$(Environment)' == 'Development' ">
      Environment = Development;
    </AppSettings>

    <!-- Staging -->
    <AppSettings Condition=" '$(Environment)' == 'Staging' ">
      Environment = Staging;
      SSL.Enabled = false;
    </AppSettings>

    <!-- Production -->
    <AppSettings Condition=" '$(Environment)' == 'Production' ">
      Environment = Production;
      SSL.Enabled = true;
      SSL.Host = https://www.acme.com
    </AppSettings>

  </PropertyGroup>
  <ItemGroup>
    <JavaScriptInputFiles Include="scripts\*.js" />
    <CSSInputFiles Include="scripts\*.css" />
  </ItemGroup>
  <Target Name="Build">
    <Packer OutputFileName="$(PackerOutputFileName)" Mode="Packer" InputFiles="@(JavaScriptInputFiles )" Verbose="false" />
    <Packer OutputFileName="$(JSMinOutputFileName)" Mode="JSMin" InputFiles="@(JavaScriptInputFiles )" Verbose="false" />
    <Packer OutputFileName="$(CSSMinOutputFileName)" Mode="CSSMin" InputFiles="@(CSSInputFiles )" Verbose="false" />

    <!-- Development -->
    <UpdateWebConfig Condition=" '$(Environment)' == 'Development' "
        WebConfigPath="$(WebConfigPath)"
        OutputPath="$(WebConfigOutputPath)"
        ConnectionStringConfigSource="$(ConnectionStringConfigSource)"
        AppSettings="$(AppSettings)"
        Debug="true"
        CustomErrorsMode="Off"
        MailHost="localhost"/>

    <!-- Staging -->
    <UpdateWebConfig Condition=" '$(Environment)' == 'Staging' "
        WebConfigPath="$(WebConfigPath)"
        OutputPath="$(WebConfigOutputPath)"
        ConnectionStringConfigSource="Configurations\\connectionStrings-staging.config"
        AppSettings="$(AppSettings)"
        Debug="false"
        CustomErrorsMode="Remote"
        MailHost="staging.acme.com"/>

    <!-- Production -->
    <UpdateWebConfig Condition=" '$(Environment)' == 'Production' "
        WebConfigPath="$(WebConfigPath)"
        OutputPath="$(WebConfigOutputPath)"
        ConnectionStringConfigSource="Configurations\\connectionStrings-production.config"
        AppSettings="$(AppSettings)"
        Debug="false"
        CustomErrorsMode="On"
        MailHost="mail.acme.com"/>

  </Target>
</Project>

UpdateWebConfig

The UpdateWebConfig task is new in version 4.1. It is a simpler option than the XmlUpdate task which is a part of the MSBuild Community Tasks. Instead of providing an XPath value to map out replacements, this UpdateWebConfig task makes it easy to replace commonly updated values during deployment, like the connection string !configSource, customer errors mode, debug mode, mail host and application settings. Not having to set the XPath for XmlUpdate show make your MSBuild script easier to read and maintain.

The UpdateWebConfig task is designed to run after a build has completed and is being prepared for deployment. The assembly is very small and can easily be included with your deployment files to carry out the UpdateWebConfig task at various points in your deployment. It is also not necessary to install Packer for .NET to use the UpdateWebConfig or even the Packer task. Refer to the test script for an example of the UsingTask directive.

For the UpdateWebConfig task the WebConfigPath must point to a valid Web.config file used with ASP.NET. And optionally the OutputPath can be set. If it is not set the output will be written to the WebConfigPath.

Also see test.proj for a working example.

More Information

Credits

Packer was originally ported to C# by Jessie Hansen. (See Packer Goes .NET)

JSMin was created by Douglas Crockford. (www.crockford.com)

CSSMin was originally written in Java by Isaac Schlueter. Then it was ported to C# by Daniel Crenna. New css tests and regexes were added by Michael Ash. Finally are additional cleaned up, commenting and refactoring by Chris Lienert it was incorporated into this project.