DokuWiki als praktisches Autorentool

Ich schrieb neulich ein Buch. Über WordPress. Ein Buch für Kunden, die eine WordPress-Installation übernehmen und selbst pflegen wollen oder sollen.

Viele Wege führen nach Rom, sagt man ja immer und ich schreibe gerne in Wikis. Versionierung, Plattformunabhängig und immer auf dem aktuellsten Stand, egal von wo man zugreift, waren für mich Gründe, das Buch mit einem Wiki als Authoringsystem zu schreiben.

Dazu brauchts nur ein paar kleine Plugins und Überlegungen: Weiterlesen

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.

Link-Ecke #56

Rechtliches und Entwicklungstechnisches diesmal.

  1. LEISTUNGSSCHUTZRECHT STOPPEN! – D-64.org
  2. Getty mahnt Blogger aufgrund von Avatar-Bild eines Kommentators ab
  3. WordPress Development and Deployment With MAMP, Git and Dropbox
  4. Import von Google Analytics Daten zu Piwik Analytik mit google2piwik mit der Google API v2.4 und API Key
  5. Import von Daten mit google2piwik erheblich beschleunigen
  6. Adobe Brackets – A web editor based on Web technology
  7. Der Firefox hat seit Version 13 die unterstützung für „-moz-border-radius“ entfernt und unterstützt nur noch „border-radius“

Mobile WordPress pre-alpha

Anlässlich des Releases von jQuery Mobile 1.1 habe ich mich mal daran gemacht, eine einigermaßen generische Version für ein WordPress-Blog mit jQuery Mobile zu schreiben. Das ganze ist derzeit alles andere als perfekt, aber ein Ansatz.

Ich versuche hier explizit, eine Alternative zu einem integrierten Ansatz wie es z.B. WordPress Mobile Pack zu entwickeln, denn wenn ein WordPress als CMS mit nur nebensächlich genutzter Blog-Funktionalität genutzt wird, kann man mit dem WordPress Mobile Pack eigentlich nichts mehr anfangen.

Das Projekt ist auch weniger als finale Version eines fertigen Packages gedacht, sondern als Vorlage und Beispiel, wie eine mobile Seite aussehen kann und wie man die Daten aus WordPress abholen kann, ohne direkt im WordPress zu sein.

Super wäre ein Tipp, wie ich die URLs möglichst einfach umschreiben kann.

Umzug einer WordPress-Seite

Ich habe gestern abend eine Internetseite umgezogen. Ein WordPress. Aus dem Bett heraus. In 20 Minuten. Mit Linux auf dem Notebook wär’s vermutlich einen Ticken schneller gegangen, aber auch nicht wirklich.

Voraussetzung für einen derart schnellen Umzug ist, dass die Seite bisher kein Emailing hat, bzw. dieses woanders liegt, und der DNS-Record vollständig konfigurierbar ist, und beide Hoster SSH-Zugriff erlauben.

Normalerweise würde man die Datenbanken auf Hoster A per PHPMyAdmin o.ä. exportieren und die Webseite-Daten per FTP herunterladen, dann auf dem neuen Hoster runterladen und die Datenbanken importieren.

Der Aufwändigste Teil war für mich das portieren der Datenbanken: Dump herunterladen, modifizieren für die neue Datenbank, dann wieder hochladen in den neuen PHPMyAdmin.

Der Rest ging einfach, weil mit wenigen Befehlen in der Konsole machbar statt ewigem Herumgeklicke und umhergelade.

  1. Einloggen bei Uberspace per SSH
  2. Navigieren in das Ziel-HTML-Root
  3. Von Uberspace aus einloggen in den Space von 1blu
  4. Navigieren in das HTML-Root der Seite.
  5. pwd eingeben und sich „1bluuser@1bluserver:/[ausgabe von pwd]/“ in die Zwischenablage kopieren
  6. Ausloggen aus 1blu
  7. Eingeben: „scp 1bluuser@1bluserver:/[ausgabe von pwd]/* .„, kurz warten (ein Server lädt die Daten direkt vom anderen Server, nix geht über den langsamen Upspeed zuhause, das macht Spaß!)
  8. Ggf. Rechte anpassen und bei WordPress z.B. die wp-config.php anpassen. Das war bei dem migrierten WordPress bisher nicht nötig, auch Uploads und Co. funktionieren einwandfrei.
  9. DNS-Eintrag A-Record auf die neue IP umstellen.

Zack. Fertig. Keine Sonderzeichen-Probleme, alles läuft.

WordPress Post Update Links 0.4.0 ist veröffentlicht

Die Version 0.4.0 des Plugins wurde veröffentlicht. Änderungen für einen „Milestone“ lt. Semver gibt es auch: Wir können jetzt Sprachen. Derzeit englisch/deutsch (ich denke, „Update“ muss man nicht übersetzen, lasse mich da aber auch gerne vom Gegenteil überzeugen) und französisch.

Links zum Plugin