web-dev-qa-db-fra.com

Comment utiliser les routes AngularJS avec Express (Node.js) lorsqu'une nouvelle page est demandée?

J'utilise Express, qui charge AngularJS à partir d'un répertoire statique. Normalement, je demanderai http://localhost/, dans lequel Express me sert mon index.html et tous les bons Angular, etc. Dans mon Angular, j'ai configuré ces itinéraires, qui remplacent le contenu d'un ng-view:

$routeProvider.when('/', {
    templateUrl: '/partials/main.html',
    controller: MainCtrl,
});

$routeProvider.when('/project/:projectId', {
    templateUrl: '/partials/project.html',
    controller: ProjectCtrl,
});

$locationProvider.html5Mode(true);

Sur ma page principale, j'ai un lien vers <a href="/project/{{project.id}}">, qui chargera le modèle avec succès et me dirigera vers http://localhost/project/3 ou l'ID que j'ai spécifié. Le problème est lorsque j'essaie de diriger mon navigateur vers http://localhost/project/3 ou actualisez la page, la demande va au serveur Express/Node, qui retourne Cannot GET /project/3.

Comment configurer mes itinéraires Express pour s'adapter à cela? Je suppose que cela nécessitera l'utilisation de $location in Angular (bien que je préfère éviter les recherches laides et les #hashes qu'ils utilisent), mais je ne sais pas comment procéder pour configurer les routes express pour gérer cela.

Merci.

52
winduptoy

Je voudrais créer un gestionnaire fourre-tout qui exécute après vos routes régulières qui envoie les données nécessaires.

app = express();
// your normal configuration like `app.use(express.bodyParser());` here
// ...
app.use(app.router);
app.use(function(req, res) {
  // Use res.sendfile, as it streams instead of reading the file into memory.
  res.sendfile(__dirname + '/public/index.html');
});

app.router est le middleware qui exécute tous vos itinéraires Express (comme app.get et app.post); normalement, Express place cela à la toute fin de la chaîne du middleware, mais vous pouvez également l'ajouter explicitement à la chaîne, comme nous l'avons fait ici.

Ensuite, si l'URL n'est pas gérée par app.router, le dernier middleware enverra la vue Angular HTML vers le client. Cela se produira pour any URL qui n'est pas gérée par l'autre middleware, donc votre application Angular devra gérer correctement les itinéraires invalides.

46
Michelle Tilley

avec express 4, vous voulez probablement intercepter toutes les demandes et les rediriger vers la page angularjs index.html. app.use(app.router); n'existe plus et res.sendfile est déconseillé, utilisez res.sendFile avec une majuscule [~ # ~] f [~ # ~] .

app.post('/projects/', projectController.createProject);
app.get('/projects/:id', projectController.getProject);
app.get('*', function (req, res) {
    res.sendFile('/public/index.html');
});

mettez toutes vos routes API avant la route pour chaque chemin app.get('*', function (req, res){...})

65
Guillaume Vincent

Je suppose que j'aurais dû clarifier que je n'étais pas intéressé à utiliser un moteur de modèle, mais avoir Angular tirer tous les partiels HTML de lui-même, Node fonctionne complètement comme un serveur statique ici (mais ce ne sera pas le cas pour l'API JSON. Brian Ford montre comment le faire en utilisant Jade ici: http://briantford.com/blog/angular-express.html

Mon application est une application d'une seule page, j'ai donc créé un itinéraire Express pour chaque modèle d'URL possible, et chacun fait la même chose.

fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, content) {
    res.send(content);
});

Je supposais que je devrais transmettre certaines variables de demande à Angular, mais cela ressemble à Angular s'en occupe automatiquement.

3
winduptoy