Angular 2.0-Router funktioniert nicht beim Neuladen des Browsers


189

Ich verwende die Version Angular 2.0.0-alpha.30. Wenn Sie zu einer anderen Route umleiten, aktualisieren Sie den Browser, und es wird "Kann nicht abgerufen / Route angezeigt" angezeigt.

Können Sie mir helfen, herauszufinden, warum dieser Fehler aufgetreten ist?



Vielen Dank für die Antwort, aber diese ist für eckige 1.x-Versionen. Ich bin mit dem Problem in Winkel 2.0 konfrontiert.
Vinz und Tonz

1
Die verknüpfte Frage ist ein allgemeines Problem mit pushState, das nicht Angular-spezifisch ist. Ihre Frage enthält nicht genügend Informationen, um festzustellen, ob sie verwandt sind.
Günter Zöchbauer

5
Angular 2.0 verwendet einen komplett neuen Router, so dass der verknüpfte Beitrag jetzt keinen Nutzen mehr hat, da er der alte Router ist
Vinz und Tonz

Wie gesagt, wenn es sich um das PushState-Problem handelt, ist es nicht Angular-spezifisch und kann nicht von Angular behoben werden, sondern muss stattdessen auf dem Server behoben werden.
Günter Zöchbauer

Antworten:


141

Der Fehler, den Sie sehen, ist, weil Sie http: // localhost / route anfordern, das nicht existiert. Laut Simon .

Wenn Sie HTML5-Routing verwenden, müssen Sie alle Routen in Ihrer App (derzeit 404) index.html auf Ihrer Serverseite zuordnen . Hier sind einige Optionen für Sie:

  1. Verwenden des Live-Servers: https://www.npmjs.com/package/live-server

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

    error_page 404 /index.html
    
  3. Tomcat - Konfiguration von web.xml. Aus Kunins Kommentar

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

1
Da man serverseitige Unterstützung für das HTML5-Routing benötigt, funktioniert dies einwandfrei. Vielen Dank
Prabhat

Kann ich nginx als Proxy für verwenden pub serve? Auf diese Weise brauche ich pub buildwährend der Entwicklung nicht viel. Ich habe es versucht, aber es proxy_passfunktioniert nicht sehr gut error_page.
Franklin Yu

@FranklinYu Ich habe es noch nie gemacht. Erhalten Sie es gelöst?
Quy Tang

1
Nginx verwenden. , error_page 404 /index.html am Speicherort der App hat bei mir funktioniert. Danke dir.
Richard K. Campion

2
Tomcat - Konfiguration von web.xml <Fehlerseite> <Fehlercode> 404 </ Fehlercode> <Standort> /index.html </ Standort> </ Fehlerseite>
Ein Kunin

65

Haftungsausschluss: Dieses Update funktioniert mit Alpha44

Ich hatte das gleiche Problem und löste es durch Implementierung der HashLocationStrategy, die in der Angular.io-API-Vorschau aufgeführt ist.

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

Beginnen Sie mit dem Importieren der erforderlichen Anweisungen

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

Und zum Schluss booten Sie alles so zusammen

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

Ihre Route wird als http: // localhost / # / route angezeigt. Wenn Sie sie aktualisieren, wird sie an der richtigen Stelle neu geladen.

Hoffentlich hilft das!


1
Dieser Code funktioniert einwandfrei, aber es gibt ein Problem in dieser Technik, #bei dem die URL automatisch hinzugefügt wird. Gibt es eine Lösung, um # mit dieser Option aus der URL zu entfernen?
Pardeep Jain

Einverstanden habe ich versucht, die hier aufgeführte "PathLocationStrategy" zu implementieren , konnte sie jedoch nicht zum Laufen bringen. Eine URL ohne das #wäre optimal.
SimonHawesome

Ja, ich habe es auch mit dem versucht, PathLocationStrategyaber das funktioniert bei mir nicht. Entweder habe ich eine falsche Methode verwendet oder ich weiß nicht, wie ich PathLocationStrategy verwenden soll.
Pardeep Jain

1
Dies funktioniert bei mir in RC1 nicht. Das Importieren von LocationStrategy, HashLocationStrategy aus '@ angle / router' schlägt fehl.
Infojolt

