Wer ein Grunt-Skript für seine Automatisierungsaufgaben erstellt, benötigt schnell einen Debugger mit leistungsfähiger GUI, z.B. den Entwicklertool des Chrome-Browsers. Leider gilt wie immer, dass Grunt auf Linux entwickelt wurde und deswegen die Debugging-Möglichkeiten unter Windows etwas hakeln oder die vorgeschlagenen Lösungen im Netz nicht für Windows funktionieren. Im folgenden wird gezeigt, wie man unter Windows mit dem Chrome-Entwicklerwerkzeug arbeiten kann, um seine Grunt-Skripte zu debuggen.
Voraussetzung für die folgende Vorgehensweise ist die ordentliche Installation von Grunt unter Windows. Hierzu hatte ich schon einen Blogbeitrag geschrieben und dort anhand eines einfachen Beispiels dargestellt, wie man mit Grunt grundsätzlich arbeitet.
Wir testen unsere Vorgehensweise für den Einsatz des Chrome-Debugger unter Windows anhand des folgenden kleinen Grunt-Skripts:
module.exports = function(grunt) { grunt.initConfig({ pkg : grunt.file.readJSON('package.json'), 'node-inspector': { dev: {} }, 'mytask': { "main": { filelist: "input.txt", dest : "C:\\Work\\tmp" } }, }); grunt.loadNpmTasks('grunt-shell'); grunt.loadNpmTasks('grunt-node-inspector'); grunt.registerTask('mytask', 'This is my task', function() { console.log('My task is doing something with following parameters: '); debugger; console.log('filelist: ' + grunt.config('mytask.main.filelist')); console.log('dest: ' + grunt.config('mytask.main.dest')); console.log('..... processing .....'); console.log('My task is ready!'); }); }
Das Grunt-Skript enthält nur eine Aufgabe mytask. Nach dem Starten läuft das Skript durch und gibt einige Zeilen auf der Console aus. Zu sehen ist in grunt.registerTask(...) ein Skript-Breakpoint (debugger;), an dem das Programm im Debug-Modus anhalten soll. Ohne Debug-Modus wird die Zeile ignoriert.
Wir benötigen für das Debugging das Node.js-Plugin node-inspector, welches wir global installieren, damit wir es in jeder Console direkt aufrufen können. Das zugehörige Grunt-Modul grunt-node-inspector installieren wir außerdem lokal (natürlich aus unserem Projektverzeichnis heraus).
npm install -g node-inspector npm install grunt-node-inspector --save-de
Den Node Inspector haben wir im Skript unter initConfig auf die simpelste Weise konfiguiert (s. oben) und dort auch die Abhängigkeiten zum entsprechenden lokalen Grunt-Modul geladen (loadNpmTasks).
Nach der Installation rufen wir eine neue Console auf, geben node-inspector ein und starten damit den Server.
C:\xampp\htdocs\TestProject>node-inspector
Diese Konsole lassen wir jetzt offen und beachten sie nicht weiter. Der Node Inspector verrichtet jetzt als Service im Hintergrund seine Arbeit, bis wir die Console wieder schließen.
Als nächstes müssen wir in einer weiteren (neuen !) Console unser zu testendes Grunt-Skript im Debug-Modus starten.
Normalerweise nutzt man dazu die Möglichkeiten von Node.js, indem man "node-debug $(which grunt) mytask" eingibt. Leider funktioniert dies nicht unter Windows. Dort wird der Debugger so gestartet:
node --debug-brk c:\Users\<user>\AppData\Roaming\npm\node_modules\grunt-cli\bin\grunt mytask
Für <user> ist hier der eigene Windows-Login-Name einzusetzen, in meinem Fall z.B. admin.
Wir starten jetzt Chrome und geben als Url ein:
http://127.0.0.1:8080/debug?port=5858
Wir sollten jetzt ungefähr Folgendes auf unserem Bildschirm haben:
Abb. 1: Screen mit Node-Inspector, Skript im Debug-Mode und Chrome-Entwicklerwerkzeug
Der Debugger hält in der ersten verfügbaren Zeile unseres Skripts, wie wir an dem blauen Balken rechts oben in unserem Entwickler-Tool sehen. Um zu dem gesetzten Debugger-Halt zu gelangen, starten wir das Skript dort mit dem Run-Button (Pfeil). Beachtet die Ausgaben von console.log(...) im zweiten Console-Fenster, wenn ihr beim debugger;-Befehl angekommen seid und im Step-Modus weitergeht.
Unter Firefox funktioniert das übrigens auch, allerdings ist die Benutzeroberfläche nicht so schön. Das Plugin ist für Chrome optimiert.
Damit verfügt ihr über eine sehr leistungsfähige Möglichkeit, eure Grunt-Skripte zu debuggen.
Allerdings sind wir mit dem Komfort noch nicht zufrieden. Die Kommandos - insbesondere das, mit dem wir unser Skript im Debug-Modus starten - sind zu lang und wenn wir 14 Tage nicht mehr mit Grunt gearbeitet haben, haben wir alles wieder vergessen.
Debugging komfortabel starten
Es gibt unter Windows die Möglichkeit, die Anwendung zusammen mit dem Debugger per Batch-Programm zu starten. Hier ein Vorschlag für ein Skript debug.bat:
echo off taskkill /im node.exe /f start /B "Node Inspector" node-inspector start /B "Grunt task" node --debug-brk c:\Users\admin\AppData\Roaming\npm\node_modules\grunt-cli\bin\%* start "Chrome" "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" http://127.0.0.1:8080/debug?port=5858
Am Anfang wird ein eventuell noch offener Node-Prozess, der in der Regel von einem vorherigen Aufruf übrig geblieben ist, beendet. Diese Zeile kann man ausklammern (mit REM davor), z.B. wenn bestimmte Node-Server durchlaufen sollen. Leider bleibt bei dem hier ausgeführten Skript immer ein node.exe-Prozess offen.
Das Skript ist leicht verständlich, wenn man sich bewußt macht, dass
- start den folgenden Befehl in einer eigenen Console öffnet und
- der Parameter /B diese Console versteckt und die Ausgabe in die erste Console umleitet.
Gestartet wird die Grunt-Task dann mit:
debug grunt mytask
Aufgrund der Probleme, die unter Windows auftreten, wenn man eine ähnliche Lösung nur mit Grunt implementieren möchte, weil Grunt für asynchron gestartete Prozesse z.B. für Chrome kein definiertes Ende findet, ist dies vielleicht sogar die beste Lösung, auch wenn diese Lösung noch den kleinen Schönheitsfehler besitzt, dass nach dem Beenden noch ein node.exe-Prozess übrig bleibt. Vielleicht fällt einem Leser eine gute Lösung für dieses Problem ein, das aber vorerst für die Entwicklung von eigenen Grunt-Automatisierungstasks nicht weiter stört.