Home / AJAX

DLL Version of Ajax Minifier

RSS
Modified on 2009/12/15 20:59 by Stephen Walther Categorized as Uncategorized
A DLL version of the code is also distributed. It does not contain any of the advanced switching or lint-style reporting that the EXE contains, but it does provide access to the abstract syntax tree produced by the JavaScript parser. This can be highly beneficial to projects that wish to do advanced modification or examination of the parsed code tree.

If all you need is to minify input code, you can simply use the supplied Microsoft.Ajax.Utilities.Minifier object. Create an instance of the object, and pass your input code to one of the MinifyJavaScript methods, depending on the language and whether you want to override the default settings. The return value is the minified code string.

public string MinifyJavaScript(string source);
public string MinifyJavaScript(string source, CodeSettings settings);

The various CodeSettings object properties modify the way the output JavaScript is generated:

  • CollapseToLiteral: convert “new Object()” to “{}” and “new Array()” to “[].” And of course, “new Array(1,2,3,4,5)” becomes “[1,2,3,4,5]” and “new Array(“foo”)” becomes “[“foo”]”. However, “new Array(5)” does not get minified, because that makes an array with five initial slots – it’s not the same as [5].
  • CombineDuplicateLiterals: combine duplicate literals into local variables. So the code:

function foo(a)
{
    a.b = 12345;
    a.c = 12345;
    a.d = 12345;
    a.e = 12345;
}

gets changed to:

function foo(a)
{
    var b=12345;
    a.b=b;
    a.c=b;
    a.d=b;
    a.e=b
}

The savings are much more dramatic with large, frequently-used strings. Works with numbers, strings, nulls, and this-pointers. The this-pointers only get minified within the current scope, since child functions might have a different meaning for the pointer. It will also only pull out reused variables within function scopes – it won’t create a global variable with the constant, as that may interfere with other global variables. For the maximum minification, wrap all your code within a namespace function scope. Beware, though, that gzipped results may end up being larger when using this option due to the change in entropy of the resulting code.

  • EvalTreatment: Normally an eval statement can contain anything, including references to local variables and functions. If it is expected to do so, when the tool encounters an eval statement, that scope and all parent scopes cannot take advantage of local variable and function renaming because things could break when the eval is evaluated and the references are looked up. To reduce the amount of resulting minification but make sure that all possible references in evaluated code will hold true, use the MakeAllSafe value. However, sometimes the developer knows that he’s not referencing local variables in his eval (like when only evaluating JSON objects), and this switch can be set to Ignore to make sure you get the maximum reduction in resulting code size. Or alternatively, if the developer knows the code being evaluated will only access local variables and functions in the current scope and nowhere else, the MakeImmediateSafe value can be specified and all parent scopes will still rename their locals. Very dangerous setting; should only be used when you are certain of all possible behavior of evaluated code.

  • IndentSize: for the multi-line output feature, how many spaces to use when indenting a block (see OutputMode).

  • LocalRenaming: renaming of locals. There are a couple settings: KeepAll is the default and doesn’t rename variables or functions at all. CrunchAll renames everything it can. In between there is KeepLocalizationVars, which renames everything it can except for variables starting with L_. Those are left as-is so localization efforts can continue on the minified code.

  • MacSafariQuirks: There are two quirks that Safari on the Mac (not the PC) needed: throw statements always seem to require a terminating semicolon; and if statements that only contains a single function declaration need to surround that function declaration with curly-braces. Basically, if you want your code to always work in Safari, set this to true. If you don’t care about Safari (for instance, in a corporate environment where the browser your users can use is highly restricted), setting this value to false might save a few bytes.

  • OutputMode: SingleLine minifies everything to a single line. MultipleLines breaks the minified code into multiple lines for easier reading (won’t drive you insane trying to debug a single line). The only difference between the two outputs is whitespace. (see also: IndentSize).

  • RemoveUnneededCode: Should be set to true for maximum minification. Removes unreferenced local functions (not global functions, though), unreferenced function parameters, quotes around object literal field names that won’t be confused with reserved words, and it does some interesting things with switch statements. For instance, if the default case is empty (just a break), it removes it altogether. If there is no default case, it also removes other empty case statements. It also removes break statements after return statements (unreachable code).

  • StripDebugStatements: removes “debugger” statements, any calls into certain namespaces like $Debug, Debug, Web.Debug or Msn.Debug. also strips calls to the WAssert function.

If you wish to perform actions on the generated syntax tree directly, you can use the Microsoft.Ajax.Utilities.JSParser object directly. Create an instance of the object, passing in the source code you wish to parse. Calling the Parse method (passing in the same CodeSettings object) will return an abstract syntax tree node to the block representing your code.

      // create the parser from the source string.
      // pass null for the assumed globals array
      JSParser parser = new JSParser( source, null );
      string minified;

// hook the engine error event parser.CompilerError += new CompilerErrorHandler(OnCompilerError);

try { // parse the input Block scriptBlock = parser.Parse(settings); if (scriptBlock != null) { // we'll return the minified code minified = scriptBlock.ToCode(); } } catch(JScriptException e) { // other error handling }

There are two analogous methods for minifying CSS:

public string MinifyStyleSheet(string source);
public string MinifyStyleSheet(string source, CssSettings settings);

The CssSettings object contains all the settings switches available for CSS minification. Its properties are:

  • CommentMode – how to treat comments in the code. The default is CssComment.None, which will strip all comments except “important” comments. CssComment.All will leave all comments, and CssComment.Hacks will only leave certain known comment-based hacks.

  • Severity – the maximum severity level to present as errors in the output. The default is zero, meaning only syntax-error generating errors. If the developer wishes to see more detail (possible errors, warnings, style suggestions), then the severity threshold can be raised. It is a numeric integer value.

  • TermSemicolons – forces all rules to be terminated with semicolons if set to true (default is false).

  • ColorNames – by default, W3C-strict color names will be used if they are shorter than the equivalent RGB values. This is the CssColor.Strict setting. If no color names are to be used, set this value to CssColor.Hex. If a set of colors recognized by all major browser is okay to use (W3C-strict validation is not required), set this value to CssColor.Major.

  • ExpandOutput – Boolean value indicting whether to output all minified code on a single line or to break it into easy-to-read multiple lines. Default is false.

  • IndentSpaces – if ExpandOutput is set to true, this property is the number of space characters to use for each indent. The default is 4.

In addition to the Minifier object, developers can use the CssParser object directly. To minify CSS source, create an instance of the CssParser, set the appropriate Settings property values, and call the Parse method:

      CssParser parser = new CssParser();
      parser.CssError += new EventHandler<CssErrorEventArgs>(OnCssError);
      parser.FileContext = sourceFileName;
      string crunchedStyles = parser.Parse(source);