Madrid JS

Octubre2014

Build

 

About

Drupal e integración continua

 

Desarrollo de juegos en html5

 

Señor agente,eso es tabaco de liar

QUÉ ES?

Un proceso

Automatizado

Que genera un entregable

necesario para la integración continua

y facilita la entrada de nuevos miembros al equipo

PREPARE

COMPILE

UNIT TEST

PACKAGE

INTEGRATION TEST

VERIFY

npm install 

bower install

sass less coffee

karma mocha qunit jasmine

zip nar min

pioneer selenium phantomJS

jslint jshint coverage

TOOLS

 

Task oriented

 

Product oriented

Ant

Grunt 

Gulp*

      MsBuild ..

Maven

Make

Rake*

Reinventar la rueda?

After a lot of experimentation and failed attempts, I learned that writing and maintaining a suite of “javascript build process” tasks in a gigantic, monolithic Makefile / Jakefile / Cakefile / Rakefile / ?akefile that was shared across all my projects was overwhelming, especially considering how many projects I have. That approach just wasn’t going to scale to meet my needs.

In the end, I realized that a task-based build tool with built-in, commonly used tasks was the approach that would work best for me. Unfortunately, I couldn’t find a build tool that worked the way that I wanted. So I built one.

2012- Why grunt ? 

http://benalman.com/news/2012/08/why-grunt/

Los gruñidos de mi build

uN POCO DE HISTORIA... *

RECIENTE

WTF

 

CUál?

El que más te guste

hasta make

Coz it haz all the bitches

SETUP

PLUGIN

 

GENERALIDADES

Registrar una tarea

 

grunt.registerTask('build', [
    'miTarea',
    'miOtraTarea'
  ]);

Instalar un plugin

 

npm install --save grunt-contrib-uglify

Cargar un plugin

 

grunt.loadNpmTasks('grunt-contrib-uglify');

Cargarlos todos

 

 

require('load-grunt-tasks')(grunt);

Configurar una tarea

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      build: {
        src: 'src/<%= pkg.name %>.js',
        dest: 'build/<%= pkg.name %>.min.js'
      }
    }
  });

  // Load the plugin that provides the "uglify" task.
  grunt.loadNpmTasks('grunt-contrib-uglify');

  // Default task(s).
  grunt.registerTask('default', ['uglify']);

};

Invocar una tarea

grunt serve:dist

FLOW

PREPARE

npm instal
bower install

//npm install -g grunt-cli
//npm install -g bower 
language: node_js
node_js:
  - "0.10"
before_install: 
  - npm install -g grunt-cli
  - npm install -g bower
install: 
  - npm install
  - bower install

COMPILE

compass: {
      options: {
        sassDir: '<%= yeoman.app %>/styles',
        cssDir: '.tmp/styles',
        generatedImagesDir: '.tmp/images/generated',
        imagesDir: '<%= yeoman.app %>/images',
        javascriptsDir: '<%= yeoman.app %>/scripts',
        fontsDir: '<%= yeoman.app %>/styles/fonts',
        importPath: './bower_components',
        httpImagesPath: '/images',
        httpGeneratedImagesPath: '/images/generated',
        httpFontsPath: '/styles/fonts',
        relativeAssets: false,
        assetCacheBuster: false,
        raw: 'Sass::Script::Number.precision = 10\n'
      },
      dist: {
        options: {
          generatedImagesDir: '<%= yeoman.dist %>/images/generated'
        }
      },
      server: {
        options: {
          debugInfo: true
        }
      }
    }
sass: {
        options: {
            sourceMap: true
        },
        dist: {
            files: {
                'main.css': 'main.scss'
            }
        }
    }
autoprefixer: {
  options: {
    browsers: ['last 1 version']
  },
  dist: {
    files: [{
      expand: true,
      cwd: '.tmp/styles/',
      src: '{,*/}*.css',
      dest: '.tmp/styles/'
    }]
  }
},

UNIT TEST

karma: {
  unit: {
    configFile: 'test/karma.conf.js',
    singleRun: true
  }
}
mocha: {
  test: {
    src: ['tests/**/*.html'],
  },
},
mochaTest: {
  test: {
    options: {
      reporter: 'spec',
      captureFile: 'results.txt', // Optional
      quiet: false // Optional
    },
    src: ['test/**/*.js']
  }
}

PACKAGE

HTML minification

CSS minification / concatenation

 

Uglify/Concat

 

Update references 

 

Revision

 

<!-- build:css style.css -->
<link rel="stylesheet" href="css/clear.css"/>
<link rel="stylesheet" href="css/main.css"/>
<!-- endbuild -->

<!-- build:js js/lib.js -->
<script src="../lib/angular-min.js"></script>
<script src="../lib/angular-animate-min.js"></script>
<!-- endbuild -->

<!-- build:js1 js/app.js -->
<script src="js/app.js"></script>
<script src="js/controllers/thing-controller.js"></script>
<script src="js/models/thing-model.js"></script>
<script src="js/views/thing-view.js"></script>
<!-- endbuild -->

