Le routeur Angular 2.0 ne fonctionne pas pour recharger le navigateur

190

J'utilise la version Angular 2.0.0-alpha.30. Lors de la redirection vers une route différente, actualisez le navigateur, son affichage Cannot GET / route.

Pouvez-vous m'aider à comprendre pourquoi cette erreur s'est produite.

Vinz et Tonz
la source
1
Je suppose que c'est stackoverflow.com/questions/16569841
Günter Zöchbauer
Merci pour la réponse mais celle-ci concerne les versions angulaires 1.x. Je suis confronté au problème angulaire 2.0.
Vinz and Tonz le
1
La question liée est un problème général avec pushState non spécifique à Angular. Votre question ne fournit pas suffisamment d'informations pour savoir si elle est liée.
Günter Zöchbauer
5
Angular 2.0 utilise un tout nouveau routeur, donc le message lié n'est plus d'aucune utilité maintenant puisque c'est l'ancien routeur
Vinz et Tonz
Comme je l'ai dit, s'il s'agit du problème pushState, il n'est pas spécifique à Angular et ne peut pas être résolu par Angular mais doit être résolu sur le serveur à la place.
Günter Zöchbauer

Réponses:

141

L'erreur que vous voyez est que vous demandez http: // localhost / route qui n'existe pas. Selon Simon .

Lorsque vous utilisez le routage html5, vous devez mapper toutes les routes de votre application (actuellement 404) à index.html côté serveur. Voici quelques options pour vous:

  1. en utilisant live-server: https://www.npmjs.com/package/live-server

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

    error_page 404 /index.html
    
  3. Tomcat - configuration de web.xml. D'après le commentaire de Kunin

    <error-page>
          <error-code>404</error-code>
          <location>/index.html</location>
    </error-page>
    
Quy Tang
la source
1
Comme on a besoin d'un support côté serveur pour le routage html5, cela fonctionne parfaitement bien. Thanx
Prabhat
Puis-je utiliser nginx comme proxy pour pub serve? De cette façon, je n'ai pas besoin de pub buildbeaucoup pendant le développement. J'ai essayé mais proxy_passne fonctionne pas très bien avec error_page.
Franklin Yu
@FranklinYu Je ne l'ai jamais fait auparavant. Le résolvez-vous?
Quy Tang
1
Utilisation de nginx. , error_page 404 /index.html à l'emplacement de l'application a fonctionné pour moi. Je vous remercie.
Richard K. Campion
2
Tomcat - configuration de web.xml <error-page> <error-code> 404 </error-code> <location> /index.html </location> </error-page>
A Kunin
65

Avertissement: ce correctif fonctionne avec Alpha44

J'ai eu le même problème et je l'ai résolu en implémentant la stratégie HashLocationStrategy répertoriée dans l'aperçu de l'API Angular.io.

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

Commencez par importer les directives nécessaires

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

Et enfin, bootstrap tout ensemble comme ça

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

Votre itinéraire apparaîtra comme http: // localhost / # / route et lorsque vous actualiserez, il se rechargera à son bon endroit.

J'espère que cela pourra aider!

SimonHawesome
la source
1
ce code fonctionnera bien mais il y a un problème dans cette technique en utilisant ceci #sera ajouté automatiquement dans l'URL. existe-t-il une solution pour supprimer # de l'URL en utilisant ceci?
Pardeep Jain
D'accord, j'ai essayé d'implémenter le "PathLocationStrategy" répertorié ici , mais je n'ai pas pu le faire fonctionner. Une URL sans le #serait optimal.
SimonHawesome
Oui moi aussi j'ai essayé la même chose avec le PathLocationStrategymais cela ne fonctionne pas pour moi. soit j'ai utilisé une mauvaise méthode, soit je ne sais pas comment utiliser PathLocationStrategy.
Pardeep Jain
1
Cela ne fonctionne pas pour moi dans RC1. L'importation de LocationStrategy, HashLocationStrategy à partir de '@ angular / router' échoue.
infojolt
1
Désolé de revenir sur ces questions après plus d'un an :) Mais HashLocationStrategy aide-t-il à rester sur le même chemin de routeur? Dans mon cas, lorsque je rafraîchis, cela m'amène à localhost / # / <default route> c'est à dire la route par défaut pour la page d'accueil. Comment puis-je accéder à l'itinéraire actuel sur lequel j'étais à l'origine lorsque j'ai «actualisé»?
rajugaadu
47

