Jak nainstalovat Grunt pod Windows

Pojďme si ukázat nástroj, který za mne dělá špinavou práci. Všechny procesy které děláte stále ručně do kola se většinou dají zautomatizovat. Já je nechávám na Gruntu aby je udělal za mne. Stroj nedělá chyby a je rychlý.

Dnes si ukážeme úvod do Gruntu. S Gruntem spolupracuje další skvělý nástroj – Bower. Ale o tom až někdy příště.

Pro zprovoznění programu Grunt je nutné nainstalovat node.js

Z webu stáhneme instalaci (tlačítko INSTALL) a nainstalujeme. Instalaci stačí odklikat. Po dokončení instalace pro jistotu restartujeme PC.

Přesvědčíme se že máme správně nainstalovaný node.js. Spustíme příkazovou řádku ( Start -> Příslušenství -> Příkazový řádek ). Do příkazové řádky zadáme příkaz node a potvrdíme klávesou ENTER:

node-test-run

Součástí každého projektu by měl být soubor package.json. Vytvoříme ho příkazem:

npm init

package.json obsahuje základní informace o projektu ( autor, verze, verzi Node, závislé balíčky a jejich verze, …) je to něco jako composer.json pro php. Pokud si projekt s tímto souborem stáhnete, jednoduše nainstalujete všechny potřebné balíčky příkazem:

npm install

Instalace Grunt

npm install -g grunt
npm install -g grunt-cli
npm install grunt --save-dev       //musim provest i tento prikaz

Parametr -g říká, že Grunt instalujeme globálně.

Úspěšné nainstalování Gruntu prověříme příkazem:

grunt

node-test-run-grunt

Z hlášky v konzoli je vidět že nemáme soubor Gruntfile.js pojďme si ho vytvořit (ten musíme vytvořit ručně):

module.exports = function(grunt) {
   grunt.initConfig({
      section: {
         foo: [1, 2, 3],
         bar: 'hello world',
         baz: false
      }
   })
   grunt.task.registerMultiTask('section', 'run section.', function() {
      grunt.log.writeln(this.target + ': ' + this.data);
   });
   grunt.task.registerMultiTask('section', 'run section.', function() {
      grunt.log.writeln(this.target + ': ' + this.data);
   });

   grunt.registerTask('only-baz', ['section:baz']);
}

Vytvořili jsme 2 tasky:

  • section – multiTast vykoná všechny tasky v sekci section
    node-test-run-grunt-run
  • only-baz – vykoná pouze 1 task ze sekce section ( section -> baz )
    node-test-run-grunt-run-1task

Neužitečný příklad výstupu, ovšem nutný pro pochopení fungování Gruntu. Příště si ukážeme zajímavější použití v praxi 🙂

Grunt – task pro automatický release nové verze

Dělám na několika doplňcích pro WordPress. Kámen úrazu je verzování. S vydáním nové verze jsem musel přepisovat verzi ve zdrojovém kódu, vytvořit nový tag v Gitu a tuto změnu commitnout a pushnout. Ale protože jsem lajdák vždy jsem na něco zapoměl…

Při vydání nové verze dělám:

  • nastavit novou verzi ve zdrojových souborech ( Version: 0.0.1 => Version: 0.0.2 )
  • coomitnout tuto změnu
  • vytvořit nový tag ( 0.0.2 )
  • pushnout tyto změny

To jsem dělal ručně do doby než jsem poznal Grunt. Nyní mám tento proces automatizovaný a tuto nudnou opičí práci za mne udělá Grunt.

Pojďme si ukázat jak. Předpokládejme nainstalovaný Grunt (o instalaci Gruntu zase někdy jindy).

Vytvoříme soubor package.json:

npm init

Nainstalujeme grunt-version:

npm install grunt-version --save-dev

Vytvoříme soubor Gruntfile.js:

module.exports = function(grunt) {
   grunt.loadNpmTasks('grunt-version');
 
   grunt.initConfig({
      version: {
         php: {
            options: {
               prefix: '\Version:\\s+'
            },
            src: [ 'my-file.php' ]
         }
      }
   });

   // Release task
   grunt.registerTask( 'release', [ 'version' ]); 
};

Příkazem grunt release nastavíme v souboru my-file.php novou verzi uvedenou v package.json:

Version:           0.0.1 se změní na verzi zadanou v souboru package.json

To je solidní základ 🙂 Ale mne to nestačí. Verzi kterou chci vydat musím zapsat do souboru package.json a příliš práce to za mne neudělá…

Dělám různé releasy:

  • patch (1.2.X)
  • minor (1.X.0)
  • major (X.0.0)

Pojďmě si napsat script který bude automaticky zvyšovat verzi v souboru package.json v závislosti na vydávané verzi. Vužijeme modul grunt-update-json

npm install grunt-update-json --save-dev

Použijeme tento kód:

