multiple script tags and concatenation + minification + preprocessing

I have a html file with multiple script tags(close to 20). I've decided to concatenate all the JS files into one and then minify the concatenated file. I am using ant tasks to concatenate and will do so for minification as well. I am aware that I need to provide the option of a non-concatenated/non-minified version for the purposes of debugging(aka in the dev env).

I was wondering how to achieve this. For ex: the file main.html has 20 script tags, one way I figured to do it was use a HTML preprocessor and conditionally include script tags:

#ifdef perf
    <script src="main.min.js"></script> 
#else 
    <script src="ctrl.js"></script>
    <script src="services.js"></script>
    <script src="directives.js"></script>
    <script src="model.js"></script>
    .
    .
    .P.S
    <script src="file_no_20.js"></script>
#endif

main.min.js is the concatenated and minified file during the build process using ant.

Is there a better way of doing this? What are the downsides of this approach?

Thanks, Chris. P.S: Thinking of using the http://fmpp.sourceforge.net/ for html preprocessing, any other suggestions are appreciated.

Chrome supports an awesome feature called "source mapping" that is perfect for this. I'd suggest you read the guide here for more info:

http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/

There are some caveats if you're using AngularJS in regards to minification. From the docs:

Since angular infers the controller's dependencies from the names of arguments to the controller's constructor function, if you were to minify the JavaScript code for PhoneListCtrl controller, all of its function arguments would be minified as well, and the dependency injector would not being able to identify services correctly.

To overcome issues caused by minification, just assign an array with service identifier strings into the $inject property of the controller function, just like the last line in the snippet (commented out) suggests:

PhoneListCtrl.$inject = ['$scope', '$http'];

There is also one more way to specify this dependency list and avoid minification issues — using the bracket notation which wraps the function to be injected into an array of strings (representing the dependency names) followed by the function to be injected:

var PhoneListCtrl = ['$scope', '$http', function($scope, $http) { /* constructor body */ }];

Both of these methods work with any function that can be injected by Angular, so it's up to your project's style guide to decide which one you use.

http://docs.angularjs.org/tutorial/step_05

I suggest using tag libraries, something like http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPTags4.html#67771 to acheieve this. Include your script's like:

<script:include src="myscript1.js" />
<script:include src="myscript2.js" />
<script:include src="myscript3.js" />
..

And the use a page parameter for your system to decide if the scripts has to be concatenated and minified. Something like below:

www.yourapp.com/app?debugMode=true

By default the scripts are concatinated and minified. If you are a developer working on the project just add a page parameter like debugMode=true. When debugMode is true, just render the scripts as it is.

There are many services out there in the market like http://developer.yahoo.com/yui/compressor/ that can be integrated with your project to do this job for you.

Do not compress the scripts everytime you load the page. Do it the first time and cache it so that you dont have to do it everytime. At any point of time to rebuild the latest script file, just add another parameter like ?rebuild=true so that all the latest files and minfied and cached. You could do the same with CSS too.