Billy G Billy G - 5 months ago 11
Javascript Question

Complette workflow for minifying and concatenating (angular) web apps with gulp

It feels like 99% of all tutorials about using gulp.js and the right workflow showing only the part where the js / css files are (for example) minified and concatenated.

But what I haven't found is what to do next to get the right

index.html
file with the new processed files correctly referenced inside without the need of manual editing the file.

Example
index.html
:

<head>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/app.css">
</head>
<body>
[...]
<script src="javascript/angular.min.js"></script>
<script src="javascript/angular-animate.min.js"></script>
<script src="javascript/ui-bootstrap-tpls-0.11.0.min.js"></script>
<script src="javascript/app/app.js"></script>
<script src="javascript/app/controllers/controller.js"></script>
<script src="javascript/app/services/factory.js"></script>
</body>


And the result should be something like this:

<head>
<link rel="stylesheet" href="css/combined.css">
</head>
<body>
[...]
<script src="javascript/combined.js"></script>
</body>


where inside the
combined.*
files are all css/js files concatenated but only these minified with gulp, that do not end with
*.min.js
or
*.min.css
.

Gulp-usemin and gulp-useref are not suitable for, because they concatenate all files inside a build block and after that can you minify the (combined) result (what would minify already minified files again - I do not want that).

How can this missing last step look like to make the workflow complete?

Answer

As it seams not to be any satisfying answer / solution to my question as stated above, I ended up using another approach that works as expected good on production side and have benefits during development.

I am using always the unminified versions of the vendor libs (as AngularJS, jQuery etc.) and the HTML looks then like this (with special comments for useref):

<head>
  <!-- build:css css/styles.css -->
  <link rel="stylesheet" href="css/bootstrap.css">
  <link rel="stylesheet" href="css/app.css">
  <!-- endbuild -->
</head>
<body>
  [...]
  <!-- build:js js/scripts.js -->
  <script src="javascript/angular.js"></script>
  <script src="javascript/angular-animate.js"></script>
  <script src="javascript/ui-bootstrap-tpls-0.11.0.js"></script>
  <script src="javascript/app/app.js"></script>
  <script src="javascript/app/controllers/controller.js"></script>
  <script src="javascript/app/services/factory.js"></script>
  <!-- endbuild -->
</body>

The gulpfile.js:

var gulp = require('gulp'),
    useref = require('gulp-useref'),
    gulpif = require('gulp-if'),
    uglify = require('gulp-uglify'),
    cleanCSS = require('gulp-clean-css'),
    rev = require('gulp-rev'),
    revReplace = require('gulp-rev-replace');

gulp.task('default', ['combineminify']);

gulp.task('combineminify', function () {
    return gulp.src('index.html')
        .pipe(useref())
        .pipe(gulpif('*.js', uglify({
            preserveComments: 'license'
        })))
        .pipe(gulpif('*.css', cleanCSS({
            keepSpecialComments: '*'
        })))
        .pipe(gulpif('*.js', rev()))
        .pipe(gulpif('*.css', rev()))
        .pipe(revReplace())        
        .pipe(gulp.dest('/path/to/destination/folder/'));
});

This gulp script creates then a new index.html file in the destination folder:

<head>
  <link rel="stylesheet" href="css/styles-1627b7eb0c.css">
</head>
<body>
  [...]
  <script src="js/scripts-595ed88b32.js"></script>
</body>

And the expected two uglified and minified *.css and *.js files (with random string attached to the filename to avoid caching issues in some browsers) are created in the folders ./css and ./js.