introduction_grunt



introduction_grunt

0 0


introduction_grunt

Présentation grunt @ChtiJS 31 oct. 2013

On Github 0gust1 / introduction_grunt

Introduction à Grunt

Vu par la lorgnette d'un dev-front / UI designer / intégrateur...

Introduction

Introduction (2)

"Grunt" ?

  • Grogner / grognement (technique vocale du death metal)
  • Soldat de base d'infanterie / "Trouffion"
  • Petit poisson des récifs coralliens.

Un moteur de tâches, un automatiseur

  • Déclaratif
  • Modulaire
  • Extensible
  • Cross-platform (Linux, MacOS, Windows)
  • Organisé par tâche (task) et par cible (target)
  • Peut être comparé (de loin !) à des outils comme Ant ou Maven (Java)

Installation

Installer globalement le wrapper pour la console.

npm install -g grunt-cli

Ensuite tout se passe au niveau de votre projet :

cd <yourProjectDir>

Si votre projet ne contient pas encore de fichier package.json, faites un npm init à la raçine de votre projet.

Installez les plugins grunt dont vous avez besoin :

npm install grunt --save-dev
npm install grunt-contrib-jshint --save-dev

Un moteur de tâches

Et non pas un moteur de tâche.

Un moteur de tâches (1)

Des tâches pour à peu près tout.

  • FTP, SSH, SVN, Git
  • Lancer des commandes shell
  • optimisation d'images, construction de sprites.
  • Lint CSS, JS
  • Minification et concaténation de ressources
  • Lancement de tests
  • Intégration avec Maven, Travis, Jenkins...
  • etc...

    http://gruntjs.com/plugins/

Un moteur de tâches (2)

Ecrire ses propres tâches.

tâches d'alias vers une ou plusieurs tâches.

grunt.registerTask('myTask', 'ma super tâche', ['jshint:prod','tests:prod'])

tâches "custom"

  • tâches aynchrones.
  • tâches à plusieurs targets (multi-tasks)
  • tâches lançant d'autres tâches (avec conditions d'échecs etc...)

Référence :

http://gruntjs.com/creating-tasks

Démo !

Là où la magie opère.

On va ecrire quelque chose

Le GruntFile

Là où tout se passe.

Le GruntFile (1)

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']);

};

Fichiers et "globbing"

Parce qu'on va travailler avec des fichiers et des arborescences. Souvent.

Fichiers et "globbing" (1)

// You can specify single files:
{src: 'foo/this.js', dest: ...}
// Or arrays of files:
{src: ['foo/this.js', 'foo/that.js', 'foo/the-other.js'], dest: ...}
// Or you can generalize with a glob pattern:
{src: 'foo/th*.js', dest: ...}

// This single node-glob pattern:
{src: 'foo/{a,b}*.js', dest: ...}
// Could also be written like this:
{src: ['foo/a*.js', 'foo/b*.js'], dest: ...}

// All .js files, in foo/, in alpha order:
{src: ['foo/*.js'], dest: ...}
// Here, bar.js is first, followed by the remaining files, in alpha order:
{src: ['foo/bar.js', 'foo/*.js'], dest: ...}

// All files except for bar.js, in alpha order:
{src: ['foo/*.js', '!foo/bar.js'], dest: ...}
// All files in alpha order, but with bar.js at the end.
{src: ['foo/*.js', '!foo/bar.js', 'foo/bar.js'], dest: ...}

// Templates may be used in filepaths or glob patterns:
{src: ['src/<%= basename %>.js'], dest: 'build/<%= basename %>.min.js'}
// But they may also reference file lists defined elsewhere in the config:
{src: ['foo/*.js', '<%= jshint.all.src %>'], dest: ...}

Fichiers et "globbing" - Dynamique

Quand on doit travailler avec un ensemble conséquent de fichiers.

Quand on veut pouvoir conserver la hierarchie de système de fichiers (lors d'une copie par ex.)

files: [{
    expand: true, // Enable dynamic expansion
    cwd: 'img/src', // Src matches are relative to this path
    src: ['**/*.{png,jpg,gif}'], // Actual patterns to match
    dest: 'img/' // Destination path prefix
    // ext :''
}]

Trucs pénibles & astuces

Parce que tout n'est pas rose chez les cochons sauvages

Le debug

grunt.log.writeln()

Pas évident pour les plugins. Plus simple pour les custom tasks.

grunt --debug --stack --verbose "yourtask"

Assez limité, mais ça peut aider.

node-inspector

node --debug-brk $(which grunt) votre_tache_grunt

ou sinon :

npm install grunt-node-inspector --save-dev

https://npmjs.org/package/grunt-node-inspector

npm install grunt-debug

https://github.com/burnnat/grunt-debug

Gestion de la configuration

Pour dégraisser le GruntFile

Gestion de la configuration (1)

Principe :

├── Gruntfile.js
├── grunt-tasks
│   ├── options
│   │   ├── imagemin.js
│   │   ├── notify.js
│   │   └── watch.js
│   ├── set_config.js
│   └── set_global.js

Gruntfile :

module.exports = function(grunt) {

  require('load-grunt-config')(grunt, {
        configPath: 'grunt-tasks/options'
    });

  grunt.loadTasks('grunt-tasks');
  grunt.registerTask('default', ['watch']);
};

Gestion de la configuration (2)

Comment ?

npm install load-grunt-config --save-dev

npm install load-grunt-tasks --save-dev

Utilisation du templating

Les templates sont évaluées à l'execution.

Les templates sont évaluées récursivement (un template peut en utiliser d'autres).

Accès à l'ensemble de l'objet de config ainsi qu'aux fonctions de l'objet grunt (cf API).

(Thomas Parisot) "Dynamic Grunt targets using templates" https://oncletom.io/2013/dynamic-grunt-targets-using-templates/

http://gruntjs.com/configuring-tasks

http://gruntjs.com/api/grunt

Références

Plugins Grunt : http://gruntjs.com/plugins

Documentation Grunt : http://gruntjs.com/getting-started

API Grunt : http://gruntjs.com/api

Articles divers :

(Thomas Parisot) "Dynamic Grunt targets using templates" https://oncletom.io/2013/dynamic-grunt-targets-using-templates/