Angular par défaut utilise le pushstate HTML5 ( PathLocationStrategyen argot angulaire).
Soit vous avez besoin d'un serveur qui traite toutes les demandes comme il le demandait, index.htmlsoit vous passez à HashLocationStrategy(avec # dans l'URL des routes) https://angular.io/docs/ts/latest/api/common/index/HashLocationStrategy-class. html

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

Pour passer à HashLocationStrategyutiliser

mise à jour pour> = RC.5 et 2.0.0 final

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

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

ou plus court avec useHash

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

assurez-vous d'avoir toutes les importations requises

Pour le nouveau routeur (RC.3)

<base href="."> 

peut également causer 404.

Il nécessite à la place

<base href="/">

mise à jour pour> = 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';  

mise à jour pour> = beta.16 Les importations ont changé

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';

Voir aussi https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta16-2016-04-26 rupture-changements

Günter Zöchbauer
la source
1
Merci! provide semble s'être déplacé sous angular / core: import {provide} de 'angular2 / core'
StrangeLoop
1
Juste à noter: update for >= RC.x(RC.2) fonctionne avec router 3.0.0-alpha.7, mais provideannoté comme obsolète sans informations sur la fonction qui l'a remplacé.
Mrusful
Utilisation{provide: SomeClass, useClass: OtherClass}
Günter Zöchbauer
2
Réponse la plus à jour. Pour la dernière version d'angular 2.4.1 j'avais <base href = "./">. Changé en <base href = "/"> a résolu le problème que j'avais. Cela pourrait être utile pour quelqu'un.
Saiyaff Farouk
28

Je pense que l'erreur que vous voyez est que vous demandez http: // localhost / route qui n'existe pas. Vous devez vous assurer que votre serveur mappera toutes les demandes sur votre page principale index.html.

Comme Angular 2 utilise le routage html5 par défaut plutôt que d'utiliser des hachages à la fin de l'url, l'actualisation de la page ressemble à une demande d'une ressource différente.

Simon
la source
7
alors comment pouvons-nous résoudre ce problème? comment mapper toutes les demandes à l'index principal par défaut? dépend-il du serveur?
Ayyash
1
Oui, vous le feriez sur le serveur avec le framework Web que vous utilisez. L'alternative consiste à utiliser la stratégie HashLocationStrategy comme décrit ci-dessous.
Simon
Vous rechargerez le SPA angulaire dans chaque itinéraire non présent. Est-ce ainsi que cela devrait être géré?
Gary
Il ne se recharge que si l'utilisateur clique sur Actualiser dans le navigateur, pas lorsque l'utilisateur change d'itinéraires via l'interface utilisateur. Pas vraiment de moyen de contourner un rechargement lorsque l'utilisateur se rafraîchit.
Wallace Howery
19

Il s'agit d'une situation courante dans toutes les versions de routeur si vous utilisez la stratégie de localisation HTML par défaut.

Ce qui se passe, c'est que l'URL de la barre du navigateur est une URL HTML complète normale, comme par exemple: http://localhost/route .

Ainsi, lorsque nous appuyons sur Entrée dans la barre du navigateur, une requête HTTP réelle est envoyée au serveur pour obtenir un fichier nommé route .

Le serveur n'a pas un tel fichier, et ni quelque chose comme express n'est configuré sur le serveur pour gérer la demande et fournir une réponse, de sorte que le serveur renvoie 404 Not Found, car il n'a pas pu trouver le route fichier.

Ce que nous souhaitons, c'est que le serveur renvoie le index.htmlfichier contenant l'application monopage. Ensuite, le routeur doit démarrer et traiter le/route URL et afficher le composant mappé dessus.

Donc, pour résoudre le problème, nous devons configurer le serveur pour qu'il retourne index.html (en supposant qu'il s'agit du nom de votre fichier d'application d'une seule page) au cas où la demande ne pourrait pas être traitée, par opposition à un 404 Not Found.

La manière de procéder dépendra de la technologie côté serveur utilisée. Si c'est Java par exemple, vous devrez peut-être écrire un servlet, dans Rails ce sera différent, etc.

Pour donner un exemple concret, si par exemple vous utilisez NodeJs, vous devrez écrire un middleware comme celui-ci:

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

Et puis enregistrez-le à la toute fin de la chaîne middleware:

