Ako integrovať Visual Studio 2013 s Grunt-om - časť 2

DOWNLOAD

Grunt build task

V predošlej časti sme si pripravili Visual Studio 2013 MVC projekt, do ktorého teraz pridáme MSBuild target-y pre integráciu Grunt task runner-a.

Aby sme mohli volať Grunt potrebujeme mať nainštalovaný Node.js a npm package manager, ktorý je súčasťou inštalácie Node.js. Pri inštalácii treba vybrať možnosť npm package manager a Add to PATH. Možnosť Add to PATH nám umožní volať node.js z príkazového riadku bez zadávania absolútnej cesty.

Inštalácia Node.js
Inštalácia Node.js

Môžeme sa pustiť do prípravy target-ov. Prvý target CheckNpmVersionTarget, ktorý sa bude volať pri builde aplikácie, bude kontrolovať dostupnosť npm package manager-a. Na to môžeme využiť volanie npm -version, ktoré v prípade, ak je npm nainštalovaný, vráti číslo verzie. V opačnom prípade volanie skončí s chybou (ExitCode bude rôzny od nuly). Tu využívame tiež predpoklad, že npm máme nainštalovaný ak máme nainštalovaný aj Node.js.

Pri niektorých cli volaniach môže byť konzolový výstup príliš dlhý. V takomto prípade, ak ho nechceme zobraziť priamo v Output okne, môžeme ho presmerovať do dočasného súboru a tento následne vymazať. Názov tohto dočasného súboru zadefinujeme v súbore GruntMvc.targets pomocou PropertyGroup nasledovne:

<PropertyGroup>
    
<ConsoleOutputFile>ConsoleOutputFile.txt</ConsoleOutputFile>
</PropertyGroup>
PropertyGroup "ConsoleOutputFile"

Aj v našom prvom targete CheckNpmVersionTarget použijeme presmerovanie do tohto dočasného súboru. V prípade, že na počítači je npm nainštalovaný, do tohto súboru sa nám zapíše číslo verzie, ktoré následne prečítame a zapíšeme do output okna. Ak npm na počítači nainštalovaný nie je, do dočasného súboru sa zapíše error hláška, ktorú v tomto prípade budeme ignorovať a na základe hodnoty ExitCode zobrazíme vlastnú chybovú hlášku o nedostupnosti npm.

<Target Name="CheckNpmVersionTarget">
  
<Exec Command="call npm -version > $(ConsoleOutputFile)"
      ContinueOnError
="true" WorkingDirectory="$(ProjectDir)" >
    
<Output TaskParameter="ExitCode" PropertyName="ErrorCode"/>
  </
Exec>
  
<ReadLinesFromFile File="$(ConsoleOutputFile)">
    
<Output TaskParameter="Lines" ItemName="NpmVersion" />
  </
ReadLinesFromFile>
  
<Delete Files="$(ConsoleOutputFile)"/>
  <
Error Text="Npm is not installed." Condition="'$(ErrorCode)' != '0'" />
  <
Message Importance="high"
         Text
="You are running npm v@(NpmVersion->'%(Identity)', '%0a%0d')."/>
</
Target>
CheckNpmVersionTarget

Upravíme aj PropertyGroup BuildDependsOn:

<PropertyGroup>
    
<BuildDependsOn>
        CheckNpmVersionTarget;
        $(BuildDependsOn);
    
</BuildDependsOn>
</PropertyGroup>
PropertyGroup "BuildDependsOn"

Keď dáme teraz Rebuild projektu a máme nainštalovaný npm celý build by mal prebehnúť, v opačnom prípade sa build zastaví na chybe "Npm is not installed".

Balíčky, ktoré má npm inštalovať sú zapísané v súbore package.json. V tejto chvíli takýto súbor v projekte ešte nemáme. Logickým krokom je teda ho do projektu pridať. Aby sme ale ošetrili aj prípad, že tento súbor v projekte chýba (mohli sme ho napr. nechtiac vymazať), pridáme si target CheckPackageJsonFileExistenceTarget, ktorý zastaví build ak tento súbor nebol nájdený a zobrazí príslušnú chybovú hlášku. Nemusím už ani pripomínať, že je potrebné doplniť volanie tohto target-u do PropertyGroup BuildDependsOn.

<Target Name="CheckPackageJsonFileExistenceTarget">
  
<Error Condition="!Exists('$(ProjectDir)\package.json')" 
         Text
="The file 'package.json' does not exists." />
</
Target>
CheckPackageJsonFileExistenceTarget

Do projektu teraz pridáme nový súbor a to tak, že klikneme pravým tlačidlom myšky v okne Solution Explorer na náš projekt a z menu vyberieme možnosť
  • Add
  • New Item...
  • JavaScript File
ako názov zadáme "package.json" a potvrdíme stlačením tlačidla Add. Do súboru doplníme nasledovný obsah, ktorý definuje názov balíčka/projektu a zoznam balíčkov (devDependencies), ktoré budeme používať pri builde. Balíček je označený ako privátny pomocou property private. Pri vytváraní tohto súboru si možeme pomôcť aj samotným npm a to tak, že v príkazovom riadku zavoláme npm init a spustí sa konzolový wizard, ktorý nám pomôže pri jeho tvorbe.

{
  
"name""gruntmvcdemo",
  
"version""1.0.0",
  
"private"true,
  
"devDependencies": {
    
"grunt""^1.0.1"
  
}
}
package.json

Momentálne máme v package.json len jedinú závislosť a to na balíčku grunt. Postupne sem však budeme pridávať ďalšie balíčky.

Aby sme mohli grunt volať z príkazového riadku, potrebujeme mať nainštalovaný balíček grunt-cli. Tento budeme inštalovať ako globálny balíček (viď. prepínač -g), čo je aj dôvod prečo sme ho nedali medzi devDependencies v súbore package.json. Stačí totiž, aby tento balíček bol nainštalovaný len raz. Vytvoríme teda ďalší target InstallGruntCliTarget a pridáme ho do BuildDependsOn:

<Target Name="InstallGruntCliTarget">
  
<Message Importance="high" 
           Text
="Installing 'grunt-cli' package:" />
  <
Exec Command="call npm install -g grunt-cli > $(ConsoleOutputFile)" 
        WorkingDirectory
="$(ProjectDir)" />
  <
Delete Files="$(ConsoleOutputFile)"/>
  <
Message Importance="high" Text="... done" />
</
Target>
InstallGruntCliTarget

Ďalší target InstallNpmPackagesTarget zabezpečí, že sa pri builde nainštalujú všetky balíčky definované v package.json.

<Target Name="InstallNpmPackagesTarget">
  
<Message Text="Installing npm packages:" Importance="high" />
  <
Exec WorkingDirectory="$(ProjectDir)" 
        Command
="call npm install > $(ConsoleOutputFile)" />
  <
Delete Files="$(ConsoleOutputFile)"/>
  <
Message Text="... done" Importance="high" />
</
Target>
InstallNpmPackagesTarget

Keď teraz spustíme rebuild projektu/solution, mal by v adresárovej štruktúre vzniknúť adresár node_modules, ktorý obsahuje nami definované devDependencies. Tento adresár nemusíme pridávať do projektu.

Ďalším krokom je spustenie grunt tasku počas build-u. Jednotlivé grunt tasky sa definujú v súbore gruntfile.js. Ten nemáme zatiaľ vytvorený. Preto si najprv pridáme kontrolný target CheckGruntFileExistenceTarget, ktorý zastaví build v prípade, že sa tento súbor v projekte nenachádza.

<Target Name="CheckGruntFileExistenceTarget">
  
<Error Condition="!Exists('$(ProjectDir)\gruntfile.js')"
         Text
="The file 'gruntfile.js' does not exists." />
</
Target>
CheckGruntFileExistenceTarget

Rovnakým spôsobom ako pri package.json pridáme do projektu nový javascript-ový súbor gruntfile.js:

module.exports = function (grunt) {
    
// Konfiguracia pre grunt tasky
    
grunt.initConfig({
    })
;

    
// Task ktory sa bude volat pri builde
    
grunt.registerTask("build"function (target) {
        
if (!target) {
            grunt.fail.fatal(
"Missing build configuration.");
            return;
        
}

        
// Zoznam taskov ktore sa pustaju vzdy bez
        // ohladu na zvolenu konfiguraciu
        
var tasks [
        ]
;

        
// Podla zvolenej konfiguracie doplnime zoznam
        // taskov, ktore sa maju spustit
        
switch (target.toUpperCase()) {
            
case "DEBUG":
                console.log(
"BUILD : DEBUG.");
                break;
            case 
"RELEASE":
                console.log(
"BUILD : RELEASE.");
                break;
            default
:
                
// Neznama konfiguracia
                
grunt.fail.fatal("Unknown build configuration '" + target + "'");
                break;
        
}

        
// Spustime vsetky zadefinovane tasky
        
grunt.task.run.apply(grunt.task, tasks);
    
});
};
gruntfile.js

Keď z príkazového riadku spustíme príkaz grunt ten spustí by default task, ktorý sa volá default. My takýto task zadefinovaný nemáme. Namiesto toho máme definovaný task s názvom build. Pre tento task je definovaná callback funkcia, ktorá podľa zadaného prepínača (parameter target) dynamicky nastaví zoznam taskov, ktoré sa majú spustiť. Tento prepínač budeme nastavovať podľa zvolenej konfigurácie vo Visual Studiu. Je totiž predpoklad, že budeme volať iné tasky, prípadne tie isté tasky ale s inou konfiguráciou v závislosti od konfigurácie pre ktorú sa builduje samotný projekt.

Do BuildDependsOn doplníme volanie ďalšieho targetu GruntBuildTarget, ktorý spustí grunt build task s príslušnou konfiguráciou:

<Target Name="GruntBuildTarget">
  
<Message Text="Running grunt:" Importance="high" />
  <
Exec WorkingDirectory="$(ProjectDir)" 
        Command
="call grunt build:$(Configuration)" />
  <
Message Text="... done" Importance="high" />
</
Target>
GruntBuildTarget

Keď teraz rebuild-neme projekt/solution, v závislosti od zvolenej konfigurácie, sa do output okna zapíše: BUILD : DEBUG alebo BUILD : RELEASE. Máme teda úspešene za sebou integráciu grunt-u do Visual Studia. V ďalšej časti si ukážeme a nakonfigurujeme niektoré grunt tasky používané pri tvorbe web aplikácií.

Publikované Friday, May 06, 2016 9:28 AM xxxmatko

Komentáre

Bez komentárov