1
Entschuldigen Sie, dass Sie nach mehr als einem Jahr auf diese Fragen zurückgekommen sind :) Aber hilft HashLocationStrategy dabei, auf demselben Router-Pfad zu bleiben? In meinem Fall gehe ich beim Aktualisieren zu localhost / # / <Standardroute >, dh der Standardroute für die Startseite. Wie gehe ich zu der aktuellen Route, auf der ich mich ursprünglich beim Aktualisieren befand?
Rajugaadu

47

Angular verwendet standardmäßig HTML5-Pushstate ( PathLocationStrategyim Angular-Slang).
Sie benötigen entweder einen Server, der alle angeforderten Anforderungen verarbeitet, index.htmloder Sie wechseln zu HashLocationStrategy(mit # in der URL für Routen) https://angular.io/docs/ts/latest/api/common/index/HashLocationStrategy-class. html

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

Um zu HashLocationStrategyverwenden, um zu verwenden

Update für> = RC.5 und 2.0.0 final

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

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

oder kürzer mit useHash

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

Stellen Sie sicher, dass Sie alle erforderlichen Importe haben

Für den neuen (RC.3) Router

<base href="."> 

kann auch 404 verursachen.

Es erfordert stattdessen

<base href="/">

Update für> = 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';  

Update für> = Beta.16 Importe haben sich geändert

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

Siehe auch https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta16-2016-04-26 breaking-Änderungen


1
Vielen Dank! Provide scheint sich unter Angular / Core bewegt zu haben: Import {Provide} von 'Angular2 / Core'
StrangeLoop

1
Nur zur Anmerkung: update for >= RC.x(RC.2) funktioniert mit router 3.0.0-alpha.7, wird jedoch provideals veraltet bezeichnet, ohne dass Informationen darüber vorliegen , welche Funktion es ersetzt hat.
Mrusful

Verwendung{provide: SomeClass, useClass: OtherClass}
Günter Zöchbauer

2
Am meisten aktualisierte Antwort. Für die neueste Version von Angular 2.4.1 hatte ich <base href = "./">. Geändert in <base href = "/"> löste das Problem, das ich hatte. Könnte für jemanden hilfreich sein.
Saiyaff Farouk

28

Ich denke, der Fehler, den Sie sehen, ist, dass Sie http: // localhost / route anfordern, das nicht existiert. Sie müssen sicherstellen, dass Ihr Server alle Anforderungen Ihrer Hauptseite index.html zuordnet.

Da Angular 2 standardmäßig HTML5-Routing verwendet, anstatt Hashes am Ende der URL zu verwenden, sieht das Aktualisieren der Seite wie eine Anforderung für eine andere Ressource aus.


7
Wie können wir das beheben? Wie ordnen wir alle Anforderungen standardmäßig dem Hauptindex zu? ist es serverabhängig?
Ayyash

1
Ja, Sie würden dies auf dem Server mit dem von Ihnen verwendeten Webframework tun. Die Alternative besteht darin, die HashLocationStrategy wie unten beschrieben zu verwenden.
Simon

Sie werden das eckige SPA auf jeder nicht vorhandenen Route neu laden. Ist es so, wie es gehandhabt werden soll?
Gary

Es wird nur neu geladen, wenn der Benutzer im Browser auf Aktualisieren klickt, nicht, wenn der Benutzer die Routen über die Benutzeroberfläche ändert. Nicht wirklich um ein Neuladen herum, wenn der Benutzer aktualisiert.
Wallace Howery

19

Dies ist in allen Router-Versionen häufig der Fall, wenn Sie die Standard-HTML-Standortstrategie verwenden.

Was passiert ist, dass die URL in der Browserleiste eine normale vollständige HTML-URL ist, wie zum Beispiel : http://localhost/route.

Wenn wir also in der Browserleiste die Eingabetaste drücken, wird eine tatsächliche HTTP-Anforderung an den Server gesendet, um eine Datei mit dem Namen zu erhalten route.

Der Server verfügt nicht über eine solche Datei, und auf dem Server ist auch kein Express konfiguriert, um die Anforderung zu verarbeiten und eine Antwort bereitzustellen. Daher gibt der Server 404 Not Found zurück, da die routeDatei nicht gefunden werden konnte .

Wir möchten, dass der Server die index.htmlDatei zurückgibt, die die Einzelseitenanwendung enthält. Dann sollte der Router die /routeURL aktivieren und die ihm zugeordnete Komponente anzeigen.

Um das Problem zu beheben, müssen wir den Server so konfigurieren, dass er zurückgibt index.html(vorausgesetzt, dies ist der Name Ihrer Einzelseiten-Anwendungsdatei), falls die Anforderung nicht verarbeitet werden konnte, im Gegensatz zu einer 404 Not Found.

Die Vorgehensweise hängt von der verwendeten serverseitigen Technologie ab. Wenn es sich beispielsweise um Java handelt, müssen Sie möglicherweise ein Servlet schreiben, in Rails ist es anders usw.

Um ein konkretes Beispiel zu geben: Wenn Sie beispielsweise NodeJs verwenden, müssten Sie eine Middleware wie diese schreiben:

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

Und registrieren Sie es dann ganz am Ende der Middleware-Kette:

app.use(sendSpaFileIfUnmatched);

Dies dient dazu, index.htmlanstatt einen 404 zurückzugeben, der Router wird eingeschaltet und alles wird wie erwartet funktionieren.


Das war genau mein Problem. Wenn Sie NGINX verwenden, hilft diese Antwort bei der Lösung: stackoverflow.com/questions/7027636/…
Nathan

Gibt es ein Tutorial, wie man das für Java macht? Vielen Dank.
000000000000000000000

13

Stellen Sie sicher, dass dies im head-Element Ihrer index.html platziert ist:

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

Das Beispiel in der Angular2 Routing & Navigation- Dokumentation verwendet stattdessen den folgenden Code im Kopf (sie erklären, warum in der Live-Beispielnotiz der Dokumentation):

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

Wenn Sie eine Seite aktualisieren, wird die Basis-HREF dynamisch auf Ihre aktuelle document.location gesetzt. Ich konnte sehen, dass dies einige Verwirrung bei den Leuten hervorrief, die die Dokumentation überflogen und versuchten, den Plunker zu replizieren.


Vielen Dank für das Teilen. Lassen Sie uns einfach klar sein, es hat nur bei mir funktioniert, wenn ich <base href = "/"> direkt nach dem Laden aller CSS in den <head> und vor dem Laden von JY-Dateien eingefügt habe. Ich hoffe, es hilft jedem
wmehanna

Ich habe <base href = "./"> in index.html und dann '.' entfernt. von der href und es hat funktioniert ..
Saurabh Solanki

10

Wenn Sie URLs im Browser eingeben möchten, ohne Ihren AppServer so zu konfigurieren, dass alle Anforderungen an index.html verarbeitet werden, müssen Sie HashLocationStrategy verwenden .

Der einfachste Weg zur Konfiguration ist:

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

Anstatt:

RouterModule.forRoot(routes)

Mit HashLocationStrategy werden Ihre URLs wie folgt aussehen:

http://server:port/#/path

Vielen Dank! das hilft, aber ich will nicht #von der URL, können wir das entfernen?
Hidayt Rahman

7

Ich hatte das gleiche Problem mit der Verwendung von Webpack-Dev-Server. Ich musste die devServer-Option zu meinem Webpack hinzufügen.

Lösung:

// in webpack
devServer: {
    historyApiFallback: true,
    stats: 'minimal'
}

Art von Voodoo-Magie: p Weitere Informationen finden Sie unter: webpack.github.io/docs/…
Jissay

7

Wenn Sie Apache oder Nginx als Server verwenden, müssen Sie eine .htaccessRewriteEngine (falls noch nicht erstellt) und "On" erstellen

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

Ich habe Ihre Frage nicht bekommen, diese Methode wurde auf dem Apache- und Nginx- Server ( nginx.com ) getestet
Rakesh Roy,

1
Dies ist nur für Apache; Das Nginx-Konfigurationsformat ist völlig anders.
Franklin Yu

5

Mein Server ist Apache. Was ich getan habe, um 404 beim Aktualisieren oder Deep Linking zu reparieren, ist sehr einfach. Fügen Sie einfach eine Zeile in apache vhost config hinzu:

ErrorDocument 404 /index.html

Damit jeder 404-Fehler zu index.html umgeleitet wird, was Angular2-Routing wünscht.

Beispiel für die gesamte vhost-Datei:

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

Egal welchen Server Sie verwenden, ich denke, der springende Punkt ist, herauszufinden, wie Sie den Server so konfigurieren können, dass er 404 zu Ihrer index.html umleitet.


4

Die Serverkonfiguration ist keine Lösung für ein SPA, denke sogar ich. Sie möchten ein eckiges SPA nicht erneut laden, wenn eine falsche Route eingeht, oder? Ich werde also nicht von einer Serverroute abhängig sein und zu einer anderen Route umleiten, aber ja, ich werde index.html alle Anforderungen für Winkelrouten des Winkel-App-Pfads verarbeiten lassen.

Versuchen Sie dies anstelle von anderen oder falschen Routen. Es funktioniert für mich, nicht sicher, scheint aber in Arbeit zu sein. Ich bin selbst darüber gestolpert, als ich vor einem Problem stand.

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

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

Denken Sie jedoch daran, Ihre Serverordner und Zugriffsrechte zu konfigurieren, falls Sie HTML- oder Web-Skripte haben, die kein SPA sind. Sonst werden Sie Probleme haben. Für mich war es bei Problemen wie Ihnen eine Mischung aus Serverkonfiguration und höher.


4

Bearbeiten Sie für die schnelle Korrektur von Winkel 5 app.module.ts und fügen Sie sie {useHash:true}nach den appRoutes hinzu.

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

3

Angular Apps sind perfekte Kandidaten für die Bereitstellung mit einem einfachen statischen HTML-Server. Sie benötigen keine serverseitige Engine, um Anwendungsseiten dynamisch zu erstellen, da Angular dies auf der Clientseite tut.

Wenn die App den Angular-Router verwendet, müssen Sie den Server so konfigurieren, dass die Hostseite der Anwendung (index.html) zurückgegeben wird, wenn Sie nach einer Datei gefragt werden, über die sie nicht verfügt.

Eine geroutete Anwendung sollte "Deep Links" unterstützen. Ein Deep Link ist eine URL, die einen Pfad zu einer Komponente in der App angibt. Zum Beispiel ist http://www.example.com/heroes/42 ein tiefer Link zur Heldendetailseite, auf der der Held mit der ID: 42 angezeigt wird.

Es gibt kein Problem, wenn der Benutzer von einem laufenden Client aus zu dieser URL navigiert. Der Angular-Router interpretiert die URL und leitet sie zu dieser Seite und diesem Helden weiter.

Wenn Sie jedoch auf einen Link in einer E-Mail klicken, ihn in die Adressleiste des Browsers eingeben oder den Browser lediglich auf der Heldendetailseite aktualisieren, werden alle diese Aktionen vom Browser selbst außerhalb der laufenden Anwendung ausgeführt. Der Browser fordert den Server direkt unter Umgehung des Routers an.

Ein statischer Server gibt routinemäßig index.html zurück, wenn er eine Anforderung für http://www.example.com/ erhält . Es lehnt jedoch http://www.example.com/heroes/42 ab und gibt den Fehler 404 - Nicht gefunden zurück, es sei denn, es ist so konfiguriert, dass stattdessen index.html zurückgegeben wird

Wenn dieses Problem in der Produktion aufgetreten ist, führen Sie die folgenden Schritte aus

1) Fügen Sie eine Web.Config-Datei im Ordner src Ihrer Winkelanwendung hinzu. Geben Sie den folgenden Code ein.

<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) Fügen Sie in angle-cli.json einen Verweis darauf hinzu. Fügen Sie in angle-cli.json Web.config wie unten gezeigt in den Assets-Block ein.

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

3) Jetzt können Sie die Lösung für die Produktion mit erstellen

ng build --prod

Dadurch wird ein dist-Ordner erstellt. Die Dateien im Ordner dist können in jedem Modus bereitgestellt werden.


Die beste Lösung finden Sie unter Angular : angle.io/guide/deployment#fallback Vergessen Sie beim Erstellen der Datei web.config nicht, das Tag <configuration> </ configuration> hinzuzufügen. Danke für die Antwort Malatesh.
Palash Roy

3

Sie können diese Lösung für mittlere Anwendungen verwenden. Ich habe ejs als Ansichtsmodul verwendet:

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

und auch in angle-cli.json gesetzt

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

es wird gut funktionieren statt

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

Das Problem beim Abrufen von Datenbankaufrufen und beim Zurückgeben von index.html


1
Dies funktionierte im Oktober 2017 perfekt für die MEAN-Stack-Anwendung.
Mindsect Team

2

Für diejenigen von uns, die sich durch das Leben in IIS kämpfen: Verwenden Sie den folgenden PowerShell-Code, um dieses Problem basierend auf den offiziellen Angular 2-Dokumenten zu beheben (die jemand in diesem Thread gepostet hat? 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

Dadurch wird der 404 gemäß dem Vorschlag in den Angular 2-Dokumenten (Link oben) in die Datei /index.html umgeleitet.


2

Sie können unten ausprobieren. Für mich geht das!

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

Sie können path.strub (2) weiter verbessern, um es in Router-Parameter aufzuteilen. Ich benutze Angular 2.4.9


Dies war sehr hilfreich für die Handhabung von Browser-Aktualisierungen! Für Winkel 5 musste ich es ein wenig ändern, um window.location.pathname zu verwenden, und diesen Wert mit den erwarteten Pfaden vergleichen.
Wallace Howery

2

Ich füge nur .htaccess in root hinzu.

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

Hier füge ich einfach den Punkt '.' (übergeordnetes Verzeichnis) in /index.html zu ./index.html hinzu. Stellen Sie
sicher, dass Ihre index.html-Datei im Basispfad der Hauptverzeichnispfad ist und im Build des Projekts festgelegt ist.


1

Ich wollte den URL-Pfad von Unterseiten im HTML5-Modus beibehalten, ohne zum Index zurückzuleiten, und keine der Lösungen hat mir gesagt, wie das geht. So habe ich es erreicht:

Erstellen Sie einfache virtuelle Verzeichnisse in IIS für alle Ihre Routen und verweisen Sie sie auf das App-Stammverzeichnis.

Wickeln Sie Ihren system.webServer in Ihre Web.config.xml mit diesem Standort-Tag ein. Andernfalls werden beim Laden von Web.config ein zweites Mal mit dem virtuellen Verzeichnis doppelte Fehler angezeigt:

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

1

Ich habe in eckigen 2 Samen eingecheckt, wie es funktioniert.

Sie können Express-History-API-Fallback verwenden , um beim erneuten Laden einer Seite automatisch umzuleiten.

Ich denke, es ist der eleganteste Weg, um dieses Problem IMO zu lösen.


1

Wenn Sie PathLocationStrategy verwenden möchten:

  • Wildfly-Konfiguration:
    • Erstellen Sie die Datei "Sog-Handler.conf", die im WEB-INF abgelegt werden soll
    • Inhalt: (Schließen Sie Ihre Restendpunkte aus!)
      • Regex ['(. / Übersicht /?. ? $)'] und nicht Regex ['(. / Endpunkte. )'] -> neu schreiben ['/ index.html']
      • regex ['(. / deployments /?. ? $)'] und nicht regex ['(. / endpoints. )'] -> rewrite ['/ index.html']

Einzelseitenanwendung mit Java EE / Wildfly: serverseitige Konfiguration


1

2017-Juli-11: Da dies mit einer Frage verknüpft ist , die dieses Problem hat, aber Angular 2 mit Electron verwendet, werde ich hier meine Lösung hinzufügen.

Alles was ich tun musste war <base href="./">aus meiner index.html zu entfernen und Electron begann die Seite erneut erfolgreich neu zu laden.


1

Importe hinzufügen:

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

Fügen Sie im NgModule-Anbieter Folgendes hinzu:

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

Ändern Sie in der Datei index.html der App die Basis href in ./index.html von/

Wenn die App auf einem beliebigen Server bereitgestellt wird, gibt sie eine echte URL für die Seite an, auf die von jeder externen Anwendung aus zugegriffen werden kann.


1

Fügen Sie einfach .htaccess in root Resolution 404 hinzu, während Sie die Seite in Angular 4 Apache2 aktualisieren.

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

1

Ich denke, Sie bekommen 404, weil Sie http: // localhost / route anfordern das auf dem Tomcat-Server nicht vorhanden ist. Da Angular 2 standardmäßig HTML 5-Routing verwendet, anstatt Hashes am Ende der URL zu verwenden, sieht das Aktualisieren der Seite wie eine Anforderung für eine andere Ressource aus.

Wenn Sie Angular Routing auf Tomcat verwenden, müssen Sie sicherstellen, dass Ihr Server alle Routen in Ihrer App Ihrer Hauptindex.html zuordnet, während Sie die Seite aktualisieren. Es gibt mehrere Möglichkeiten, dieses Problem zu beheben. Was auch immer zu Ihnen passt, Sie können sich dafür entscheiden.

1) Fügen Sie den folgenden Code in die Datei web.xml Ihres Bereitstellungsordners ein:

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