app.use(sendSpaFileIfUnmatched);

Cela servira index.html au lieu de renvoyer un 404, le routeur démarrera et tout fonctionnera comme prévu.

Université angulaire
la source
C'était exactement mon problème. Si vous utilisez NGINX, cette réponse aide à le résoudre: stackoverflow.com/questions/7027636/…
Nathan
Existe-t-il un tutoriel sur la façon de faire cela pour Java? Merci.
000000000000000000000
13

Assurez-vous qu'il est placé dans l'élément head de votre index.html:

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

L' exemple de la documentation Angular2 Routing & Navigation utilise le code suivant dans l'en-tête à la place (ils expliquent pourquoi dans l'exemple en direct de la documentation):

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

Lorsque vous actualisez une page, cela définit dynamiquement le href de base sur votre document.location actuel. Je pouvais voir cela causer une certaine confusion pour les gens qui parcouraient la documentation et essayaient de reproduire le plunker.

user2263572
la source
Merci d'avoir partagé ça. Soyons clairs, cela n'a fonctionné pour moi que lorsque j'ai mis <base href = "/"> directement après avoir chargé tous les css dans le <head>, et avant de charger TOUT fichier Js. J'espère que cela aide n'importe qui
wmehanna
J'ai <base href = "./"> dans index.html puis supprimé '.' de la href et cela a fonctionné ..
Saurabh Solanki
10

Si vous souhaitez pouvoir entrer des URL dans le navigateur sans configurer votre serveur AppServer pour gérer toutes les demandes à index.html, vous devez utiliser HashLocationStrategy .

Le moyen le plus simple de configurer est d'utiliser:

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

Au lieu de:

RouterModule.forRoot(routes)

Avec HashLocationStrategy, vos URL seront comme:

http://server:port/#/path
Felipecrp
la source
Merci! cela aide, mais je ne veux pas #de l'URL, pouvons-nous supprimer cela?
Hidayt Rahman
7

J'ai eu le même problème avec l'utilisation de webpack-dev-server. J'ai dû ajouter l'option devServer à mon pack Web.

Solution:

// in webpack
devServer: {
    historyApiFallback: true,
    stats: 'minimal'
}
angmerique
la source
Sorte de magie vaudou: p Pour plus d'informations, voir: webpack.github.io/docs
...
7

Si vous utilisez Apache ou Nginx en tant que serveur, vous devez créer un .htaccessmoteur de réécriture (s'il n'a pas été créé auparavant) et "On"

RewriteEngine On  
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html
Rakesh Roy
la source
Vous n'avez pas obtenu votre question, cette méthode testée sur les serveurs Apache et Nginx ( nginx.com )
Rakesh Roy
1
Ceci est uniquement pour Apache; Le format de configuration Nginx est totalement différent.
Franklin Yu
5

Mon serveur est Apache, ce que j'ai fait pour réparer 404 lors de l'actualisation ou de la liaison profonde est très simple. Ajoutez simplement une ligne dans la configuration apache vhost:

ErrorDocument 404 /index.html

Ainsi, toute erreur 404 sera redirigée vers index.html, ce que veut le routage angular2.

L'exemple de fichier vhost complet:

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

Quel que soit le serveur que vous utilisez, je pense que tout l'intérêt est de trouver les moyens de configurer le serveur pour qu'il redirige 404 vers votre index.html.

Willie Z
la source
4

La configuration du serveur n'est pas une solution pour un SPA, c'est ce que même je pense. Vous ne voulez pas recharger à nouveau un SPA angulaire si un mauvais itinéraire arrive, n'est-ce pas? Je ne vais donc pas dépendre d'une route de serveur et rediriger vers une autre route, mais oui, je laisserai index.html gérer toutes les demandes de routes angulaires du chemin angulaire de l'application.

Essayez ceci au lieu d'itinéraires différents ou erronés. Cela fonctionne pour moi, pas sûr mais cela semble être un travail en cours. J'ai trébuché moi-même face à un problème.

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

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

Cependant, n'oubliez pas de configurer vos dossiers de serveur et vos droits d'accès au cas où vous auriez des scripts HTML ou Web qui ne sont pas SPA. Sinon, vous rencontrerez des problèmes. Pour moi, face à un problème comme vous, c'était un mélange de configuration de serveur et plus.

Gary
la source
4

pour une solution rapide angulaire 5, éditez app.module.ts et ajoutez {useHash:true}après les appRoutes.

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

Les applications angulaires sont des candidats parfaits pour servir avec un simple serveur HTML statique. Vous n'avez pas besoin d'un moteur côté serveur pour composer dynamiquement les pages d'application, car Angular le fait du côté client.

Si l'application utilise le routeur Angular, vous devez configurer le serveur pour renvoyer la page hôte de l'application (index.html) lorsqu'on vous demande un fichier qu'il ne possède pas.

Une application routée doit prendre en charge les "liens profonds". Un lien profond est une URL qui spécifie un chemin vers un composant dans l'application. Par exemple, http://www.example.com/heroes/42 est un lien profond vers la page de détails du héros qui affiche le héros avec l'ID: 42.

Il n'y a aucun problème lorsque l'utilisateur accède à cette URL à partir d'un client en cours d'exécution. Le routeur angulaire interprète l'URL et les achemine vers cette page et ce héros.

Mais en cliquant sur un lien dans un e-mail, en le saisissant dans la barre d'adresse du navigateur ou en actualisant simplement le navigateur sur la page de détails du héros, toutes ces actions sont gérées par le navigateur lui-même, en dehors de l'application en cours d'exécution. Le navigateur fait une demande directe au serveur pour cette URL, en contournant le routeur.

Un serveur statique renvoie systématiquement index.html lorsqu'il reçoit une requête pour http://www.example.com/ . Mais il rejette http://www.example.com/heroes/42 et renvoie une erreur 404 - Not Found sauf s'il est configuré pour renvoyer index.html à la place

Si ce problème s'est produit en production, suivez les étapes ci-dessous

1) Ajoutez un fichier Web.Config dans le dossier src de votre application angular. Placez-y le code ci-dessous.

