This page comes from a WebReflection post. If you have any doubt, suggestion, requirement, question, please feel free to post in latest link dedicated post. Thank You.

The Story

The de facto standard, and the tool that every developer should use to optimize and to serve client files, is the YUI Compressor, a tool created to minimize with perfect precision both JavaScript and CSS.

The only real limit this tool has so far, is the single file as input if you call its execution via command line.

There are hundreds of IDE out there able to integrate this compressor and make multiple file "merge with optimization" that simple operation, while somebody else suggested poor practices to solve the problem via batch script in a truly "not that portable/scalable" way.

So, apparently, there is nothing "that serious" able to easily bring this functionality everywhere, at least in Windows (ta-da, ta-da! ... uh, no, that was Intel, sorry ...)

As example, in my company we are using Visual Studio Team System and since I am in charge of the front end development and client/server interaction over C# files, "of course there are more than 10 files" and only to manage the GUI via Ext JS library.

One of the most boring thing about ASP.NET C# development via Visual Studio, is the "missed" support for the client side.

What I mean, not considering the extremely poor native support for JavaScript code, is that WYHINWYG (What You Have Is Not What You Give, for those whose dislike the acronym tag).

Due to build process, which at least is good enough to understand which file should be copied in the built system, even if it is not under .NET control (CSS and JavaScript, I still prefer Notepad++ for these files) I need to create a batch file which aim is to quickly xcopy everything from the solution folder into the web served one.

A Web Application Should Be Entirely Compiled, not only on the server side then.

The YUI Compressor has the ability to tell us if the parsed source had something wrong, which at least from the "syntax parsing point of view", is a useful information.

Both CSS and JavaScript are not compilable yet (bytecode speaking), mainly because there will be a fight about who created the best bytecode for each standard (I bet Adobe) and how free this bytecode standard will be ... too early right now, too many conflicts between browser vendors and companies behind, but this is another story!

So how did I solve the problem?

As I twitted few days ago, in my company I created a partially clever batch file which use Java, for the yuicompressor file, Python 3000 for the UTF8BOM remover, and a Batch Script file to aggregate file operations, and everything to be able to optimize a C# application ... and this is the point when I realized "it's too much"! (to be honest, the "LOL" reply in twitter gave me a hint ...)

Testing and coding at home during the evening, as a proper geek that does never stop to code and learn breaking my own limits, I created the perfect tower of babele match in order to solve our internal build application and serve via the best way our client side based application.

This week end I did something better, I removed python 3000 dependency and improved even more what was already OKish for what I need at work.

My creature name? The yuibompressor batch file, and you read properly!

This batch script file can remove from files that for some reason have been encoded via UTF-8 BOM that triplet of characters able to make Internet Explorer useless and probably other browsers as well.

The good part is that it requires only a java runtime installation, in order to make the yuicompressor jar file usable, and it is almost fully customizable, but we need a configuration file.

The Configuration File

The main goal for this file is to prepare the batch environment in order to perform the compilation we need in a click.

If you are not familiar with batch scripting, the only thing you need to know to use my yuibompressor file is that "set" means you are setting a variable, and rem means you are creating a comment, discarding then everything comes after this keyword and before an enter.

The last important thing to know, is that being in Windows prompt environment, paths for files or folder requires just a back slash "\" and that the common web slash "/" could cause some problem. Finally, for each specified folder in the configuration file, please do not add the last back slash, or the compilation could be a failure.

In few words, if you have a file in C:\temporaryFolder, that is the right way to point to that file while C:/temporaryFolder or /temporaryFolder, considering the first slash as a root, will not work as expected.

This is important to understand how the files list should be written inside the file itself. If we need a relative parent folder, for example, we can simply use "..\anotherFolder\fileName.whatever"

Everything else has been commented inside the file itself. Please do not forget you can have any number of configuration files, as long as they call at the end the yuibompressor one.

configuration.bat

@echo off

rem ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rem ;; yuibompressor.bat configuration file       ;;
rem ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rem ;; pause program execution or each main step [1/0]
set YUI_DEBUG=1

rem ;; specify the project type [js/css]
set YUI_TYPE=js

rem ;; your project name. will produce two files
rem ;; projectname.min.[js/css]
rem ;; projectname.debug.[js/css]
rem ;; debug version is a single big file not compressed
set YUI_BUILD_NAME=vice-versa

rem ;; where are yuicompressor-ver.jar and bom file
set YUI_FOLDER=..

rem ;; a txt file with a list of files to include in the project
rem ;; NOTE: the file order is preserved
rem ;; NOTE: if YUI_FOLDER_SOURCE is not set each file must have an absolute path
set YUI_FILE_LIST=..\vice-versa\file-list.txt

