web-dev-qa-db-fra.com

Mode HTML5 AngularJS - Comment fonctionnent les liens directs sans modifications spécifiques au serveur?

Remarque: Cette question pourrait également se lire:

Comment prendre en charge le bookmarking des frameworks mvc côté client sans hashbang en Java.

Je transfère une application angular qui utilise hashtags vers une application qui est html5mode. J'ai réussi à régler

$locationProvider.html5Mode(true);

Et tous les liens de la page de destination (index.html) fonctionnent correctement.

Le problème est que, si les URL partielles sont référencées directement, j'obtiens un 404, naturellement, car les définitions de point de terminaison du serveur ne sont pas couplées à des itinéraires définis côté client.

Donc, sans HTML5, nous obtenons des hashbangs non optimisés pour le référencement, mais avec lui, nous ne pouvons pas mettre en signet autre chose que la page de destination (la page qui démarre angulairement).

Pourquoi cela fonctionne-t-il si vous demandez d'abord la page de destination par défaut (index.html), c'est-à-dire htpp: //mydomain.com/:

  1. Le navigateur demande index.html au serveur
  2. Le serveur renvoie index.html et le navigateur charge angular
  3. Les modifications d'URL sont envoyées au routeur côté client et le ou les partiels appropriés sont chargés.

Pourquoi cela ne fonctionne pas si (ie) http://mydomain.com/foo est demandé directement depuis le navigateur:

  1. Le navigateur demande mon domaine/foo au serveur.
  2. La ressource n'existe pas
  3. Le serveur renvoie 404

Quelque chose manque dans cette histoire, je ne sais pas quoi. Voici les deux seules réponses que je peux voir ...

  • C'est par conception. Est-ce ainsi que cela est censé fonctionner? Que les utilisateurs doivent toujours atterrir sur la page bootstrap (généralement index.html) du framework MVC client, puis y naviguer. Ce n'est pas idéal car l'état ne peut pas être enregistré et il n'y a aucun moyen de créer un signet ... sans parler de ramper.
  • Solution serveur. Est-ce que cela a été résolu avec une astuce côté serveur? Par exemple, sur toutes les demandes, retournez index.html et appelez immédiatement router avec un contexte supplémentaire. Si c'est le cas, cela va à l'encontre de l'objectif selon lequel AngularJS est complètement côté client et semble être un hack.
45
Robert Christian

La documentation AngularJS en fait mention

Côté serveur L'utilisation de ce mode nécessite une réécriture d'URL côté serveur, fondamentalement vous devez réécrire tous vos liens vers le point d'entrée de votre application (par exemple index.html)

Dans ce cas, une solution basée sur Java consiste à dire au serveur de "mapper toutes les URL vers index.html". Cela peut être fait dans n'importe quel serveur HTTP ou conteneur. J'ai implémenté cela en utilisant Java/Servet car je veux que mon application soit indépendante du serveur HTTP (c'est-à-dire Apache contre NginX, ou Tomcat/JBoss uniquement).

Dans web.xml:

  <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

  <servlet>
      <servlet-name>StaticServlet</servlet-name>
      <jsp-file>/index.jsp</jsp-file>
  </servlet>

  <servlet-mapping>
      <servlet-name>StaticServlet</servlet-name>
      <url-pattern>/app</url-pattern>
  </servlet-mapping>

Et index.jsp ressemble simplement à:

<%@ include file="index.html" %>

Et ajoutez ce qui suit à la balise dans index.html:

<base href="/app" />
39
Robert Christian

J'ai passé un peu de temps à y penser pour mon PHP. J'arrête tout mon code côté serveur hors du /api pour le séparer d'Angular. Voici la solution que j'ai trouvée en mettant à jour ma configuration Apache:

RewriteEngine on
#let the php framework do its thing
RewriteRule ^(api/.*)$ index.php?url=$1 [QSA,L,NC]
#let angular do its thing
RewriteCond %{REQUEST_FILENAME} !-f      
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.html [NC,L]

J'ai écrit comment j'y suis allé en utilisant le framework Flight PHP à http://www.awnage.com/2013/10/10/taking-flight-with-angularjs /

3
Awnage