Wie Grunt meinen Workflow für WordPress-Themes verbessert hat

Vorweg: Es geht hier nicht um Freie Themes, die über das WordPress-Repository laufen, sondern um kundenspezifische Themes, die nur via Datei verteilt werden. (Das macht es unter Umständen auch für Entwickler von Premium-Themes interessant).

Wie arbeite ich und womit?

Ich arbeite mittlerweile extrem gerne mit LESS und das war der Grund, warum ich Grunt überhaupt einzusetzen begonnen habe. Da ich aber ungern mit der JS-Version rumspiele, um später mein WP-Theme für “Production” wieder umzubauen, benutzte ich in meinem letzten Projekt, bei dem das Styling umfangreicher wurde, WinLess. Allerdings nutze ich gerne und exzessiv die Möglichkeit von LESS, Dateien auszulagern und an beliebigen Orten wie bei einem php include() einzubinden. Das hat zur Folge, dass mein “Haupt”-LESS-File in der Regel ein paar Konstanten wie Farben enthält, sonst aber alles nur mit @import eingebunden wird. Direkte Folge daraus ist, dass das Haupt-Stylesheet recht selten geändert wird. Da es aber wenig Sinn ergibt, jedesmal, wenn ich eine der inkludierten Dateien gespeichert habe, in die Master-Datei zu wecheln und “Leerzeichen rein, Leerzeichen raus, speichern” zu spielen, damit der Compiler anspringt, habe ich nach Alternativen gesucht und endlich eine gefunden: Grunt.

Die letzten 2 Projekte habe ich mit mit _s von underscores.me als Starter-Template begonnen, hier ist für die Zukunft dann wohl der erste Schritt, das mitgelieferte style.css in LESS zu verwandeln.

Welche Grunt-Tasks benutze ich?

In der Kurzform:

grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-compress');

In der Langform:

Zuerst einmal benutze ich grunt-contrib-less um LESS in CSS umzuwandeln. Hierzu habe ich zwei Versionen: “dev” und “prod”. Die beiden Versionen unterscheiden Sich da nur minimal:

less: {
  dev: {
    options: {
      paths: ["less"]
    },
    files: {
      "style.css": "style.less"
    }
  },
  prod: {
    options: {
      paths: ["less"],
      compress: true
    },
    files: {
      "style.css": "style.less"
    }
  }
},

Die “Production”-Version wird im Gegensatz zur Development-Version komprimiert, d.h. es werden alle Kommentare und überflüssige Leerzeichen und Zeilenumbrüche werden entfernt. Die dev-Version enthält dabei Zeilenumbrüche und CSS-Kommentare mit /* Kommentar */ werden dabei nicht entfernt.

Da WordPress aber mit dem Kommentar am Anfang der style.css arbeitet, brauchen wird dort einen Kommentar.
Ich habe meinen Theme-Header z.B. in der Datei “less/wp_header.less”. Diese Datei wird in meiner style.less-Datei importiert.

Da beim Erstellen der Produktionsversion alle Kommentare entfernt werden, muss ich in diesem Fall den Header vor das erstellte style.css einfügen.

Das mache ich mit dem concat-Task:

concat: {
  prod: {
    src: ['less/wp_header.less', 'style.css'],
    dest: 'style.css'
  }
},

Hiermit hänge ich den Header vor die style.css-Datei.

Für mich der absolute Grund, Grunt zu nutzen ist der Watcher-Task:

watch: {
  styles: {
    files: '**/*.less',
    tasks: ['less:dev']
  }
}

Hier wird definiert: Wenn ich in der Konsole “grunt watch” eingebe, wird das Verzeichnis und alle Unterdateien überwacht. Ich definiere hier, dass jede .less-Datei überwacht wird, auch in den Unterverzeichnissen. Wenn sich eine Datei ändert, wird der Task “less:dev” ausgeführt, sprich: das LESS-File wird compiliert. Mehr brauche ich nicht, um bequem entwickeln zu können.

Vorbereitung für das Deployment von “Premium”-Themes

Wenn ich freies WordPress-Theme entwicklen würde, so wie ich es mit meinen Plugins tue, dann ist das einfachste, das Theme im WordPress-Repository einzustellen. Via SVN lade ich die Sachen hoch, den Rest erledigt WordPress. Da ich aber spezielle, kundenspezifische Themes entwickle, die nicht im Repository auftauchen sollen, muss ich das Theme per Hand ausliefern.

Wenn ich die Webseite betreue, kann ich das unter Umständen noch selbst tun, indem ich meine Entwicklungsversion, wenn Sie “fertig” ist z.B. per FTP-Client hochlade.

Wenn ich ein Premium-Theme vertreibe, muss ich allerdings meinen Kunden ein neues ZIP-Paket bereitstellen. Das kann man per Hand machen, man kann es aber auch automatisieren:

compress: {
  zip: {
    files: {
      'dist/theme-name.zip': [
         '*.php',
         '*.css',
         'license.txt',
         'readme.txt',
         'screenshot.png',
         'font/**', 
         'img/**', 
         'inc/**',
         'js/**', 
         'languages/**', 
         'layouts/**', 
       ]
     },
     options: {
       'rootDir': 'theme-name'
     }
   }
},

Ich definiere also, welche Dateien zusammengepackt werden sollen. Das endgültige Theme kann auch automatisiert die Versionsnummer in den Dateinamen gekommen, wie man der Doku von grunt-contrib-compress entnehmen kann. Die Notation mit den zwei Sternen ist die so genannte “minimatch” Notation und bedeutet im Fall der Verzeichnisse, dass alle Unterverzeichnise und Dateien einbezogen werden sollen.

Im Fall des oben genannten watch-Tasks sagt der Pfad aus “.less-Dateien in jedem Verzeichnis”

Welche Tasks konfiguriere ich?

grunt.registerTask('default', ['less:dev']);
grunt.registerTask('production', ['less:prod', 'concat:prod', 'compress:zip']);

Ich brauche eigentlich nur 2 Tasks: Den Standard (für mich als Entwicklungs-Umgebung) und einen für den Production-Export. Letzterer führt nacheinander(!) die Tasks: “less:prod”, “concat:prod” und “compress:zip” aus.

Was geht noch?

Während Grunt in erster Linie auf Frontend-Dinge spezialisiert ist, und dafür auch entsprechende Testmodule unterstützt, ist ein Test für PHP beispielsweise mit PHPUnit nicht möglich. Abhilfe schaffen kann man dabei allerdings mit grunt-shell, mit dem man dann beispielsweise PHPUnit aufrufen und das Ergebnis und den Exit Code überwachen könnte.

Serverseitig wäre hier auch eine Verknüpfung mit git-hooks oder SVN-Hooks denkbar: Code nach dem Push/Checkin testen und den Entwickler benachrichtigen.

Was ist zu beachten?

Aktuell wird Grunt auf 0.4.0 geupgraded. Momentan sind alle “contrib”-Modul mit der neuen Version 0.4 kompatibel, allerdings ein Großteil der anderen Module nicht. Unter Grunt 0.3.x sind die contrib-tasks fest eingebaut und die Task-Konfiguration funktioniert etwas anders.

1 Kommentar Schreibe einen Kommentar

Hinterlasse eine Antwort

Pflichtfelder sind mit * markiert.


Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>