2) Sie können auch versuchen, HashLocationStrategy mit # in der URL für Routen zu verwenden:

Versuchen Sie es mit:

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

Anstatt:

RouterModule.forRoot (Routen)

Mit HashLocationStrategy werden Ihre URLs wie folgt aussehen:

http: // localhost / # / route

3) Tomcat URL Rewrite Valve: Schreiben Sie die URLs mithilfe einer Konfiguration auf Serverebene neu, um sie zu index.html umzuleiten, wenn die Ressource nicht gefunden wird.

3.1) Erstellen Sie im Ordner META-INF eine Datei context.xml und kopieren Sie den folgenden Kontext hinein.

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

3.2) Erstellen Sie in WEB-INF die Datei rewrite.config (diese Datei enthält die Regel für das Umschreiben von URLs und wird von Tomcat zum Umschreiben von URLs verwendet). Kopieren Sie in rewrite.config den folgenden Inhalt:

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

0

Dies ist nicht die richtige Antwort, aber bei der Aktualisierung können Sie alle toten Anrufe auf die Homepage umleiten, indem Sie die 404-Seite opfern. Dies ist ein vorübergehender Hack, der nur in der Datei 404.html wiederholt wird

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

0

Die beste Lösung, um den "Router, der nicht am Neuladen des Browsers arbeitet" zu beheben, besteht darin, Spa-Fallback zu verwenden. Wenn Sie eine Angular2-Anwendung mit asp.net-Kern verwenden, müssen Sie diese auf der Seite "StartUp.cs" definieren. unter MVC-Routen. Ich füge den Code hinzu.

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