<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) Ajoutez-y une référence dans angular-cli.json. Dans angular-cli.json, placez Web.config dans le bloc assets comme indiqué ci-dessous.

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

3) Vous pouvez maintenant créer la solution pour la production en utilisant

ng build --prod

Cela créera un dossier dist. Les fichiers dans le dossier dist sont prêts à être déployés dans n'importe quel mode.

Malatesh Patil
la source
La meilleure solution, peut trouver les détails de angular: angular.io/guide/deployment#fallback Lors de la création du fichier web.config, n'oubliez pas d'ajouter la balise <configuration> </configuration>. Merci pour la réponse Malatesh.
Palash Roy
3

Vous pouvez utiliser cette solution pour une application moyenne, j'ai utilisé ejs comme moteur de vue:

// 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');
});

et également défini dans angular-cli.json

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

cela fonctionnera bien au lieu de

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

son problème de création avec les appels get db et le retour de index.html

Shoaib Qureshi
la source
1
Cela a parfaitement fonctionné en octobre 2017 pour l'application MEAN stack.
Équipe Mindsect
2

Pour ceux d'entre nous qui luttent contre IIS: utilisez le code PowerShell suivant pour résoudre ce problème en vous basant sur la documentation officielle Angular 2 (que quelqu'un a publiée dans ce fil de discussion? 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

Cela redirige le 404 vers le fichier /index.html selon la suggestion dans la documentation Angular 2 (lien ci-dessus).

Jim Hume
la source
2

Vous pouvez essayer ci-dessous. Ça marche pour moi!

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() { }
}

Vous pouvez encore améliorer path.substr (2) pour le fractionner en paramètres de routeur. J'utilise angular 2.4.9

Kaifeong
la source
Cela a été vraiment utile pour gérer les actualisations du navigateur! Pour angular 5, j'ai dû le modifier un peu pour utiliser window.location.pathname, et comparer cette valeur aux chemins attendus.
Wallace Howery
2

i Il suffit d'ajouter .htaccess à la racine.

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

ici, j'ajoute simplement le point '.' (répertoire parent) dans /index.html à ./index.html,
assurez-vous que votre fichier index.html dans le chemin de base est le chemin du répertoire principal et défini dans la construction du projet.

hadiya vipul
la source
1

Je voulais conserver le chemin de l'URL des sous-pages en mode HTML5 sans redirection vers l'index et aucune des solutions disponibles ne m'a dit comment faire cela, c'est ainsi que je l'ai accompli:

Créez des répertoires virtuels simples dans IIS pour tous vos itinéraires et faites-les pointer vers la racine de l'application.

