Lucian Maran

home

Gulp pentru dev environment. Partea I - Build

01 Jun 2015

De ceva vreme, cel putin pentru proiectele Node.js/Angular, mi-am propus sa evit clasicul VisualStudio. Am incercat pe rand cu Sublime, Brackets si, in final, am ramas la VisualStudio Code. Procesul de build sunt nevoit acum sa-l implementez de la zero, iar pentru asta am ales sa ma folosesc de Gulp. Cand spun build pe dev. environment ma gandesc la 2 componente:

Cele 2 componente le-am evidentiat in imaginea de mai jos:

Am sa sar peste explicatiile de tipul "de ce Gulp si nu Grunt", cum se instaleaza si cum se configureaza Grunt, sau care sunt pachetele folosite in gulpfile.js si cum se initializeaza acestea.

In caz ca doresti sa sari pesti explicatii, poti accesa direct codul sursa.

Initializarea task-urilor

Task-ul pentru build (apelabil cu gulp dev):

gulp.task('dev', function(cb) {
    runSequence(
        'clean-css',
        'less',
        'build-dev-html',
        'jshint',
    cb);
});

iar task-ul pentru build + watch (apelabil cu gulp dev:watch):

gulp.task('dev:watch', function(cb) {
    runSequence(
        'dev',
        ['livereload', 'watch'],
    cb);
});

In ambele cazuri am folosit runSequence pentru a stabili care task-uri se executa in paralel (ex: livereload si watch) si care in serie (restul).

Al 2-lea task l-am declarat ca fiind implicit (apelabil cu gulp):

gulp.task('default',['dev:watch']);

Implementarea task-urilor

clean-css

Vreau sa ma asigur ca nu au ramas, din greseala, fisiere .css care sa nu aibe un corespondent `.less'.

gulp.task('clean-css', function (cb) {
    return del(['./client/app/**/*.css'], cb);
});

less

Compileaza fisierele .less in .css. Fisierele (css) rezultate se genereaza in acelasi director ca si fisierele (less) sursa.

gulp.task('less', function() {
    return gulp.src('./client/app/**/*.less')
        .pipe(less())
        .pipe(gulp.dest('./client/app'));
});

build-html

Initial fisierul index.html nu contine referinte catre fisierele js sau css ci doar niste placeholder-e care indica locatia in care aceste referinte urmeaza a fi injectate:

<!doctype html>
<html ng-app=app>
<head>
    <base href="/" />   
    <!-- cdn -->
    <link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />

    <!-- inject-vendor:css -->
    <!-- endinject -->

    <!-- inject:css -->
    <!-- endinject -->
</head>
<body>     
    <h2>Gulp Demo</h2>
    <div ng-class="demoClass" ng-controller="demoController"></div>
    <!-- cdn -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>

    <!-- inject-vendor:js -->
    <!-- endinject -->

    <!-- inject:js -->
    <!-- endinject -->
</body>
</html>

Task-ul care populeaza aceste tag-uri este:

gulp.task('build-dev-html', function(){  
    return gulp.src('./client/index.html')
        .pipe(inject(gulp.src('./client/app/**/*.css', {read:false}), {relative: true})) // css app files  
        .pipe(inject(gulp.src('./client/app/**/*.js', {read: false}), {relative: true})) // js app files  
        .pipe(inject(gulp.src(bowerFiles(), {read: false}), {name:'inject-vendor', relative: true})) // bower js and css files  
        .pipe(gulp.dest('./client/'));
});

Unde:

La sfarsitul acestei operatii, fisierul index.html va arata asa:

<!doctype html>
<html ng-app=app>
<head>
    <base href="/" />   
    <!-- cdn -->
    <link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />

    <!-- inject-vendor:css -->
    <link rel="stylesheet" href="bower_components/normalize.css/normalize.css">
    <!-- endinject -->

    <!-- inject:css -->
    <link rel="stylesheet" href="app/app.css">
    <link rel="stylesheet" href="app/components/component1/test.css">
    <!-- endinject -->
</head>
<body>    
    <h2>Node Demo22345</h2>
    <div ng-class="demoClass" ng-controller="demoController"></div>

    <!-- cdn -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>

    <!-- inject-vendor:js -->
    <script src="bower_components/lodash/lodash.js"></script>
    <!-- endinject -->

    <!-- inject:js -->
    <script src="app/app.js"></script>
    <script src="app/controllers/demoController.js"></script>
    <script src="app/controllers/test.js"></script>
    <script src="app/directives/demoDirective.js"></script>
    <script src="app/services/demoService.js"></script>
    <!-- endinject -->
</body>
</html>

jshint

gulp.task('jshint', function() { 
    return gulp.src('./client/app/**/*.js')
        .pipe(jshint())
        .pipe(jshint.reporter(stylish))      
        .pipe(jshint.reporter('fail'))  
        .on('error', function(error){
            gutil.log(gutil.colors.red('JSHINT failed!'));
            this.emit('end');
        })
        .pipe(notify({
            onLast: true,
            message: function(){
                gutil.log(gutil.colors.green('JSHINT passed!'));
            }
        }));
});

Cum functioneaza jshint? Daca, spre exemplu, introduc in cod doua greseli:

atunci aceste erori le pot depista in procesul de build - faza de analiza a codului:

Intr-un articol viitor am sa prezint cum mi-am configurat un watcher in Gulp astfel incat, de fiecare data cand editez, sterg sau adaug un fisier, procesul de build sa se reia automat.

comments powered by Disqus