0

Die Antwort ist ziemlich schwierig. Wenn Sie einen einfachen alten Apache-Server (oder IIS) verwenden, tritt das Problem auf, da die Angular-Seiten nicht wirklich vorhanden sind. Sie werden aus der Winkelroute "berechnet".

Es gibt verschiedene Möglichkeiten, um das Problem zu beheben. Eine besteht darin, die von Angular angebotene HashLocationStrategy zu verwenden . In der URL wird jedoch ein scharfes Zeichen hinzugefügt. Dies dient hauptsächlich der Kompatibilität mit Angular 1 (nehme ich an). Tatsache ist, dass der Teil nach dem scharfen Teil nicht Teil der URL ist (dann löst der Server den Teil vor dem "#" - Zeichen auf). Das kann perfekt sein.

Hier eine erweiterte Methode (basierend auf dem 404-Trick). Ich gehe davon aus, dass Sie eine "verteilte" Version Ihrer Winkelanwendung haben (ng build --prod Angular- wenn Sie Angular-CLI verwenden) und Sie direkt mit Ihrem Server auf die Seiten zugreifen und PHP aktiviert ist.

Wenn Ihre Website auf Seiten basiert (z. B. Wordpress) und Sie nur einen Ordner für Angular haben (in meinem Beispiel "dist" genannt), können Sie etwas Seltsames tun, aber am Ende einfach. Ich gehe davon aus, dass Sie Ihre Angular-Seiten in "/ dist" (mit dem entsprechenden <BASE HREF="/dist/">) gespeichert haben . Verwenden Sie jetzt eine 404-Umleitung und die Hilfe von PHP.

