Mit Gulp nach SharePoint deployen

Nachdem man nun also seine Entwicklungsumgebung mit VSCode, Node, Bower und Gulp schon sehr gut im Griff hat, stellt sich noch die Frage: wie bekomme ich meine Dateien nun in den SharePoint?

Mit Hilfe von Gulp habe ich ja schon alles nett in einem Verzeichnis (z.B. dist) zusammen. Also muss ich das ja nur alles in den SharePoint laden. Dank Drag&Drop ist das ja recht einfach und der Browser bietet mir ja auch direkt an vorhandene Dateien zu ersetzen. Aber auf die Dauer ist es ja doch irgendwie nervig.

Eigentlich ist die Lösung recht einfach: WebDAV!

Ich kann ja jede SharePoint Bibliothek über WebDAV erreichen. Wenn ich nun auch weiß, dass ich diese WebDAV-Freigaben über eine UNC-Schreibweise ansprechen kann … so kann ich die Bibliothek http://sharepoint.acme.local/sites/henning/scripts auch über \\sharepoint.acme.local\DavWWWRoot\sites\henning\scripts ansprechen.

Entsprechend kann ich in meinem gulpfile.js einfach folgende Task mit aufnehmen

gulp.task('deploy', [], function () {
    return gulp.src(['dist/**/*'])
        .pipe(gulp.dest(\\sharepoint.acme.local\DavWWWRoot\sites\henning\scripts));
};

Wenn ich nun z.B. nach SharePoint-Online deployen will, dann geht das dort ebenfalls, nur dass ich \\henning.sharepoint.com@SSL\[…] schreiben muss, damit der Zugriff per SSL läuft (ich kann SSL natürlich auch bei On-Premise Installationen verwenden, nur bei Office365 geht halt ausschließlich SSL).

Gulp: Wie Coffeescript zu JavaScript wird

Nachdem ja nun einfache Dinge mit gulp automatisiert werden können, kann man sich ja so langsam mal an weitere Aufgaben begeben.

Coffeescript kann bei der Arbeit mit JavaScript ja schon mal ganz hilfreich sein, nimmt es einem doch manch lästige Zeremonie von JavaScript ab und fügt gleich noch Best-Practices hinzu. Wenn man nicht immer diese .coffee-Datei nach JavaScript übersetzen (compilieren) müsste.

Mit gulp kann man das sehr gut automatisieren.

npm install gulp-coffee --save-dev

sorgt dafür, dass ich das notwendige gulp-coffee Package habe. Nun also noch eine entsprechen Task im gulpfile.js einfügen.

gulp.task('coffee', function () {
    return gulp.src('app/*.coffee')
        .pipe(coffee())
        .pipe(gulp.dest('app'));
})

In diesem Fall werden also alle von Coffee-Script erzeugten Dateien ebenfalls in dem Verzeichnis app gespeichert.

Insgesamt sieht das Build Script nun so aus:

var gulp = require('gulp'),
    coffee = require('gulp-coffee'),
    uglify = require('gulp-uglify');

gulp.task('html', function () {
    return gulp.src('app/*.html')
        .pipe(gulp.dest('dist'));
})

gulp.task('js', ['coffee'], function () {
    return gulp.src('app/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('dist'));
})

gulp.task('coffee', function () {
    return gulp.src('app/*.coffee')
        .pipe(coffee())
        .pipe(gulp.dest('app'));
})

gulp.task('default', ['html', 'js'], function () {
})

Die Task „js“ ist dabei Abhängig von der Coffee-Task. In der Konsole sieht die Ausführung dann so aus:

D:\projects\html_app>gulp
[14:43:24] Using gulpfile D:\projects\html_app\gulpfile.js
[14:43:24] Starting 'html'...
[14:43:24] Starting 'coffee'...
[14:43:24] Finished 'coffee' after 34 ms
[14:43:24] Starting 'js'...
[14:43:24] Finished 'html' after 47 ms
[14:43:24] Finished 'js' after 43 ms
[14:43:24] Starting 'default'...
[14:43:24] Finished 'default' after 13 μs

Gerade beim Umgang mit Coffeescript ist das Debugging des JavaScript Codes z.B. in der Konsole der Browsers etwas umständlich, denn hier wird ja nicht der eigentliche Coffeescript Code debuged, sondern der von Coffeescript erzeugte JavaScript Code. Moderne Browser können aber mit Hilfe von sogenannte SourceMaps auch den ursprünglichen Quellcode anzeigen und debuggen – hier also Coffeescript. Und auch dabei kann gulp helfen.

Dazu erweitern wir die Task coffee entsprechend.

gulp.task('coffee', function () {
    return gulp.src('app/*.coffee')
        .pipe(sourceMaps.init())
        .pipe(coffee())
        .pipe(sourceMaps.write('../dist'))
        .pipe(gulp.dest('app'));
})

Nun wird für jede Coffeescript-Datei eine entsprechende SourceMap-Datei in dem Verzeichnis dist erstellt.

Gulp: JavaScript-Buildsystem

Nachdem ich ja im letzten Post beschrieben habe, wie man mit Hilfe von node und bower sich JavaScript Bibliotheken für seine Anwendung einbinden kann, will ich nun noch etwas mehr zeigen, was einem Node so zu bieten hat.

Typische Aufgabe während der Entwicklung ist ja, dass die HTML und JavaScript-Dateien vom lokalen Rechner auf einen Web-Server kopiert werden müssen. Dazu müssen zunächst alle Dateien, die auf den Server kopiert werden müssen identifiziert und dann kopiert werden.

In reinen .Net Projekten würde ich für das Deployment vielleicht zu MSBuild greifen – das hilft mir aber in meinem Fall nicht so wirklich weiter.

Mit gulp gibt es ein Buildsystem als Node-Module in JavaScript.

npm install gulp -g

installiert gulp und stellt es global zur Verfügung. Nun kann ich in meinem Projekt ein gulpfile.js erstellen.

Ein einfaches Buildfile kann z.B. so aussehen:

var gulp = require('gulp');
gulp.task('copy', function(){
    return gulp.src('app/*.html')
        .pipe(gulp.dest('dist/'));
})

Dabei werden alle *.html Dateien aus dem Verzeichnis app in das Verzeichnis dist kopiert. Existiert das Verzeichnis dist noch nicht, wird es zuvor erstellt. Dieses Beispiel ist natürlich sehr einfach. Mittels gulp copy kann nun die neue copy-Task von einer Konsole ausgeführt werden:

D:\projects\html_app>gulp copy
[14:25:01] Using gulpfile D:\projects\html_app\gulpfile.js
[14:25:01] Starting 'copy'...
[14:25:01] Finished 'copy' after 17 ms

Ein etwas fortgeschritteneres Buildfile könnte wie folgt aussehen:

var gulp = require('gulp'),
    uglify = require('gulp-uglify');

gulp.task('html', function () {
    return gulp.src('app/*.html')
        .pipe(gulp.dest('dist'));
})

gulp.task('js', function () {
    return gulp.src('app/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('dist'));
})

gulp.task('default', ['html', 'js'], function () {
})

Die Task default wird dabei automatisch aufgerufen, wenn man gulp von der Kommandozeile startet. Als zweiter Parameter der Task werden die abhängigen Tasks angegeben. Diese werden also automatisch zuvor ausgeführt.

D:\projects\html_app>gulp
[14:26:15] Using gulpfile D:\projects\html_app\gulpfile.js
[14:26:15] Starting 'html'...
[14:26:15] Starting 'js'...
[14:26:15] Finished 'js' after 39 ms
[14:26:15] Finished 'html' after 49 ms
[14:26:15] Starting 'default'...
[14:26:15] Finished 'default' after 12 μs

In diesem Fall werden alle *.js Datei aus dem Verzeichnis app mit dem uglify-Package minimiert und dann nach dist geschrieben. Somit kann man also in dem app-Verzeichnis die Anwendung entwickeln und in dist erhält man immer alle Dateien, die man auf den Server kopieren muss.