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?
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:
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:
J'espère que vous trouverez cette réponse utile :)
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>
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
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:
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]
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.