module.exports = function(grunt) {

   grunt.loadNpmTasks('grunt-version');
	
   grunt.initConfig({
      pkg: grunt.file.readJSON( 'package.json' ),
         version: {
            php: {
               options: {
                  prefix: '\Version:\\s+'
               },
                  src: [ 'my-file.php' ]
               }
            }
         });
         // Release task		
         grunt.registerTask('release:patch', 'Release patch version', function( target ) {
            release( "patch" );
         });

         grunt.registerTask('release:minor', 'Release minor version', function( target ) {
            release( "minor" );
         });

         grunt.registerTask('release:major', 'Release major version', function( target ) {
            release( "major" );
         });

         function release( type )
         {
            var version = grunt.config.data.pkg.version;
            var aVersion = version.split(".");
            if( type == "patch" )
            {
               aVersion[ 2 ] = ( 1 * aVersion[ 2 ] ) + 1;
            }
            else if( type == "minor" )
            {
               aVersion[ 2 ] = 0;
               aVersion[ 1 ] = ( 1 * aVersion[ 1 ] ) + 1;
            }
               else if( type == "major" )
            {
               aVersion[ 2 ] = 0;
               aVersion[ 1 ] = 0;
               aVersion[ 0 ] = ( 1 * aVersion[ 0 ] ) + 1;
            }
            var newVersion = aVersion.join(".");
            grunt.log.writeln('Release ' + type + ' version: ' + version + ' => ' + newVersion );

            //save new version to package.json
            grunt.config.data.pkg.version = newVersion;		
            grunt.file.write( './package.json', JSON.stringify( grunt.config.data.pkg, null, '  ') + '\n');
		
            //change version in source code
            grunt.task.run(['version']);
		
            //@TODO commit
            //@TODO create TAG
            //@TODO push
         }
};

To už je lepší. Můžeme použít následující příkaz:

  • grunt release:patch
  • grunt release:minor
  • grunt release:major

K dokonalosti chybí pouze commit, vytvořit tag s novou verzí a push. K tomu využijeme grunt-git

npm install grunt-git --save-dev

Do souboru package.json přidáme následující kód:

gitcommit: {
   version: {
      options: {
         message: 'New version: <%= pkg.version %>'
      },
      files: {
         // Specify the files you want to commit
         src: ['my-file.php', 'package.json']
      }
   }
},
gittag: {
   version: {
      options: {
         tag: '<%= pkg.version %>',
         message: 'Tagging version <%= pkg.version %>'
      }
   }
},
gitpush: {
   version: {},
   tag: {
      options: {
         tags: true
      }
   }
},

Celý kód nakonec vypadá takto:

module.exports = function(grunt) {

   grunt.loadNpmTasks('grunt-version');
   grunt.loadNpmTasks('grunt-git');
	
   grunt.initConfig({
      pkg: grunt.file.readJSON( 'package.json' ),
         version: {
            php: {
               options: {
                  prefix: '\Version:\\s+'
               },
               src: [ 'my-file.php' ]
            }
         },
         gitcommit: {
            version: {
               options: {
                  message: 'New version: <%= pkg.version %>'
               },
               files: {
                  src: ['my-file.php', 'package.json']
               }
            }
         },
         gittag: {
            version: {
               options: {
                  tag: '<%= pkg.version %>',
                  message: 'Tagging version <%= pkg.version %>'
               }
            }
         },
         gitpush: {
            version: {},
            tag: {
               options: {
                  tags: true
               }
            }
         }		
      });

      grunt.registerTask('release:patch', 'Release patch version', function( target ) {
         release( "patch" );
      });

      grunt.registerTask('release:minor', 'Release minor version', function( target ) {
         release( "minor" );
      });

      grunt.registerTask('release:major', 'Release major version', function( target ) {
         release( "major" );
      });

      function release( type )
      {
         var version = grunt.config.data.pkg.version;
         var aVersion = version.split(".");
         if( type == "patch" )
         {
            aVersion[ 2 ] = ( 1 * aVersion[ 2 ] ) + 1;
         }
         else if( type == "minor" )
         {
            aVersion[ 2 ] = 0;
            aVersion[ 1 ] = ( 1 * aVersion[ 1 ] ) + 1;
         }
         else if( type == "major" )
         {
            aVersion[ 2 ] = 0;
            aVersion[ 1 ] = 0;
            aVersion[ 0 ] = ( 1 * aVersion[ 0 ] ) + 1;
         }
         var newVersion = aVersion.join(".");
         grunt.log.writeln('Release ' + type + ' version: ' + version + ' => ' + newVersion );

         //save new version to package.json
         grunt.config.data.pkg.version = newVersion;		
         grunt.file.write( './package.json', JSON.stringify( grunt.config.data.pkg, null, '  ') + '\n');
		
         //change version in source code
         grunt.task.run(['version']);
		
         //git commit
         grunt.task.run(['gitcommit:version']);
         //git create TAG
         grunt.task.run(['gittag:version']);
         //git push
         grunt.task.run(['gitpush']);
      }
};