In Ihrer Apache-Konfiguration (oder in der .htaccessDatei Ihres eckigen Anwendungsverzeichnisses) müssen Sie hinzufügenErrorDocument 404 /404.php

Die 404.php startet mit folgendem Code:

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

Wo $angularist der Wert, der in der HREF Ihres Winkels gespeichert ist?index.html .

Das Prinzip ist recht einfach: Wenn Apache die Seite nicht findet, wird eine 404-Umleitung zum PHP-Skript vorgenommen. Wir prüfen nur, ob sich die Seite im eckigen Anwendungsverzeichnis befindet. In diesem Fall laden wir die index.html einfach direkt (ohne umzuleiten): Dies ist erforderlich, um die URL unverändert zu lassen. Wir ändern auch den HTTP-Code von 404 auf 200 (nur besser für Crawler).

Was ist, wenn die Seite in der Winkelanwendung nicht vorhanden ist? Nun, wir verwenden das "catch all" des Angular-Routers (siehe Dokumentation zum Angular-Router).

Diese Methode funktioniert mit einer eingebetteten Angular-Anwendung innerhalb einer einfachen Website (ich denke, dass dies in Zukunft der Fall sein wird).

ANMERKUNGEN:

  • Der Versuch, dasselbe mit dem zu tun mod_redirect (durch Umschreiben der URLs) ist überhaupt keine gute Lösung, da Dateien (wie Assets) wirklich geladen werden müssen, dann ist es viel riskanter als nur die "nicht gefundene" Lösung zu verwenden.
  • Nur das Umleiten mithilfe von ErrorDocument 404 /dist/index.htmlWorks, aber Apache antwortet immer noch mit einem 404-Fehlercode (was für Crawler schlecht ist).

