Modo HTML5 AngularJS: ¿Cómo funcionan los enlaces directos sin cambios específicos del servidor?

Nota: esta pregunta también podría leer:

Cómo admitir marcadores de marcos mvc del lado del cliente sin hashbang en Java.

Estoy html5mode transición de una aplicación angular que usa hashtags a una que es html5mode . He establecido con éxito

 $locationProvider.html5Mode(true); 

Y todos los enlaces de la página de destino (index.html) funcionan bien.

El problema es que, si se hace referencia directa a las URL parciales, obtengo un 404, naturalmente, ya que las definiciones del punto final del servidor no están acopladas a las rutas definidas por el lado del cliente.

Entonces, sin HTML5 obtenemos hashbangs que no son SEO, pero con él no podemos marcar nada más que la página de destino (la página que carga angular).

Por qué funciona si primero se solicita la página de destino predeterminada (index.html), es decir, htpp: //mydomain.com/:

  1. El navegador solicita index.html desde el servidor
  2. El servidor devuelve index.html y el navegador carga el marco angular
  3. Los cambios de URL se envían al enrutador del lado del cliente y se cargan los parciales adecuados.

Por qué no funciona si (es decir) http://mydomain.com/foo se solicita directamente desde el navegador:

  1. El navegador solicita mydomain / foo del servidor.
  2. El recurso no existe
  3. El servidor devuelve 404

Algo falta en esta historia, simplemente no sé qué. Estas son las únicas dos respuestas que puedo ver …

  • Es por diseño. ¿Es así como se supone que debe funcionar? Los usuarios siempre deben aterrizar en la página de arranque del framework MVC del cliente (generalmente index.html), y luego navegar desde allí. Esto no es ideal porque el estado no se puede guardar y no hay forma de marcar … sin mencionar el rastreo.
  • Solución de servidor ¿Esto funciona con un truco del lado del servidor? Por ejemplo, en todas las solicitudes, devuelva index.html e inmediatamente llame al enrutador con contexto adicional. Si es así, esto va en contra del objective de que AngularJS esté completamente al lado del cliente y parezca un truco.

La documentación de AngularJS de hecho menciona esto

Lado del servidor El uso de este modo requiere la reescritura de URL en el lado del servidor, básicamente tiene que volver a escribir todos sus enlaces al punto de entrada de su aplicación (por ejemplo, index.html)

En este caso, una solución basada en Java es decirle al servidor “asignar todas las URL a index.html”. Esto se puede hacer en cualquier servidor HTTP o contenedor. Implementé esto usando Java / Servet ya que quiero que mi aplicación sea independiente del servidor HTTP (es decir, Apache versus NginX, o Tomcat / JBoss solamente).

En web.xml:

   index.jsp   StaticServlet /index.jsp   StaticServlet /app  

Y index.jsp simplemente se ve así:

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

Y agregue lo siguiente a la etiqueta dentro de index.html:

  

Pasé un tiempo pensando en esto para mi sitio PHP. Colgué todo el código del lado del servidor fuera de la ruta / api para mantenerlo separado de Angular. Aquí está la solución que se me ocurrió al actualizar mi configuración de 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] 

Escribí cómo hice esto usando el framework Flight PHP en http://www.awnage.com/2013/10/10/taking-flight-with-angularjs/

Las URL a las que se vincula y que se ubican en la barra de direcciones del usuario deben referirse a contenido válido en el servidor y, de ser posible, deben referirse al contenido correcto . Claro, puede servir la misma página para cada URL, y hacer que el código del cliente se apague y cargue el contenido real, y las cosas funcionan de la misma manera que lo hacen en el mundo de hash-URL. De hecho, ese es el camino menos código para seguir. Pero también califica como “romper el internet”, y es por eso que HTML5 e History API le brindan una forma de vincularse a URL semánticamente correctas .

Como un pequeño ejemplo, si va a https://github.com/kriskowal/q y hace clic en “ejemplos”, el código del lado del cliente cargará el direcory “examples” en el buscador de archivos sin salir de la página, y la barra de URL leerá https://github.com/kriskowal/q/tree/master/examples . Si va directamente a https://github.com/kriskowal/q/tree/master/examples , obtiene el contenido del directorio “examples” enviado directamente a su navegador, sin intermediarios en el código del lado del cliente. Sí, esto es más difícil de hacer, y tal vez imposible en una “aplicación de una sola página”, pero es lo correcto para hacer en cualquier momento que sea posible.