AngularJS mit RequireJS aufsetzen

RequireJS ist wunderbar geeignet, um JavaScript-Code zu modularisieren. AngularJS ist ein gut gemachtes MVC-Framework mit Data-Binding. Es liegt nahe, in einem Projekt beide Technologien zu verwenden. Leider geht das nicht "out of the box" - das liegt daran, dass AngularJS die Controller im globalen JavaScript-Scope sucht und sie natürlich nicht findet, wenn wir diese in einer define-Anweisung deklarieren.

AngularJS muss also leider von Hand aufgesetzt werden, was allerdings gar nicht so schwer ist, wenn man ein paar Stolperfallen vermeidet. Mein hier beschriebenes Setup ist sehr minimalistisch. Wenn das Projekt größer wird, macht evtl. das von Dmitry Evseev beschriebene Setup Sinn.

Verzeichnisstruktur

Das Projekt folgt der von RequireJS empfohlenen Struktur: Die main.js liegt in einem Verzeichnis js . Darunter je ein Verzeichnis lib für (Fremd)-Bibliotheken und app für unsere eigenen Scripte - in diesem Fall für die AngularJS-Controller. Im Top-Level liegen die HTML-Dateien und in einem richtigen Projekt auch CSS, Bilder etc.

HTML

<!DOCTYPE html>
<html lang="de"><!-- kein ng-app! -->
<head>
  <title>RequireJS mit AngularJS</title>
  <script data-main="js/main"
          src="js/lib/require.js"></script>
</head>
<body ng-controller="StartCtrl">
  {{'{' + '{greeting}' + '}'}}
</body>
</html>
			

In der index.html wird natürlich nur RequireJS eingebunden. Hier gibt es keine Überraschungen.

Die gibt es hingegen beim Angular-Part: Das HTML-Tag bleibt frei von einem ng-app . Das muss so sein, damit AngularJS nicht versucht, sich selbst zu initialisieren, was zu Fehlern führen würde! Der Controller wird hingegen wie gewohnt deklariert.

Konfiguration

// Standard RequireJS-Konfiguration
// mit einem Shim für AngularJS
requirejs.config({
  baseUrl : 'js/lib',
  paths : {
    app : '../app'
  },
  shim : {
    'angular' : {
      exports : 'angular'
    }
  }
});

require([ "angular", "app/controller" ],
  function(angular, StartCtrl) {
  // Controller registrieren
  var ng = angular.module('ng')
  ng.controller('StartCtrl', StartCtrl);
  angular.bootstrap(document, ['ng']);
});
			

Sowohl RequireJS als auch AngularJS werden in der js/main.js aufgesetzt. Wichtig im requirejs.config ist das shim für AngularJS.

In require() wird Angular verdrahtet. Wir geben angular und unseren (einzigen) Controller als Abhängigkeiten an. Dann rufen wir das Standardmodul "ng" ab und binden unseren Controller an den Namen, den wir in der index.html angegeben haben. Leider tut sich so noch garnichts. Erst nach einem Aufruf von bootstrap() ist AngularJS vollständig initialisiert.

Eine Abhänigkeit zu domReady sollte man hier nicht deklarieren, sonst sieht man die Angular-Ausdrücke {{}} für eine kurze Zeit. domReady kann man in einem weiteren require() verpacken.

Controller

define(function() {
  // Erstellt den Controller für die Seite
  return function($scope) {
    $scope.greeting = "Hallo Welt!";
  };
});
			

In der Demo-Seite gibt es nur einen Controller, der in der gleichnamigen JavaScript-Datei steckt. Das ist straight forward: Es wird die Funktion exportiert, die man sonst direkt in den globalen JavaScript-Scope geschrieben hätte.

Damit wäre unsere kleine Demo fertig. Wer zu faul zum abtippen ist, kann sich das ZIP runterladen. Ich hoffe, ich konnte einigen von euch weiterhelfen und motivieren, RequireJS zusammen mit AngularJS einzusetzen!

Weitere Links: