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

Note: cette question pourrait aussi se lire:

comment soutenir le bookmarking des cadres mvc hashbang-less client side en Java.

je fais la transition d'une application angulaire qui utilise hashtags vers une qui est html5mode . J'ai mis avec succès

$locationProvider.html5Mode(true);

et tous les liens de la page d'accueil (index.html) fonctionne bien.

le le problème est que, si des URL partielles sont référencées directement, j'obtiens un 404, naturellement, puisque les définitions des points terminaux du serveur ne sont pas couplées aux routes définies du côté du client.

donc sans HTML5 nous obtenons des hashbangs Non-SEO amical, mais avec elle nous ne pouvons pas marquer autre chose que la page d'accueil (la page qui bootstraps angular).

Pourquoi cela fonctionne si l'on demande par défaut de la page de destination (l'index.html) d'abord, c'est à dire htpp://mondomaine.com/ :

  1. les requêtes du Navigateur de l'index.html du serveur
  2. Serveur renvoie l'index.html, et le navigateur charge angulaire cadre
  3. Les changements D'URL
  4. sont envoyés au routeur côté client et le/s partiel approprié est chargé.

pourquoi ça ne marche pas si (ie) http://mydomain.com/foo est demandé directement auprès du navigateur:

  1. Navigateur de requêtes mondomaine/foo de serveur.
  2. la ressource n'existe pas
  3. le serveur renvoie 404

il manque quelque chose dans cette histoire, Je ne sais pas quoi. Voici les deux seules réponses que je vois...

  • c'est de conception. C'est comme ça que ça doit marcher? Que les utilisateurs doivent toujours se poser sur la page bootstrap du client MVC framework (généralement index.html), puis de naviguer à partir de y. Ce n'est pas idéal parce que l'état ne peut pas être sauvé et il n'y a aucun moyen de marquer des pages... pour ne pas mentionner l'analyse.
  • solution de serveur. est-ce que cela fonctionne avec une astuce côté serveur? Par exemple, sur toutes les demandes, l'indice de rendement.html et appeler immédiatement routeur avec contexte supplémentaire. Si c'est le cas, cela va à l'encontre de l'objectif que AngularJS est complètement client-côté et semble comme un piratage.
45
demandé sur Robert Christian 2013-07-15 08:35:18

3 réponses

le AngularJS documentation ne mentionne en fait ce

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

dans ce cas, une solution basée sur Java est de dire au serveur" map all urls to index.HTML."Cela peut être fait dans N'importe quel HTTP Serveur ou conteneur. J'ai implémenté cela en utilisant Java / Servet puisque je veux que mon application soit agnostique (C'est-à-dire Apache versus NginX, ou Tomcat/JBoss seulement).

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 ajouter ce qui suit à la balise dans l'index.html:

<base href="/app" />
38
répondu Robert Christian 2015-10-30 16:46:18

j'ai passé du temps à y réfléchir pour mon site PHP. J'accroche tout mon code côté serveur sur la route /api pour le garder séparé de L'angle. Voici la solution que j'ai trouvée en mettant à jour ma config apache:

RewriteEngine on
#let the php framework do its thing
RewriteRule ^(api/.*)$ index.php?url= [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'ai fait avec le Flight PHP framework à http://www.awnage.com/2013/10/10/taking-flight-with-angularjs /

3
répondu Awnage 2013-10-10 15:41:25

les URL que vous liez et placez dans la barre d'adresse de l'utilisateur, doivent renvoyer au contenu valide sur le serveur, et si possible, ils doivent renvoyer au contenu correct . Bien sûr, vous pouvez juste servir la même page pour chaque URL, et avoir le code client aller off et charger le contenu réel, et les choses fonctionnent à peu près la façon dont ils le font dans le monde de hachage-URL. En fait, c'est la façon la moins codée de faire. Mais il est également qualifié de "briser l'internet", qui c'est pourquoi HTML5 et L'API History vous donnent un lien vers les URLs sémantiquement correctes .

comme petit exemple, si vous allez à https://github.com/kriskowal/q et vous cliquez sur "exemples", le code côté client chargera la direcory" exemples "dans le navigateur de fichier sans quitter la page, et la barre D'URL se lira https://github.com/kriskowal/q/tree/master/examples . Si vous allez à https://github.com/kriskowal/q/tree/master/examples directement, vous obtenez le contenu du répertoire" examples " envoyé directement à votre navigateur, sans intermédiaire de code côté client. Oui, c'est plus difficile à faire, et peut-être impossible dans une "application d'une seule page", mais c'est la bonne chose à faire chaque fois que c'est possible.

-3
répondu hobbs 2013-07-15 23:55:27