Enveloppez votre system.webServer dans votre Web.config.xml avec cette balise d'emplacement, sinon vous obtiendrez des erreurs en double lors du chargement de Web.config une deuxième fois avec le répertoire virtuel:

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

J'ai vérifié dans angular 2 seed comment cela fonctionne.

Vous pouvez utiliser express-history-api-fallback pour rediriger automatiquement lorsqu'une page est rechargée.

Je pense que c'est le moyen le plus élégant de résoudre ce problème IMO.

Lievno
la source
1

Si vous souhaitez utiliser PathLocationStrategy:

  • Configuration Wildfly:
    • Créer le fichier Undertow-handlers.conf à placer dans le WEB-INF
    • Contenu: (excluez vos points de terminaison de repos!)
      • regex ['(. / overview / ?. ? $)'] et non regex ['(. / endpoints. )'] -> réécrire ['/ index.html']
      • regex ['(. / deployments / ?. ? $)'] et non regex ['(. / endpoints. )'] -> rewrite ['/ index.html']

Application monopage avec Java EE / Wildfly: configuration côté serveur

nkeymeulen
la source
1

2017-juillet-11: Puisque ceci est lié à une question ayant ce problème mais utilisant Angular 2 avec Electron, j'ajouterai ma solution ici.

Tout ce que j'avais à faire était de supprimer <base href="./">de mon index.html et Electron a recommencé à recharger la page avec succès.

TimTheEnchanter
la source
1

Ajouter des importations:

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

Et dans le fournisseur NgModule, ajoutez:

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

Dans le fichier principal index.html de l'application, changez le href de base en ./index.htmlde/

L'application lorsqu'elle est déployée sur n'importe quel serveur donnera une URL réelle pour la page accessible depuis n'importe quelle application externe.

Debargho24
la source
1

L'ajout de .htaccess à la racine a résolu 404 tout en actualisant la page 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
la source
1

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 d'une ressource différente.

Lorsque vous utilisez le routage angulaire sur tomcat, vous devez vous assurer que votre serveur mappera toutes les routes de votre application à votre index.html principal tout en actualisant la page. Il existe plusieurs façons de résoudre ce problème. Celui qui vous convient, vous pouvez opter pour cela.

1) Mettez le code ci-dessous dans 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 des routes:

Essayez d'utiliser:

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

Au lieu de:

RouterModule.forRoot (routes)

Avec HashLocationStrategy, vos URL seront comme:

http: // localhost / # / route

3) Valve de réécriture d'URL Tomcat: réécrivez les URL en utilisant une configuration de niveau serveur pour rediriger vers index.html si la ressource n'est pas trouvée.

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

<? 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 utilisé par tomcat pour la réécriture d'URL). À l'intérieur de rewrite.config, copiez le contenu ci-dessous:

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

Ce n'est pas la bonne réponse, mais lors de l'actualisation, vous pouvez rediriger tous les appels morts vers la page d'accueil en sacrifiant la page 404, c'est un hack temporaire, il suffit de relire le fichier 404.html

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

La meilleure solution pour résoudre le "routeur ne fonctionnant pas lors du rechargement du navigateur" est que nous devrions utiliser spa-fall back. Si vous utilisez l'application angular2 avec asp.net core, nous devons la définir sur la page "StartUp.cs". sous les routages MVC. Je joins le code.

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

La réponse est assez délicate. Si vous utilisez un ancien serveur Apache (ou IIS), vous obtenez le problème car les pages angulaires n'existent pas pour de vrai. Ils sont "calculés" à partir de la route angulaire.

Il existe plusieurs façons de résoudre le problème. La première consiste à utiliser la stratégie HashLocationStrategy offerte par Angular. Mais un signe pointu est ajouté dans l'URL. C'est principalement pour la compatibilité avec Angular 1 (je suppose). Le fait est que la partie après le sharp ne fait pas partie de l'URL (alors le serveur résout la partie avant le signe "#"). Cela peut être parfait.