rem ;; where to put min and debug version of the project
set YUI_FOLDER_DEST=..\vice-versa

rem ;; where are files specified in the list
rem ;; NOTE: if files in the list have absolute path please remove this variable
rem ;;       writing "rem" instead of "set" as prefix
set YUI_FOLDER_SOURCE=..\vice-versa

rem ;; specify if you do not want to munge file (obfuscation)
rem ;; NOTE: YUICompressor is a great tool but sometimes it could have some problem with munge option
set YUI_NO_MUNGE=1

rem ;; yuicompressor jar file version
rem ;; NOTE: this variable is used as yuicompressor-%YUI_COMPRESSOR_VERSION%.jar
rem ;;       please be sure that jar file respects this naming convention
rem ;; EXAMPLE: yuicompressor-2.4.2.jar
set YUI_COMPRESSOR_VERSION=2.4.2

rem ;; at this point is possible to call the yuibompressor file
call yuibompressor.bat

The yuibompressor File

For sharing sake, I decided to put the yuibompressor file with its comments as well, so you can understand each performed step (label) and find a solution for your batch files. The best resource I found so far is DosTips website, truly accurate and loads of hints for every headache you could have with batch scripting.

yuibompressor.bat

@echo off

rem ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rem ;; WebReflection YUI Compressor Batch Manager ;;
rem ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

rem ;; Block Execution If Called Directly
if not defined YUI_BUILD_NAME (
    echo.Warning: This file should not be called directly
    pause>nul
    exit
)

rem ;; Set --no-mounge Only If Necessary
if "%YUI_NO_MUNGE%"=="1" (
    if "%YUI_TYPE%"=="js" set YUI_NOMUNGE=--nomunge
    if not "%YUI_TYPE%"=="js" set YUI_NOMUNGE=
)
if not "%YUI_NO_MUNGE%"=="1" set YUI_NOMUNGE=

rem ;; Set A Delimiter Between Files If Type Is js
if "%YUI_TYPE%"=="js" set YUI_DELIM=;

rem ;; Start Script Execution
goto show_summary

:build_minified_version
    rem ;; After The Unique Big File Has Been Created Creates The Single Compressed One
    echo.
    echo   Creating build
    echo.
    java -jar "%YUI_FOLDER%\yuicompressor-%YUI_COMPRESSOR_VERSION%.jar" --charset=UTF-8 --type=%YUI_TYPE% %YUI_NOMUNGE% "%YUI_FOLDER%\full.%YUI_TYPE%" -o "%YUI_FOLDER%\min.%YUI_TYPE%"
    echo  ____________________________________
    echo.
    if "%YUI_DEBUG%"=="1" pause>nul
    goto copy_and_remove

:check_utf8_bom
    rem ;; Checks If There Is The UTF-8 Bom At The Beginning Of The File
    set /p firstLine=<%YUI_FOLDER%\tmp
    if "%firstLine:~0,3%"=="%~1" call:create_utf8bom_free_file
    goto:eof

:copy_and_remove
    rem ;; Merge With An Header The Compressed File. Move Files Into Destination Folder
    echo.
    echo   Copying and removing files
    echo.
    echo./** %YUI_BUILD_NAME% - %DATE% %TIME% */>"%YUI_FOLDER%\%YUI_BUILD_NAME%.min.%YUI_TYPE%"
    TYPE "%YUI_FOLDER%\min.%YUI_TYPE%">>"%YUI_FOLDER%\%YUI_BUILD_NAME%.min.%YUI_TYPE%"
    rem ;; NOTE: If Files Are Not Present This Command May Ask If It Is A File Or A Directory - Please Press F
    rem ;; NOTE: If Files Were Present This Command Forces Overwrites (In Visual Studio Solution Folders As Well)
    xcopy /Y /V /R /Q /Z "%YUI_FOLDER%\%YUI_BUILD_NAME%.min.%YUI_TYPE%" "%YUI_FOLDER_DEST%\%YUI_BUILD_NAME%.min.%YUI_TYPE%"
    xcopy /Y /V /R /Q /Z "%YUI_FOLDER%\full.%YUI_TYPE%" "%YUI_FOLDER_DEST%\%YUI_BUILD_NAME%.debug.%YUI_TYPE%"
    del "%YUI_FOLDER%\min.%YUI_TYPE%"
    del "%YUI_FOLDER%\full.%YUI_TYPE%"
    del "%YUI_FOLDER%\%YUI_BUILD_NAME%.min.%YUI_TYPE%"
    echo  ____________________________________
    echo.
    if "%YUI_DEBUG%"=="1" pause>nul
    goto end_procedure

:create_utf8bom_free_file
    rem ;; Remove UTF-8 BOM From "tmp" File o Avoid Problems During Interpretation
    type %YUI_FOLDER%\tmp>%YUI_FOLDER%\tmp.bom
    for /f "delims=" %%G in (%YUI_FOLDER%\tmp.bom) do (
        if defined i echo.%%G>>%YUI_FOLDER%\tmp
        if not defined i (
            call:remove_utf8_bom "%%G"
            set i=1
        )
    )
    del %YUI_FOLDER%\tmp.bom
    goto:eof

:end_procedure
    rem ;; Hopefully Everything Is OK - It Is Time To Exit
    echo.
    echo   Done
    echo  ____________________________________
    if "%YUI_DEBUG%"=="1" pause>nul
    exit

:remove_utf8_bom
    rem ;; Called From create_utf8bom_free_file Function Create The File Without The BOM In The First line
    set fl=%~1
    echo %fl:~3,-1%%fl:~-1%>"%YUI_FOLDER%\tmp"
    goto:eof

:show_file_list_and_append_content
    rem ;; Performs Checks For Each File In The List
    echo.
    echo   File Analysis
    echo  ------------------------------------
    set /p bom=<%YUI_FOLDER%\bom
    for /f "delims=" %%G in (%YUI_FILE_LIST%) do (
        if defined YUI_FOLDER_SOURCE (
            echo   %%G
            type "%YUI_FOLDER_SOURCE%\%%G">"%YUI_FOLDER%\tmp"
        )
        if not defined YUI_FOLDER_SOURCE (
            echo   %%G [%%~zG]
            type "%%G">"%YUI_FOLDER%\tmp"
        )
        call:check_utf8_bom %bom%
        if "%YUI_DEBUG%"=="1" (
            java -jar "%YUI_FOLDER%\yuicompressor-%YUI_COMPRESSOR_VERSION%.jar" --charset=UTF-8 --type=%YUI_TYPE% %YUI_NOMUNGE% "%YUI_FOLDER%\tmp" -o "%YUI_FOLDER%\tmp.min"
            del "%YUI_FOLDER%\tmp.min"
            if not "%errorlevel%"=="0" (
                echo.Warning: Errors during compression
                pause>nul
                del "%YUI_FOLDER%\tmp"
                exit
            )
        )
        TYPE "%YUI_FOLDER%\tmp">>"%YUI_FOLDER%\full.%YUI_TYPE%"
        del "%YUI_FOLDER%\tmp"
        if defined YUI_DELIM echo.%YUI_DELIM%>>"%YUI_FOLDER%\full.%YUI_TYPE%"
    )
    echo  ____________________________________
    echo.
    if "%YUI_DEBUG%"=="1" pause>nul
    goto build_minified_version

:show_summary
    rem ;; Initial Screen Mit Style License Please Do Not Remove My Credits
    echo  ____________________________________
    echo.
    echo  (C) Andrea Giammarchi @WebReflection
    echo       YUI Batch Build System V 1.0
    echo.
    echo  ------------------------------------
    echo   %YUI_BUILD_NAME%
    echo  ------------------------------------
    echo   Date         %DATE% %TIME%
    echo   Type         %YUI_TYPE%
    echo   Place        %YUI_FOLDER%
    echo   Destination  %YUI_FOLDER_DEST%
    echo   List         %YUI_FILE_LIST%
    if "%YUI_DEBUG%"=="1" (echo   Debug        ON)
    if not "%YUI_DEBUG%"=="1" (echo   Debug        OFF)
    echo  ____________________________________
    echo.
    if "%YUI_DEBUG%"=="1" pause>nul
    goto show_file_list_and_append_content

rem ;; Enjoy Your Compressed File - Thank You YUICompressor

The bom File

Since I am not that skilled with batch scripting as I am with JavaScript, PHP, MySQL, Python, or C#, I decided to avoid problems with charset and encoding creating a file that will be included by yuibompressor for each call, the bom file.

This file simply contains those 3 characters able to create a mess if one of included file has them at the top.

To make everything more simple, I created a zip archive which aims is to bring a workable example in your PC.

All you need to do is to unpack the zip somewhere in your PC, and to double click the vice-versa.bat file insid the projects folder.

The configuration file is a dedicated one for my vice-versa project and since debug variable is set to 1, you have to press a button for each step until the prompt window will not disappear.

A yuibompressor Workable Example

All you need to test this file is the next Zip link. Please do not hesitate to tell me your opinion in my blog.

yuibompressor.zip

About This Project

Well, so far this project is everything I need to make YUI Compressor portable. If I was in Linux I would have use Python rather than a batch script file, but since I consider myself extremely flexible, this was not that big deal and I hope other developers will use this approach.

Best Regards, Andrea Giammarchi