web-dev-qa-db-fra.com

rafraîchissement des résultats de page en erreur 404 - Angular 6

Je construis une application avec l’aide de Angular6 et je fais face à des problèmes de routage. Tous les itinéraires fonctionnent lorsque je clique sur un onglet particulier mais chaque fois que je rafraîchit la page en cours, il renvoie 404 error. J'ai vu de nombreux articles concernant ce problème sur le débordement de pile, mais je n'ai pas réussi à surmonter ce problème. 

Ci-dessous mon app.module.ts

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {AppComponent} from './app.component';
import {FetchApiComponent} from './fetch-api/fetch-api.component';
import {FormsModule} from '@angular/forms';
import {HttpClientModule} from '@angular/common/http';
import {UserServiceLatest} from './fetch-latest/app.service';
import {UserServiceTop} from './fetch-top/app.service';
import {YoutubePlayerModule} from 'ngx-youtube-player';
import {SidebarComponent} from './sidebar/sidebar.component';
import {FetchLatestComponent} from './fetch-latest/fetch-latest.component';
import { FetchTopComponent } from './fetch-top/fetch-top.component'
import {UserService} from './fetch-api/app.service';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { AngularFireModule } from 'angularfire2';
import * as firebase from 'firebase';
import { firebaseConfig } from './../environments/firebase.config';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import {PushService} from './Push.service';

const appRoutes: Routes = [
  {
    path: '',

  component: FetchApiComponent
  }, 
{
    path: '/latest',

    component: FetchLatestComponent
  },
{
    path: '/top',

    component: FetchTopComponent
  },
{
path :'*',
component: FetchApiComponent 
}

];

firebase.initializeApp(firebaseConfig);

@NgModule({
  declarations: [
    AppComponent,
    FetchApiComponent,SidebarComponent, FetchLatestComponent, FetchTopComponent
  ],
  imports: [
    RouterModule.forRoot(appRoutes),
    BrowserModule, YoutubePlayerModule,
    FormsModule,
    AngularFireModule.initializeApp(firebaseConfig),
    AngularFireDatabaseModule,environment.production ?ServiceWorkerModule.register('firebase-messaging-sw.js'):[],ServiceWorkerModule.register('/firebase-messaging-sw.js', { enabled: environment.production }),
    HttpClientModule,environment.production ? ServiceWorkerModule.register('ngsw-worker.js') : [], ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production })
  ],
  providers: [UserService,UserServiceTop,UserServiceLatest,PushService],

  bootstrap: [AppComponent]
})
export class AppModule {}

Pouvez-vous me diriger dans la bonne direction?

7
N Sharma

Vous verrez dans votre exemple d'URL qu'une fois l'erreur 404 générée, vous ne pourrez plus le faire fonctionner, mais si vous incluez un hachage avant l'URL spécifique à l'angulaire telle que /#latest, elle fonctionnera.

Pourquoi arrête de travailler quand rafraîchissant? votre webserver intercepte la demande GET de votre navigateur et tente d'accéder directement au répertoire /latest, qui n'existe pas. Il ne sait pas qu'il doit aller à /bosv2, rechercher une application angulaire, puis ajouter le petit bit de fin à votre chemin, qui est un répertoire non réel mais un routage pour angulaire. Dans votre section locale, cela fonctionnerait comme si vous serviez, le serveur Web Webpack est préparé pour cela, mais pas l’hôte où vous hébergez l’application.

Par défaut, angular utilise la navigation dans le style HTML5, mais avec les paramètres actuels de votre serveur Web, vous aurez besoin de l'ancien style angularjs (avec hash #).

De là, vous avez deux solutions:

  1. Changer la configuration de votre serveur web
  2. Indiquez à Angular d'utiliser HashLocationStrategy (solution parfaitement valide), vous pouvez passer à l'ancienne avec HashLocationStrategy en fournissant le useHash: true dans un objet en tant que deuxième argument de RouterModule.forRoot dans AppModule.

    @NgModule ({ Importations: [ ... RouterModule.forRoot (routes, {useHash: true}) // .../#/latest /], . ..

Je dirais que le style de hachage a quelques inconvénients, ce qui peut ne pas être pertinent dans votre scénario:

  1. Il ne produit pas les URL propres et conviviales pour le référencement, qui sont plus faciles à comprendre et à mémoriser pour les utilisateurs.
  2. Vous ne pouvez pas tirer parti du rendu côté serveur.

J'espère que vous trouverez cette réponse utile :)

9
Javier Aviles

Avec .htaccess, vous pouvez aussi essayer de la manière suivante:

<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>
6
bharat

Pour éviter d'utiliser des routes hachées, vous devez modifier correctement la configuration de votre serveur Web, ce qui est la meilleure solution. Vous devez juste le configurer pour qu'il se replie sur index.html, qui est le bootstrap d'Angular. Bien qu'il n'y ait pas de configuration universelle pour cela, en voici quelques unes:

Apache

Ajouter une règle de réécriture au fichier .htaccess

RewriteEngine On
    # If an existing asset or directory is requested go to it as it is
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
    RewriteRule ^ - [L]
    # If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html

Nginx

Utilisez try_files dans votre bloc de localisation

try_files $uri $uri/ /index.html;

IIS

Ajouter une règle de réécriture à web.config

<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="/index.html" />
      </rule>
    </rules>
  </rewrite>
</system.webServer>

Source: https://angular.io/guide/deployment#server-configuration

2
GTX

Je pense que vous obtenez 404 parce que vous demandez http: // localhost/route qui n’existe pas sur le serveur Tomcat. Comme Angular 2 utilise le routage html 5 par défaut plutôt que d'utiliser des hachages à la fin de l'URL, l'actualisation de la page ressemble à une demande pour une ressource différente.

Lorsque vous utilisez le routage angulaire sur Tomcat, vous devez vous assurer que votre serveur mappera tous les itinéraires de votre application sur votre index.html principal lors de l'actualisation de la page. Il existe plusieurs façons de résoudre ce problème. Quel que soit le choix qui vous convient, vous pouvez y aller.

1) Placez le code ci-dessous dans le fichier web.xml de votre dossier de déploiement:

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

2) Vous pouvez également essayer d'utiliser HashLocationStrategy avec # dans l'URL pour les itinéraires:

Essayez d'utiliser:

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

Au lieu de:

RouterModule.forRoot (routes)

Avec HashLocationStrategy, vos URLs seront comme:

http: // localhost/#/route

3) Valve de réécriture d'URL Tomcat: réécrivez l'URL à l'aide d'une configuration au niveau du serveur pour la rediriger vers index.html si la ressource est introuvable.

3.1) Dans le dossier META-INF, créez un fichier context.xml et copiez le contexte ci-dessous.

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

3.2) Dans WEB-INF, créez le fichier rewrite.config (ce fichier contient la règle de réécriture d'URL et est utilisé par Tomcat pour la réécriture d'URL). Dans rewrite.config, copiez le contenu ci-dessous:

RewriteCond% {SERVLET_PATH}! -F

RewriteRule ^/(. *) $ /Index.html [L]

1
karan khanna

Dans app.module.ts

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

Après l'importation, ajoutez la ligne suivante aux fournisseurs.

{provide: LocationStrategy, useClass: HashLocationStrategy}

ex: 

providers: [AuthService, 
            AuthGuard, 
            FlxUiDataTable,
            {provide: LocationStrategy, useClass: HashLocationStrategy}]

Cela résoudra votre problème. Lire Documentation ici.