Voici une méthode améliorée (basée sur l'astuce 404). Je suppose que vous avez une version "distribuée" de votre application angulaire ( ng build --prodsi vous utilisez Angular-CLI) et que vous accédez aux pages directement avec votre serveur et que PHP est activé.

Si votre site web est basé sur des pages (Wordpress par exemple) et que vous n'avez qu'un seul dossier dédié à Angular (nommé "dist" dans mon exemple), vous pouvez faire quelque chose de bizarre mais, au final, simple. Je suppose que vous avez stocké vos pages angulaires dans "/ dist" (avec le<BASE HREF="/dist/"> ). Maintenant, utilisez une redirection 404 et l'aide de PHP.

Dans votre configuration Apache (ou dans le .htaccessfichier de votre répertoire d'application angulaire), vous devez ajouterErrorDocument 404 /404.php

Le 404.php commencera par le code suivant:

<?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>"

$angularest la valeur stockée dans le HREF de votre angulaire index.html.

Le principe est assez simple, si Apache ne trouve pas la page, une redirection 404 est faite vers le script PHP. Nous vérifions simplement si la page est à l'intérieur du répertoire d'application angulaire. Si c'est le cas, nous chargeons simplement l'index.html directement (sans redirection): cela est nécessaire pour garder l'URL inchangée. Nous changeons également le code HTTP de 404 à 200 (juste mieux pour les robots d'exploration).

Que faire si la page n'existe pas dans l'application angulaire? Eh bien, nous utilisons le "catch all" du routeur angulaire (voir la documentation du routeur angulaire).

Cette méthode fonctionne avec une application Angular intégrée dans un site Web basique (je pense que ce sera le cas à l'avenir).

REMARQUES:

  • Essayer de faire de même avec le mod_redirect (en réécrivant les URL) n'est pas du tout une bonne solution car les fichiers (comme les actifs) doivent être vraiment chargés, alors c'est beaucoup plus risqué que d'utiliser simplement la solution "non trouvé".
  • La redirection en utilisant ErrorDocument 404 /dist/index.htmlfonctionne mais Apache répond toujours avec un code d'erreur 404 (ce qui est mauvais pour les robots d'exploration).
William R
la source
0

Ce n'est pas une solution permanente au problème, mais plutôt une solution de contournement ou un hack

J'ai eu ce même problème lors du déploiement de mon application angulaire sur gh-pages. J'ai d'abord été accueilli avec 404 messages lors de l'actualisation de mes pages sur gh-pages.

Puis, comme l'a souligné @gunter, j'ai commencé à utiliser HashLocationStrategy ce qui était fourni avec Angular 2.

Mais cela est venu avec son propre ensemble de problèmes #dans l'URL, c'était vraiment mauvais, ce qui donnait à l'URL l'air bizarre comme çahttps://rahulrsingh09.github.io/AngularConcepts/#/faq .

J'ai commencé à faire des recherches sur ce problème et suis tombé sur un blog. J'ai essayé de lui donner une chance et cela a fonctionné.

Voici ce que j'ai fait comme mentionné dans ce blog.

Vous devrez commencer par ajouter un fichier 404.html à votre référentiel gh-pages qui contient un document HTML vide à l'intérieur - mais votre document doit totaliser plus de 512 octets (expliqué ci-dessous). Ensuite, placez le balisage suivant dans l'élément head de votre page 404.html:

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

Ce code définit l'URL d'entrée tentée sur une variable de l'objet sessionStorage standard et redirige immédiatement vers la page index.html de votre projet à l'aide d'une balise meta refresh. Si vous créez un site d'organisation Github, ne mettez pas de nom de dépôt dans le texte de remplacement d'attribut de contenu, faites simplement ceci: content = "0; URL = '/'"

Afin de capturer et de restaurer l'URL vers laquelle l'utilisateur a navigué initialement, vous devez ajouter la balise de script suivante à la tête de votre page index.html avant que tout autre JavaScript n'agisse sur l'état actuel de la page:

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

Ce bit de JavaScript récupère l'URL que nous avons mise en cache dans sessionStorage sur la page 404.html et remplace l'entrée d'historique actuelle par elle.

Référence backalleycoder Merci à @Daniel pour cette solution de contournement.

Maintenant, l'URL ci-dessus devient https://rahulrsingh09.github.io/AngularConcepts/faq

Rahul Singh
la source
0

J'ai corrigé cela (en utilisant le backend Java / Spring) en ajoutant un gestionnaire qui correspond à tout ce qui est défini dans mes routes angulaires, qui renvoie index.html au lieu d'un 404. Cela (re) amorce alors efficacement l'application et charge la page correcte. J'ai aussi un gestionnaire 404 pour tout ce qui n'est pas pris en compte par cela.

@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
la source
0

Si vous utilisez Apache ou Nginx comme serveur, vous devez créer 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
la source