0

Dies ist keine dauerhafte Lösung für das Problem, sondern eher eine Problemumgehung oder ein Hack

Ich hatte genau das gleiche Problem bei der Bereitstellung meiner Angular App auf Gh-Seiten. Zuerst wurde ich mit 404 Nachrichten begrüßt, als ich meine Seiten auf Gh-Seiten aktualisierte.

Dann, wie @gunter darauf hinwies, fing ich an zu benutzen HashLocationStrategy das mit Angular 2 gelieferte zu verwenden.

Aber das brachte seine eigenen Probleme mit sich, die #in der URL wirklich schlecht waren und die URL so seltsam aussehen ließenhttps://rahulrsingh09.github.io/AngularConcepts/#/faq .

Ich begann über dieses Problem zu recherchieren und stieß auf einen Blog. Ich habe versucht, es zu versuchen, und es hat funktioniert.

Hier ist, was ich getan habe, wie in diesem Blog erwähnt.

Sie müssen zunächst eine 404.html-Datei zu Ihrem gh-pages-Repo hinzufügen, die ein leeres HTML-Dokument enthält. Ihr Dokument muss jedoch mehr als 512 Byte umfassen (siehe unten). Fügen Sie als Nächstes das folgende Markup in das Kopfelement Ihrer 404.html-Seite ein:

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

Dieser Code setzt die versuchte Eingangs-URL auf eine Variable im Standard-sessionStorage-Objekt und leitet sie sofort mithilfe eines Meta-Refresh-Tags zur index.html-Seite Ihres Projekts weiter. Wenn Sie eine Github Organization-Site erstellen, geben Sie keinen Repo-Namen in den Ersatztext für Inhaltsattribute ein. Gehen Sie dazu folgendermaßen vor: content = "0; URL = '/'"

Um die URL zu erfassen und wiederherzustellen, zu der der Benutzer ursprünglich navigiert hat, müssen Sie dem Kopf Ihrer index.html-Seite das folgende Skript-Tag hinzufügen, bevor ein anderes JavaScript auf den aktuellen Status der Seite einwirkt:

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

Dieses JavaScript-Bit ruft die URL ab, die wir in sessionStorage auf der Seite 404.html zwischengespeichert haben, und ersetzt den aktuellen Verlaufseintrag durch diese.

Referenz- Backalleycoder Vielen Dank an @Daniel für diese Problemumgehung.

Jetzt ändert sich die obige URL in https://rahulrsingh09.github.io/AngularConcepts/faq


0

Ich habe dies behoben (mithilfe des Java / Spring-Backends), indem ich einen Handler hinzugefügt habe, der mit allen in meinen Angular-Routen definierten Elementen übereinstimmt und index.html anstelle eines 404 zurücksendet. Dadurch wird die Anwendung effektiv (neu) gebootet und die richtige Seite geladen. Ich habe auch einen 404-Handler für alles, was davon nicht erfasst wird.

@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";
    }
}

0

Wenn Sie Apache oder Nginx als Server verwenden, müssen Sie einen .htaccess erstellen

<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>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.