El enrutador angular 2.0 no funciona para recargar el navegador

190

Estoy usando la versión Angular 2.0.0-alpha.30. Cuando se redirige a una ruta diferente, luego actualice el navegador, se muestra No se puede OBTENER / ruta.

¿Me pueden ayudar a averiguar por qué ocurrió este error?

Vinz y Tonz
fuente
1
Supongo que es stackoverflow.com/questions/16569841
Günter Zöchbauer
Gracias por la respuesta, pero esa es para las versiones angulares 1.x. Estoy enfrentando el problema en angular 2.0.
Vinz y Tonz
1
La pregunta vinculada es un problema general con pushState no específico angular. Su pregunta no proporciona suficiente información para saber si está relacionada.
Günter Zöchbauer
55
Angular 2.0 utiliza un enrutador completamente nuevo, por lo que la publicación vinculada no sirve ahora ya que es el antiguo enrutador
Vinz y Tonz
Como dije si es el problema de pushState, no es específico de Angular y Angular no puede solucionarlo, sino que debe solucionarse en el servidor.
Günter Zöchbauer

Respuestas:

141

El error que está viendo es porque está solicitando http: // localhost / route que no existe. De acuerdo a Simon .

Al usar el enrutamiento html5, debe asignar todas las rutas en su aplicación (actualmente 404) a index.html en el lado del servidor. Aquí hay algunas opciones para usted:

  1. usando el servidor en vivo: https://www.npmjs.com/package/live-server

    $live-server --entry-file=index.html`
    
  2. usando nginx: http://nginx.org/en/docs/beginners_guide.html

    error_page 404 /index.html
    
  3. Tomcat: configuración de web.xml. Del comentario de Kunin

    <error-page>
          <error-code>404</error-code>
          <location>/index.html</location>
    </error-page>
    
Quy Tang
fuente
1
Como se necesita soporte del servidor para el enrutamiento html5, esto funciona perfectamente bien. Gracias
Prabhat
¿Puedo usar nginx como proxy para pub serve? De esa manera no necesito pub buildmucho durante el desarrollo. Lo intenté pero proxy_passno funciona muy bien error_page.
Franklin Yu
@FranklinYu No lo he hecho antes. ¿Lo resuelves?
Quy Tang
1
Usando nginx. , error_page 404 /index.html en la ubicación de la aplicación funcionó para mí. Gracias.
Richard K. Campion
2
Tomcat - configuración de web.xml <error-page> <error-code> 404 </error-code> <location> /index.html </location> </error-page>
A Kunin
65

Descargo de responsabilidad: esta solución funciona con Alpha44

Tuve el mismo problema y lo resolví implementando la HashLocationStrategy enumerada en la Vista previa de la API Angular.io.

https://angular.io/docs/ts/latest/api/common/index/HashLocationStrategy-class.html

Comience importando las directivas necesarias

import {provide} from 'angular2/angular2';
import {
  ROUTER_PROVIDERS,
  LocationStrategy,
  HashLocationStrategy
} from 'angular2/router';

Y finalmente, ponlo todo junto así

bootstrap(AppCmp, [
  ROUTER_PROVIDERS,
  provide(LocationStrategy, {useClass: HashLocationStrategy})
]);

Su ruta aparecerá como http: // localhost / # / route y cuando actualice, se volverá a cargar en el lugar adecuado.

¡Espero que ayude!

SimonHawesome
fuente
1
este código funcionará bien, pero hay algún problema en esta técnica al usar esto #se agregará automáticamente en la URL. ¿Hay alguna solución para eliminar # de la URL usando esto?
Pardeep Jain
De acuerdo, intenté implementar la "PathLocationStrategy" enumerada aquí , pero no pude hacer que funcionara. Una URL sin la #sería óptima.
SimonHawesome
Sí, yo también intenté lo mismo con el PathLocationStrategypero esto no funciona para mí. o usé un método incorrecto o no sé cómo usar PathLocationStrategy.
Pardeep Jain
1
Esto no funciona para mí en RC1. Importar LocationStrategy, HashLocationStrategy de '@ angular / router' falla.
infojolt
1
Perdón por volver a estas preguntas después de más de 1 año :) ¿Pero HashLocationStrategy ayuda a permanecer en el mismo camino del enrutador? En mi caso, cuando actualizo me lleva a localhost / # / < ruta predeterminada > es decir, la ruta predeterminada para la página de inicio. ¿Cómo voy a la ruta actual en la que estaba originalmente cuando 'Actualicé'?
rajugaadu
47

Angular por defecto usa HTML5 pushstate ( PathLocationStrategyen argot angular).
Necesita un servidor que procese todas las solicitudes como si estuviera solicitando index.htmlo cambie a HashLocationStrategy(con # en la URL para rutas) https://angular.io/docs/ts/latest/api/common/index/HashLocationStrategy-class. html

Ver también https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/

Para cambiar a HashLocationStrategyusar

actualización para> = RC.5 y 2.0.0 final

import {HashLocationStrategy, LocationStrategy} from '@angular/common';

@NgModule({
  declarations: [AppCmp], 
  bootstrap: [AppCmp],
  imports: [BrowserModule, routes],
  providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]
]);

o más corto con useHash

imports: [RouterModule.forRoot(ROUTER_CONFIG, {useHash: true}), ...

asegúrese de tener todas las importaciones requeridas

Para el nuevo enrutador (RC.3)

<base href="."> 

puede causar 404 también.

Requiere en su lugar

<base href="/">

actualización para> = RC.x

bootstrap(AppCmp, [
  ROUTER_PROVIDERS,
  provide(LocationStrategy, {useClass: HashLocationStrategy})
  // or since RC.2
  {provide: LocationStrategy, useClass: HashLocationStrategy} 
]);

import {provide} from '@angular/core';
import {  
  PlatformLocation,  
  Location,  
  LocationStrategy,  
  HashLocationStrategy,  
  PathLocationStrategy,  
  APP_BASE_HREF}  
from '@angular/common';  

actualización para> = beta.16 Las importaciones han cambiado

import {BrowserPlatformLocation} from '@angular/platform-browser';

import {provide} from 'angular2/core';
import {
  // PlatformLocation,
  // Location,
  LocationStrategy,
  HashLocationStrategy,
  // PathLocationStrategy,
  APP_BASE_HREF}
from 'angular2/router';
import {BrowserPlatformLocation} from 'angular2/src/router/location/browser_platform_location';

<beta.16

import {provide} from 'angular2/core';
import {
  HashLocationStrategy
  LocationStrategy,
  ROUTER_PROVIDERS,
} from 'angular2/router';

Ver también https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta16-2016-04-26 cambios de ruptura

Günter Zöchbauer
fuente
1
¡Gracias! provide parece haberse movido bajo angular / core: import {provide} desde 'angular2 / core'
StrangeLoop
1
Solo para tener en cuenta: update for >= RC.x(RC.2) funciona router 3.0.0-alpha.7, pero se provideanota como obsoleto sin información sobre qué función lo reemplazó.
Mrusful
Uso{provide: SomeClass, useClass: OtherClass}
Günter Zöchbauer
2
La respuesta más actualizada. Para la última versión de angular 2.4.1 tenía <base href = "./">. Cambiado a <base href = "/"> resolvió el problema que tenía. Puede ser útil para alguien.
Saiyaff Farouk
28

Creo que el error que está viendo es porque está solicitando http: // localhost / route que no existe. Debe asegurarse de que su servidor asignará todas las solicitudes a su página index.html principal.

Como Angular 2 usa el enrutamiento html5 de forma predeterminada en lugar de usar hashes al final de la url, actualizar la página parece una solicitud de un recurso diferente.

Simón
fuente
77
Entonces, ¿cómo arreglamos eso? ¿Cómo asignamos todas las solicitudes al índice principal de forma predeterminada? ¿depende del servidor?
Ayyash
1
Sí, haría esto en el servidor con cualquier marco web que esté utilizando. La alternativa es utilizar HashLocationStrategy como se describe a continuación.
Simon
Recargará el SPA angular en cada ruta no presente. ¿Es cómo se debe manejar?
Gary
Solo se recarga si el usuario hace clic en Actualizar en el navegador, no cuando el usuario cambia las rutas a través de la interfaz de usuario. Realmente no hay forma de evitar una recarga cuando el usuario se actualiza.
Wallace Howery
19

Esta es una situación común en todas las versiones de enrutadores si está utilizando la estrategia de ubicación HTML predeterminada.

Lo que pasa es que la URL en la barra del navegador es una URL normal de HTML, como por ejemplo: http://localhost/route.

Entonces, cuando presionamos Enter en la barra del navegador, hay una solicitud HTTP real enviada al servidor para obtener un archivo con el nombre route.

El servidor no tiene dicho archivo, y tampoco hay algo como express configurado en el servidor para manejar la solicitud y proporcionar una respuesta, por lo que el servidor devuelve 404 No encontrado, porque no pudo encontrar el routearchivo.

Lo que nos gustaría es que el servidor devuelva el index.htmlarchivo que contiene la aplicación de página única. Luego, el enrutador debe iniciar y procesar la /routeurl y mostrar el componente asignado a él.

Por lo tanto, para solucionar el problema, debemos configurar el servidor para que regrese index.html(suponiendo que ese sea el nombre del archivo de la aplicación de una sola página) en caso de que la solicitud no se pueda manejar, en lugar de un 404 No encontrado.

La forma de hacerlo dependerá de la tecnología del lado del servidor que se utilice. Si es Java, por ejemplo, es posible que tenga que escribir un servlet, en Rails será diferente, etc.

Para dar un ejemplo concreto, si por ejemplo está usando NodeJs, tendría que escribir un middleware como este:

function sendSpaFileIfUnmatched(req,res) {
    res.sendFile("index.html", { root: '.' });
}

Y luego regístralo al final de la cadena de middleware:

app.use(sendSpaFileIfUnmatched);

Esto servirá en index.htmllugar de devolver un 404, el enrutador se activará y todo funcionará como se esperaba.

Universidad angular
fuente
Este fue exactamente mi problema. Si usa NGINX, esta respuesta ayuda a resolverlo: stackoverflow.com/questions/7027636/…
Nathan
¿Hay un tutorial sobre cómo hacer esto para Java? Gracias.
000000000000000000000
13

Asegúrese de que esto se coloca en el elemento principal de su index.html:

<base href="https://stackoverflow.com/">

El ejemplo en la documentación de enrutamiento y navegación de Angular2 utiliza el siguiente código en el encabezado (explican por qué en la nota de ejemplo en vivo de la documentación):

<script>document.write('<base href="' + document.location + '" />');</script>

Cuando actualice una página, esto establecerá dinámicamente la base href en su ubicación de documento actual. Pude ver que esto causaba cierta confusión a las personas que hojeaban la documentación e intentaban replicar el saqueador.

usuario2263572
fuente
Gracias por compartir esto. Seamos claros, solo funcionó para mí cuando puse <base href = "/"> directamente después de cargar todos los css en el <head>, y antes de cargar CUALQUIER archivo Js. Espero que ayude a nadie
wmehanna
Tengo <base href = "./"> en index.html y luego eliminé '.' del href y funcionó ..
Saurabh Solanki
10

Si desea poder ingresar las URL en el navegador sin configurar su AppServer para manejar todas las solicitudes a index.html, debe usar HashLocationStrategy .

La forma más fácil de configurar es usar:

RouterModule.forRoot(routes, { useHash: true })

En vez de:

RouterModule.forRoot(routes)

Con HashLocationStrategy, tus URL serán como:

http://server:port/#/path
felipecrp
fuente
¡Gracias! esto ayuda, pero no quiero #de url, ¿podemos eliminar esto?
Hidayt Rahman
7

Tuve el mismo problema con el uso de webpack-dev-server. Tuve que agregar la opción devServer a mi paquete web.

Solución:

// in webpack
devServer: {
    historyApiFallback: true,
    stats: 'minimal'
}
angmerica
fuente
Tipo de magia vudú: p Para obtener más información, consulte: webpack.github.io/docs/…
Jissay
7

Si está utilizando Apache o Nginx como servidor, debe crear un .htaccessRewriteEngine (si no se creó antes) y "On"

RewriteEngine On  
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html
Rakesh Roy
fuente
No obtuve su pregunta, este método se probó en el servidor Apache y Nginx ( nginx.com )
Rakesh Roy el
1
Esto es solo para Apache; El formato de configuración de Nginx es totalmente diferente.
Franklin Yu
5

Mi servidor es Apache, lo que hice para arreglar 404 cuando la actualización o la vinculación profunda es muy simple. Simplemente agregue una línea en la configuración de apache vhost:

ErrorDocument 404 /index.html

Para que cualquier error 404 sea redirigido a index.html, que es lo que quiere el enrutamiento angular2.

El ejemplo completo del archivo vhost:

<VirtualHost *:80>
  ServerName fenz.niwa.local
  DirectoryIndex index.html
  ErrorDocument 404 /index.html

  DocumentRoot "/Users/zhoum/Documents/workspace/fire/fire_service/dist"
  ErrorLog /Users/zhoum/Documents/workspace/fire/fire_service/logs/fenz.error.log
  CustomLog /Users/zhoum/Documents/workspace/fire/fire_service/logs/fenz.access.log combined

  <Directory "/Users/zhoum/Documents/workspace/fire/fire_service/dist">
    AllowOverride All
    Options Indexes FollowSymLinks
    #Order allow,deny
    #Allow from All
    Require all granted
  </Directory>

  Header set Access-Control-Allow-Origin "*"
  Header set Access-Control-Allow-Methods "GET, POST"
  Header set Access-Control-Allow-Credentials "true"
  Header set Access-Control-Allow-Headers "Accept-Encoding"
</VirtualHost>

No importa qué servidor esté utilizando, creo que el punto es descubrir las formas de configurar el servidor para redirigir 404 a su index.html.

Willie Z
fuente
4

La configuración del servidor no es una solución para un SPA, es lo que incluso yo pienso. No desea volver a cargar un SPA angular si entra una ruta incorrecta, ¿verdad? Por lo tanto, no dependeré de una ruta del servidor y redirigiré a otra ruta, pero sí dejaré que index.html maneje todas las solicitudes de rutas angulares de la ruta angular de la aplicación.

Intente esto en lugar de lo contrario o rutas incorrectas. Funciona para mí, no estoy seguro, pero parece un trabajo en progreso. Me tropecé con esto cuando me enfrento a un problema.

@RouteConfig([
  { path: '/**', redirectTo: ['MycmpnameCmp'] }, 
   ...
  }
])

https://github.com/angular/angular/issues/4055

Sin embargo, recuerde configurar las carpetas de su servidor y acceder directamente en caso de que tenga HTML o scripts web que no sean SPA. De lo contrario, enfrentará problemas. Para mí, cuando me enfrento a un problema como tú, era una combinación de configuración de servidor y superior.

Gary
fuente
4

para la solución rápida angular 5, edite app.module.ts y agregue {useHash:true}después de appRoutes.

@NgModule(
{
  imports:[RouterModule.forRoot(appRoutes,{useHash:true})]
})
Adesh Shah
fuente
3

Las aplicaciones angulares son candidatas perfectas para servir con un servidor HTML estático simple. No necesita un motor del lado del servidor para componer dinámicamente las páginas de la aplicación porque Angular lo hace en el lado del cliente.

Si la aplicación usa el enrutador angular, debe configurar el servidor para que devuelva la página de host de la aplicación (index.html) cuando se le solicite un archivo que no tiene.

Una aplicación enrutada debe soportar "enlaces profundos". Un enlace profundo es una URL que especifica una ruta a un componente dentro de la aplicación. Por ejemplo, http://www.example.com/heroes/42 es un enlace profundo a la página de detalles del héroe que muestra al héroe con id: 42.

No hay ningún problema cuando el usuario navega a esa URL desde un cliente en ejecución. El enrutador angular interpreta la URL y las rutas a esa página y héroe.

Pero al hacer clic en un enlace de un correo electrónico, ingresarlo en la barra de direcciones del navegador o simplemente actualizar el navegador mientras está en la página de detalles del héroe: todas estas acciones son manejadas por el navegador, fuera de la aplicación en ejecución. El navegador realiza una solicitud directa al servidor para esa URL, sin pasar por el enrutador.

Un servidor estático devuelve rutinariamente index.html cuando recibe una solicitud de http://www.example.com/ . Pero rechaza http://www.example.com/heroes/42 y devuelve un error 404 - No encontrado a menos que esté configurado para devolver index.html en su lugar

Si este problema ocurrió en la producción, siga los pasos a continuación.

1) Agregue un archivo Web.Config en la carpeta src de su aplicación angular. Coloque debajo del código en él.

<configuration>
<system.webServer>
<rewrite>
    <rules>
    <rule name="Angular Routes" stopProcessing="true">
        <match url=".*" />
        <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        </conditions>
        <action type="Rewrite" url="/" />
    </rule>
    </rules>
</rewrite>
</system.webServer>
</configuration>

2) Agregue una referencia a él en angular-cli.json. En angular-cli.json coloque Web.config en el bloque de activos como se muestra a continuación.

"assets": [
    "assets",
    "favicon.ico",
    "Web.config"
  ],

3) Ahora puede construir la solución para producción usando

ng build --prod

Esto creará una carpeta dist. Los archivos dentro de la carpeta dist están listos para ser implementados por cualquier modo.

Malatesh Patil
fuente
La mejor solución, puede encontrar los detalles de angular: angular.io/guide/deployment#fallback Al crear el archivo web.config, no olvide agregar la etiqueta <configuration> </configuration>. Gracias por la respuesta Malatesh.
Palash Roy el
3

Puede usar esta solución para aplicaciones malas, usé ejs como motor de vista:

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
app.use(function (req, res, next) {
    return res.render('index.html');
});

y también establecido en angular-cli.json

"apps": [
    {
      "root": "src",
      "outDir": "views",

funcionará bien en lugar de

app.get('*', function (req, res, next) {
    res.sendFile('dist/index.html', { root: __dirname });
 });

está creando un problema con obtener llamadas de db y devolver index.html

Shoaib Qureshi
fuente
1
Esto funcionó perfectamente en octubre de 2017 para la aplicación MEAN stack.
Mindsect Team
2

Para aquellos de nosotros que luchamos por la vida en IIS: use el siguiente código de PowerShell para solucionar este problema basado en los documentos oficiales de Angular 2 (que alguien publicó en este hilo) http://blog.angular-university.io/angular2-router/ )

Import-WebAdministration
# Grab the 404 handler and update it to redirect to index.html.
$redirect = Get-WebConfiguration -filter "/system.WebServer/httperrors/error[@statusCode='404']" -PSPath IIS:\Sites\LIS 
$redirect.path = "/index.html"
$redirect.responseMode = 1
# shove the updated config back into IIS
Set-WebConfiguration -filter "/system.WebServer/httperrors/error[@statusCode='404']" -PSPath IIS:\Sites\LIS -value $redirect

Esto redirige el 404 al archivo /index.html según la sugerencia en los documentos de Angular 2 (enlace de arriba).

Jim Hume
fuente
2

Puedes probar a continuación. ¡Esto funciona para mi!

main.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

...
export class MainComponent implements OnInit {
    constructor(private router: Router) {
        let path: string = window.location.hash;
        if (path && path.length > 0) {
            this.router.navigate([path.substr(2)]);
        }
    }

    public ngOnInit() { }
}

Puede mejorar aún más path.substr (2) para dividir en parámetros de enrutador. Estoy usando angular 2.4.9

kaifeong
fuente
¡Esto fue realmente útil para manejar las actualizaciones del navegador! Para angular 5, tuve que modificarlo un poco para usar window.location.pathname, y comparar ese valor con las rutas esperadas.
Wallace Howery
2

Solo agrego .htaccess en la raíz.

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
    RewriteRule ^ - [L]
    RewriteRule ^ ./index.html
</IfModule>

aquí solo agrego el punto '.' (directorio principal) en /index.html a ./index.html,
asegúrese de que su archivo index.html en la ruta base es la ruta del directorio principal y se configura en la compilación del proyecto.

hadiya vipul
fuente
1

Quería preservar la ruta URL de las subpáginas en modo HTML5 sin una redirección al índice y ninguna de las soluciones me dijo cómo hacerlo, así que así es como lo logré:

Cree directorios virtuales simples en IIS para todas sus rutas y apúntelos a la raíz de la aplicación.

Envuelva su system.webServer en su Web.config.xml con esta etiqueta de ubicación, de lo contrario obtendrá errores duplicados al cargar Web.config por segunda vez con el directorio virtual:

<configuration>
    <location path="." inheritInChildApplications="false">
    <system.webServer>
        <defaultDocument enabled="true">
            <files>
                <add value="index.html" />
            </files>
        </defaultDocument>
    </system.webServer>
  </location>
</configuration>
Devin McQueeney
fuente
1

Comprobé en angular 2 seed cómo funciona.

Puedes usar express-history-api-fallback para redirigir automáticamente cuando se recarga una página.

Creo que es la forma más elegante de resolver este problema de la OMI.

Lievno
fuente
1

Si quieres usar PathLocationStrategy:

  • Configuración de Wildfly:
    • Cree el archivo undertow-handlers.conf para colocarlo en WEB-INF
    • Contenido: (¡excluya sus puntos finales de descanso!)
      • regex ['(. / overview / ? . ? $)'] y no regex ['(. / puntos finales. )'] -> reescribir ['/ index.html']
      • regex ['(. / deployments / ? . ? $)'] y no regex ['(. / endpoints. )'] -> reescribir ['/ index.html']

Aplicación de una sola página con Java EE / Wildfly: configuración del lado del servidor

nkeymeulen
fuente
1

2017-julio-11: ya que esto está vinculado a una pregunta que tiene este problema pero que usa Angular 2 con Electron, agregaré mi solución aquí.

Todo lo que tenía que hacer era eliminarlo <base href="./">de mi index.html y Electron comenzó a volver a cargar la página con éxito.

TimTheEnchanter
fuente
1

Agregar importaciones:

import { HashLocationStrategy, LocationStrategy } from '@angular/common';

Y en el proveedor de NgModule, agregue:

providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]

En principal del archivo index.html de la aplicación cambiar el href de base a ./index.htmlpartir de/

La aplicación cuando se implementa en cualquier servidor dará una URL real para la página a la que se puede acceder desde cualquier aplicación externa.

Debargho24
fuente
1

Simplemente agregando .htaccess en la raíz resolvió 404 mientras actualizaba la página en angular 4 apache2.

<IfModule mod_rewrite.c>
    RewriteEngine on

    # Don't rewrite files or directories
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # Rewrite everything else to index.html
    # to allow html5 state links
    RewriteRule ^ index.html [L]
</IfModule>
a_k_v
fuente
1

Creo que está obteniendo 404 porque está solicitando http: // localhost / route que no existe en el servidor tomcat. Como Angular 2 usa el enrutamiento html 5 de forma predeterminada en lugar de usar hashes al final de la URL, actualizar la página parece una solicitud de un recurso diferente.

Cuando utilice el enrutamiento angular en Tomcat, debe asegurarse de que su servidor asignará todas las rutas de su aplicación a su index.html principal mientras actualiza la página. Hay varias formas de resolver este problema. Cualquiera que te convenga, puedes ir por eso.

1) Ponga el siguiente código en web.xml de su carpeta de implementación:

<error-page>
     <error-code>404</error-code>
     <location>/index.html</location>
</error-page>

2) También puede intentar usar HashLocationStrategy con # en la URL de las rutas:

Intenta usar:

RouterModule.forRoot (rutas, {useHash: true})

En vez de:

RouterModule.forRoot (rutas)

Con HashLocationStrategy, tus URL serán como:

http: // localhost / # / route

3) Válvula de reescritura de URL de Tomcat: vuelva a escribir las URL utilizando una configuración de nivel de servidor para redirigir a index.html si no se encuentra el recurso.

3.1) Dentro de la carpeta META-INF, cree un archivo context.xml y copie el siguiente contexto dentro de él.

<? xml version='1.0' encoding='utf-8'?>
<Context>
  <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
</Context>

3.2) Dentro de WEB-INF, cree el archivo rewrite.config (este archivo contiene la regla para la reescritura de URL y lo utiliza tomcat para la reescritura de URL). Dentro de rewrite.config, copie el contenido a continuación:

  RewriteCond %{SERVLET_PATH} !-f
  RewriteRule ^/(.*)$ /index.html [L]
karan khanna
fuente
0

Esta no es la respuesta correcta, pero al actualizar puede redirigir todas las llamadas inactivas a la página de inicio sacrificando la página 404, es un hack temporal que solo se reproduce en el archivo 404.html

<!doctype html>
<html>
    <head>
        <script type="text/javascript">
            window.location.href = "http://" + document.location.host;
        </script>
    </head>
</html>
don625
fuente
0

La mejor solución para resolver el "enrutador que no funciona al recargar el navegador" es que deberíamos usar spa-fall back. Si está utilizando la aplicación angular2 con asp.net core, entonces debemos definirla en la página "StartUp.cs". bajo rutas MVC. Estoy adjuntando el código.

 app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
            routes.MapSpaFallbackRoute("spa-fallback", new { controller = "Home", action = "Index" });
        });
Divyanshu-systematix
fuente
0

La respuesta es bastante complicada. Si usa un servidor Apache antiguo (o IIS), obtendrá el problema porque las páginas angulares no existen de verdad. Se "calculan" a partir de la ruta angular.

Hay varias formas de solucionar el problema. Una es utilizar la estrategia HashLocationStrategy que ofrece Angular. Pero se agrega un signo agudo en la URL. Esto es principalmente por compatibilidad con Angular 1 (supongo). El hecho es que la parte después de que el sostenido no es parte de la URL (entonces el servidor resuelve la parte antes del signo "#"). Eso puede ser perfecto.

Aquí un método mejorado (basado en el truco 404). Supongo que tiene una versión "distribuida" de su aplicación angular ( ng build --prodsi usa Angular-CLI) y accede a las páginas directamente con su servidor y PHP está habilitado.

Si su sitio web está basado en páginas (Wordpress, por ejemplo) y solo tiene una carpeta dedicada a Angular (llamada "dist" en mi ejemplo), puede hacer algo extraño pero, al final, simple. Supongo que ha almacenado sus páginas angulares en "/ dist" (con el correspondiente<BASE HREF="/dist/"> ). Ahora use una redirección 404 y la ayuda de PHP.

En su configuración de Apache (o en el .htaccessarchivo del directorio angular de su aplicación), debe agregarErrorDocument 404 /404.php

El 404.php comenzará con el siguiente código:

<?php
$angular='/dist/';
if( substr($_SERVER['REQUEST_URI'], 0, strlen($angular)) == $angular ){
    $index = $_SERVER['DOCUMENT_ROOT'] . $angular . "index.html";
    http_response_code(200);
    include $index;
    die;
}

// NOT ANGULAR...
echo "<h1>Not found.</h1>"

donde $angulares el valor almacenado en el HREF de su angularindex.html .

El principio es bastante simple, si Apache no encuentra la página, se realiza una redirección 404 al script PHP. Simplemente verificamos si la página está dentro del directorio angular de la aplicación. Si es el caso, simplemente cargamos el index.html directamente (sin redirigir): esto es necesario para mantener la URL sin cambios. También cambiamos el código HTTP de 404 a 200 (simplemente mejor para los rastreadores).

¿Qué pasa si la página no existe en la aplicación angular? Bueno, usamos el "capturar todo" del enrutador angular (consulte la documentación del enrutador angular).

Este método funciona con una aplicación angular integrada dentro de un sitio web básico (creo que será el caso en el futuro).

NOTAS

  • Tratando de hacer lo mismo con el mod_redirect (reescribiendo las URL) no es una buena solución porque los archivos (como los activos) tienen que estar realmente cargados, entonces es mucho más riesgoso que simplemente usar la solución "no encontrada".
  • Simplemente redirecciona usando ErrorDocument 404 /dist/index.htmlWorks, pero Apache todavía responde con un código de error 404 (que es malo para los rastreadores).
William R
fuente
0

Esta no es una solución permanente para el problema, sino más bien una solución o un hack

Tuve este mismo problema al implementar mi aplicación angular en gh-pages. Primero me saludaron con mensajes 404 cuando actualicé mis páginas en gh-pages.

Entonces, como lo señaló @gunter, comencé a usar el HashLocationStrategyque se proporcionó con Angular 2.

Pero eso vino con su propio conjunto de problemas; #en la url, fue realmente malo, hizo que la url se viera tan extraña como esta https://rahulrsingh09.github.io/AngularConcepts/#/faq.

Comencé a investigar sobre este problema y encontré un blog. Intenté darle una oportunidad y funcionó.

Aquí está lo que hice como se menciona en ese blog.

Deberá comenzar agregando un archivo 404.html a su repositorio de gh-pages que contenga un documento HTML vacío en su interior, pero su documento debe sumar más de 512 bytes (explicado a continuación). A continuación, coloque el siguiente marcado en el elemento principal de la página 404.html:

<script>
  sessionStorage.redirect = location.href;
</script>
<meta http-equiv="refresh" content="0;URL='/REPO_NAME_HERE'"></meta>

Este código establece la URL de entrada intentada en una variable en el objeto sessionStorage estándar e inmediatamente redirige a la página index.html de su proyecto utilizando una etiqueta de meta actualización. Si está haciendo un sitio de Organización Github, no ponga un nombre de repositorio en el texto de reemplazo del atributo de contenido, solo haga esto: content = "0; URL = '/'"

Para capturar y restaurar la URL a la que navegó inicialmente el usuario, deberá agregar la siguiente etiqueta de script al encabezado de su página index.html antes de que cualquier otro JavaScript actúe en el estado actual de la página:

<script>
  (function(){
    var redirect = sessionStorage.redirect;
    delete sessionStorage.redirect;
    if (redirect && redirect != location.href) {
      history.replaceState(null, null, redirect);
    }
  })();
</script>

Este bit de JavaScript recupera la URL que almacenamos en caché en sessionStorage en la página 404.html y reemplaza la entrada del historial actual con ella.

Referencia backalleycoder Gracias a @Daniel por esta solución.

Ahora la URL anterior cambia a https://rahulrsingh09.github.io/AngularConcepts/faq

Rahul Singh
fuente
0

Solucioné esto (usando Java / Spring backend) agregando un controlador que coincide con todo lo definido en mis rutas angulares, que devuelve index.html en lugar de un 404. Esto (efectivamente) reinicia la aplicación y carga la página correcta. También tengo un controlador 404 para cualquier cosa que no sea atrapada por esto.

@Controller         ////don't use RestController or it will just send back the string "index.html"
public class Redirect {

    private static final Logger logger = LoggerFactory.getLogger(Redirect.class);

    @RequestMapping(value = {"comma", "sep", "list", "of", "routes"})
    public String redirectToIndex(HttpServletRequest request) {
        logger.warn("Redirect api called for URL {}. Sending index.html back instead. This will happen on a page refresh or reload when the page is on an Angular route", request.getRequestURL());
        return "/index.html";
    }
}
Lee Willis
fuente
0

Si está utilizando Apache o Nginx como servidor, debe crear un .htaccess

<IfModule mime_module>
      AddHandler application/x-httpd-ea-php72 .php .php7 .phtml
    </IfModule>
    # php -- END cPanel-generated handler, do not edit

    <IfModule mod_rewrite.c>
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html
        # to allow html5 state links
        RewriteRule ^ index.html [L]
    </IfModule>
Mukesh Kumar Bijarniya
fuente