Symfony2 im Backend und AngularJS im Frontend, das war die Wahl für ein internes Projekt zur Teamplanung bei meinem Praktikum im September/Oktober 2013.
Eine besondere Herausforderung von Zusammenfügen der beiden Frameworks, sodass sie angenehm miteinander harmonieren, da beide ihr eigenes Routing mitbringen.
Soll hier Symfony das Routing übernehmen oder soll AngularJS das alles regeln? Brauche ich eine spezielle Webserverkonfiguration?
In diesem Artikel möchte ich beschrieben, wie die Projektstruktur aussehen muss, damit Symfony2 und AngularJS bequem zusammen spielen und es keine Kompilkationen mit Updates und dem Deployment gibt.
Prinzipielles Vorgehen
Nach einigem Ausprobieren und Gesprächen im Team habe ich mich entschlossen, wie folgt vorzugehen:
- den Webserver so zu konfigurieren, damit er den ersten Teil des Routings übernimmt
- alle Anfragen nach
/api/*
an den Symfony2 Front-Controller zu leiten - eine statische Datei auszuliefern, damit sie über die URL gefunden werden kann
- AngularJS One-Page-App auszuliefern wenn an der URL keine Datei gefunden wird
Dies sieht am Beispiel von nginx folgendermaßen aus:
server { listen *:80; server_name example.com; location ~ ^/api.+$ { root /path/to/project/api/web; index app.php; rewrite ^(.+)$ /app.php/$1 last; } location ~ ^/app\.php($|/) { root /path/to/project/api/web; index app.php; fastcgi_buffer_size 512k; fastcgi_buffers 16 512k; fastcgi_busy_buffers_size 512k; fastcgi_index app.php; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.+)$; include fastcgi_params; } location / { root /path/to/project/dist; try_files $uri $uri/ /index.html =404 ; index index.html; } }
Die Teile der Konfiguration dabei sind:
location ~ ^/api.+$
schreibt die Requests von/api/*
an die app.php umlocation ~ ^/app\.php($|/)
leitet die Requests der app.php an php-fpm weiterlocation /
probiert erst mittry_files
die Datei und leitet sonst an AngularJS weiter
Keine Probleme mit Updates von Composer & Co.
Die Ordnerstruktur im Projekt gleicht grundsätzlich dem Angular Template von Yeoman, mit Symfony in einem Unterordner:
/app
(Angular-Sourcedateien für Entwicklung)/dist
(gebaute JS Dateien für Produktivumgebung)/api
(Symfony Hauptordner)
Somit ist die Struktur flexibel, Grunt, Bower etc. funktionieren dann wie in jedem anderen Yeoman-Projekt, Composer wird einfach im Symfony-Ordner ausgeführt.
Deployment mit Capistrano
Ein weiterer interessanter Teil des Setups war das Deployment mit Capifony, einem Addon für Capistrano für Symfony. Da Symfony nicht wie erwartet im Hauptordner des Repositorys liegt, war die Konfiguration eine echte Herausforderung.
Zu guter Letzt sind aber nur ein paar Änderungen an der Konfiguration notwendig, um auch dieses Problem aus der Welt zu schaffen. Hier ist eine Übersicht der wichtigsten Änderungen an der Standardkonfiguration für Symfony2:
set :cache_path, "api/app/cache"
set :composer_options, "--no-dev --verbose --prefer-dist --optimize-autoloader --working-dir=api"
set :composer_dump_autoload_options, "--optimize --working-dir=api"
set :symfony_console, "api/app/console"
shared_files
/shared_children
auf die richtigen Pfade setzen
Für das Deployment des Javascript-Codes ist das Capistrano Plugin für Grunt hilfreich. Mit einigen weiteren Änderungen lassen sich noch npm und Bower ausführen:
before 'deploy:finalize_update', 'grunt' before 'grunt', 'bower:install' before 'bower:install', 'npm:install' set :grunt_tasks, ['build'] namespace :bower do desc "Install bower components" task :install do run "cd #{release_path} && bower install --production --quiet" end end namespace :npm do desc "Install npm components" task :install do run "cd #{release_path} && npm install --quiet" end end
Fazit
Die hier gezeigten Lösungen haben sich im Projekt bewährt, da die Konfiguration im Gegensatz zu anderen Varianten keinen speziellen Code oder große Änderungen an weiteren Config-Dateien nach sich zieht. Dadurch bleibt das Projekt übersichtlich und auch für andere Entwickler verständlich und es ergibt sich die Möglichkeit Tools wie Capistrano zu benutzen, um bspw. automatisiert zu deployen oder testen.
Ausblick
Aufgrund der Webserver-Konfiguration, muss irgendwie sichergestellt werden, dass alle Entwickler im Team die gleiche Basisumgebung haben. Darüber hinaus sollte es für neue Entwickler im Team möglich sein, gleich mit der Arbeit zu beginnen und keine Zeit verschwenden zu müssen um z.B. die Infrastruktur einzurichten oder sich um deren Abhängigkeiten Gedanken zu machen. Hier könnte Vagrant der beste Lösungsansatz sein, um den Entwicklern das Leben ganz einfach zu erleichtern- denn mit Vagrant lassen sich schnell virtuelle Maschinen (inkl. aller benötigten Komponenten) erstellen, die dann das gesamte Team nutzen kann, so dass alle mit exakt den gleichen Bibliotheken und Infrastrukturkomponenten in identischen Versionen arbeiten.
Schreibe einen Kommentar