<!-- build:remove -->
<script src="js/localhostDependencies.js"></script>
<!-- endbuild -->
useminPrepare: {
    html: ['app/html/**.html'],
    options: {
        dest: '<%= appRoutes.dist %>'
    }
},
usemin: {
    html: ['dist/app/**/**.html'],
    css: ['<%= appRoutes.dist %>/style/{,*/}*.css'],
    options: {
       dirs: ['<%= appRoutes.dist %>'],
       assetsDirs: ['<%= appRoutes.dist %>']
    }
}
var usemin = require('gulp-usemin');
var uglify = require('gulp-uglify');
var minifyHtml = require('gulp-minify-html');
var minifyCss = require('gulp-minify-css');
var rev = require('gulp-rev');

gulp.task('usemin', function() {
  gulp.src('./*.html')
    .pipe(usemin({
      css: [minifyCss(), 'concat'],
      html: [minifyHtml({empty: true})],
      js: [uglify(), rev()]
    }))
    .pipe(gulp.dest('build/'));
});

IMAGES

imagemin: {
  dist: {
    files: [{
      expand: true,
      cwd: '<%= yeoman.app %>/images',
      src: '{,*/}*.{png,jpg,jpeg,gif}',
      dest: '<%= yeoman.dist %>/images'
    }]
  }
},

O probar grunt-webp

https://developers.google.com/speed/webp/

INTEGRATION TEST

karma: {
   e2e: {
    configFile: 'karma-e2e.conf.js',
    singleRun: true
  }
},
'use strict';

describe('E2E: Testing Routes:', function () {

    beforeEach(function() {
        browser().navigateTo('/');
    });

    it('test', function() {
        browser().navigateTo('#/');
        expect(browser().location().path()).toBe("/list_persons");
    });
})

VERIFY

jshint: {
  options: {
    jshintrc: '.jshintrc',
    reporter: require('jshint-stylish')
  },
  all: {
    src: [
      'Gruntfile.js',
      '<%= yeoman.app %>/scripts/{,*/}*.js'
    ]
  },
  test: {
    options: {
      jshintrc: 'test/.jshintrc'
    },
    src: ['test/spec/{,*/}*.js']
  }
},

BUILD

grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

DEmo

 

 

Evolve Your Deployment System Incrementally

Somos capaces de desplegar AUTOMÁTICAMENTE?

Touch

touch gulpfile.js 
touch Gruntfile.js
touch Makefile
npm install grunt --save
npm install gulp --save 
npm install -g grunt-cli
npm install -g gulp

Karma

npm install grunt-karma --save-dev
npm install gulp-karma --save-dev
/* ... */
karma: {
    unit: {
        configFile: 'karma.conf.js',
        singleRun: true,
        reporters: ['mocha'],
        browsers: ['PhantomJS']
    }
 }
/* ... */
grunt.registerTask('test', ['karma']);
gulp.task('test', function (done) {
  karma.start({
    configFile: __dirname + '/karma.conf.js',
    singleRun: true
  }, done);
});
npm install karma --save-dev
KARMA = ./node_modules/karma/bin/karma
test:	karma build

Additional karma config

npm install karma-jasmine //Jasmine Tests
npm install karma-phantomjs-launcher //Launcher
npm install karma-mocha-reporter //Reporters
npm install karma-sinon //Sinon. Yeah

karma.conf.js

 

module.exports = function(config) {
  config.set({
    basePath: './',
    frameworks: ['jasmine', 'sinon'],
    
    // list of files / patterns to load in the browser
    files: [
      'bower_components/jquery/dist/jquery.js',
      'bower_components/underscore/underscore.js',
      'bower_components/backbone/backbone.js',
      'app/**/**.js',
      'test/**/*.js'
    ],

    // list of files to exclude
    exclude: [],

    singleRun: true,
    reporters: ['mocha'],
    browsers: ['PhantomJS']

  });
};

Karma test output

gulp test
grunt test
make test

Creando Un plugin

 

Grunt

npm install -g grunt-init
git clone git://github.com/gruntjs/grunt-init-gruntplugin.git ~/.grunt-init/gruntplugin
grunt-init gruntplugin
//http://gruntjs.com/creating-plugins
npm install -g generator-gruntplugin
yo gruntplugin
//https://github.com/yeoman/generator-gruntplugin

Yeoman generator

 

Gulp

 npm install -g generator-gulp-plugin
yo gulp-plugin

https://github.com/gulpjs/gulp/blob/master/docs/writing-a-plugin/README.md

 

https://github.com/sindresorhus/gulp-react/blob/master/index.js

Lecturas adecuadas

 

  • http://yeoman.io/blog/performance-optimization.html
  • https://github.com/tooling/book-of-modern-frontend-tooling
  • https://github.com/substack/stream-handbook

Referencias

 

  • Brunch http://brunch.io/
  • Gulp http://gulpjs.com/
  • Grunt http://gruntjs.com/
  • Bower http://bower.io/
  • Yeoman http://yeoman.io/
  • Lineman http://linemanjs.com/
  • Grunt usemin https://github.com/yeoman/grunt-usemin
  • Karma http://karma-runner.github.io/
  • NAR https://github.com/h2non/nar
  • VINYL FS https://github.com/wearefractal/vinyl-fs
  • MAKE "the ultimate front end build tool" https://algorithms.rdio.com/post/make/

Los gruñidos de mi build

By rafinskipg

Los gruñidos de mi build

  • 1,561