Last active
April 19, 2017 11:26
-
-
Save evaisse/2c9feac19496928ad1fd62459cff8122 to your computer and use it in GitHub Desktop.
An Angular-seed tailored gulpfile, with ng-annotate, template pre-compile, html/css/js min, sourcemaps for css & js, revision & cache busting.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @author Emmanuel VAÏSSE <evaisse@gmail.com> | |
* @see https://gist.github.com/evaisse/2c9feac19496928ad1fd62459cff8122 | |
* | |
* An Angular-seed (https://github.com/angular/angular-seed) tailored gulpfile, provide : | |
* | |
* - ng-annotate, prevengt loosing angular injection $annotation syntax against minification | |
* - angular template pre-compile | |
* - html/css/js minification | |
* - sourcemaps for css & js | |
* - css autoprefixer | |
* - assets url revision hash & cache busting | |
* | |
* Todos: | |
* - assets optim (images, svg, ...) | |
* | |
* How to Use: | |
* | |
* 1 — Install NPM required gulp build dependencies | |
* | |
* npm install --save-dev gulp gulp-htmlmin gulp-useref gulp-rename \ | |
* gulp-cache-bust gulp-ng-annotate gulp-uglify gulp-cssnano \ | |
* lazypipe gulp-sourcemaps gulp-if gulp-autoprefixer \ | |
* gulp-angular-templatecache del gulp-rev gulp-rev-replace \ | |
* gulp-filter gulp-concat gulp-insert | |
* | |
* 2 — Prepare your index{-async}.html file | |
* | |
* In your HTML entry point you should wrap js & css files into "useref" comments to specificy | |
* merge groups | |
* | |
* <!-- build:css css/combined.css --> | |
* <link rel="stylesheet" href="bower_components/html5-boilerplate/dist/css/normalize.css"> | |
* <link rel="stylesheet" href="bower_components/html5-boilerplate/dist/css/main.css"> | |
* <link rel="stylesheet" href="app.css"> | |
* <!-- endbuild --> | |
* | |
* <!-- build:js js/head.js --> | |
* <script src="bower_components/html5-boilerplate/dist/js/vendor/modernizr-2.8.3.min.js"></script> | |
* <!-- endbuild --> | |
* | |
* 3 — Build | |
* | |
* run `gulp`, that's all. | |
* Build output will remains in ./dist | |
* | |
*/ | |
var gulp = require('gulp'); | |
var htmlmin = require('gulp-htmlmin'); | |
var useref = require('gulp-useref'); | |
var gulpRename = require('gulp-rename'); | |
var cacheBuster = require('gulp-cache-bust'); | |
var ngAnnotate = require('gulp-ng-annotate'); | |
var uglify = require('gulp-uglify'); | |
var cssnano = require('gulp-cssnano'); | |
var lazypipe = require('lazypipe'); | |
var sourcemaps = require('gulp-sourcemaps'); | |
var gulpif = require('gulp-if'); | |
var autoprefixer = require('gulp-autoprefixer'); | |
var templateCache = require('gulp-angular-templatecache'); | |
var del = require('del'); | |
var rev = require('gulp-rev'); | |
var revReplace = require('gulp-rev-replace'); | |
var filter = require('gulp-filter'); | |
var concat = require('gulp-concat'); | |
var insert = require('gulp-insert'); | |
var fs = require('fs'); | |
// compressTasks is a sub process used by useRef (below) that | |
// compresses (takes out white space etc) the javascript and | |
// css files | |
var compressTasks = lazypipe() | |
.pipe(sourcemaps.init, { loadMaps: true }) | |
.pipe(function() { | |
return gulpif('*.js', ngAnnotate()); | |
}) | |
.pipe(function() { | |
return gulpif('*.js', uglify()); | |
}) | |
.pipe(function() { | |
return gulpif('*.css', autoprefixer()); | |
}) | |
.pipe(function() { | |
return gulpif('*.css', cssnano({ | |
zindex: false | |
})); | |
}); | |
/** | |
* Helper func to fetch main module name regarding first app.js file | |
* then regarding the ng-app attributes | |
* @return {String} main module name | |
*/ | |
var guessMainModuleName = function () { | |
var res, | |
htmlContent, | |
appContent; | |
appContent = fs.readFileSync('./app/app.js', { encoding: 'utf-8' }); | |
res = appContent.match(/angular\.module\(["']([a-z0-9\-_]+)['"]/i); | |
if (res) { | |
return res[1]; | |
} | |
htmlContent = fs.readFileSync( | |
fs.exists('./app/index-async.html') ? './app/index-async.html' : './app/index.html', | |
{ encoding: 'utf-8' } | |
); | |
res = htmlContent.match(/ng-app=\"([a-z0-9\-_]+)\"/i); | |
if (res) { | |
return res[1]; | |
} | |
return "myApp"; | |
}; | |
// remove old dist dir | |
gulp.task('cleanup-dist', [], function() { | |
return del([ | |
'dist', | |
// we don't want to clean this file though so we negate the pattern | |
'!dist/mobile/deploy.json' | |
]); | |
}); | |
// copy all assets in dist | |
gulp.task('cleanup', ['cleanup-dist'], function() { | |
return gulp.src('./app/**/*.*').pipe(gulp.dest('dist')); | |
}); | |
/** | |
* Create $templateCache from the html templates | |
* @return {Stream} | |
*/ | |
gulp.task('templateCache', ['cleanup'], function() { | |
return gulp | |
.src('app/**/templates/*.html') | |
.pipe(htmlmin({ collapseWhitespace: true, removeComments: true })) | |
.pipe(templateCache({ | |
module: guessMainModuleName(), | |
standalone: false | |
})) | |
.pipe(gulp.dest('app/cache')); | |
}); | |
gulp.task("useref", ['templateCache'], function() { | |
var jsFilter = filter("**/*.js", { restore: true }); | |
var cssFilter = filter("**/*.css", { restore: true }); | |
var angularTemplateFilter = filter('app/**/templates/*.html', { restore: true }); | |
var indexHtmlFilter = filter(['**/*', '!**/index.html'], { restore: true }); | |
function relativeIfMap(filename) { | |
if (filename.indexOf('.map') > -1) { | |
// console.log(filename); | |
return filename.replace('js/', '').replace('css/', ''); | |
} | |
return filename; | |
} | |
return gulp.src("app/index.html") | |
.pipe(sourcemaps.init()) | |
.pipe(useref({ | |
collapseWhitespace: true, | |
removeComments: true | |
}, | |
lazypipe().pipe(compressTasks) | |
)) | |
.pipe(gulpif('app/index.html', htmlmin())) | |
.pipe(sourcemaps.write('.')) | |
.pipe(indexHtmlFilter) | |
.pipe(rev()) // Rename the concatenated files (but not index.html) | |
.pipe(indexHtmlFilter.restore) | |
.pipe(revReplace({ | |
modifyUnreved: relativeIfMap, | |
modifyReved: relativeIfMap | |
})) // Substitute in new filenames | |
.pipe(gulp.dest('dist')); | |
}); | |
gulp.task("default", ['useref'], function () { | |
return gulp | |
.src('./dist/index.html') | |
.pipe(htmlmin({ collapseWhitespace: true, removeComments: true })) | |
.pipe(gulp.dest('dist')); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment