Router Angular 2.0 nie działa przy ponownym ładowaniu przeglądarki


190

Używam wersji Angular 2.0.0-alpha.30. Po przekierowaniu na inną trasę odśwież stronę przeglądarki, wyświetlając komunikat Nie można uzyskać / trasy.

Czy możesz mi pomóc w ustaleniu przyczyny tego błędu.



Dzięki za odpowiedź, ale ta dotyczy wersji kątowych 1.x. Problem ten pojawia się w wersji kątowej 2.0.
Vinz i Tonz

1
Powiązane pytanie jest ogólnym problemem związanym z pushState, a nie specyficznym dla Angulara. Twoje pytanie nie zawiera wystarczających informacji, aby wiedzieć, czy jest powiązane.
Günter Zöchbauer

5
Angular 2.0 używa zupełnie nowego routera, więc połączony post nie jest już potrzebny, ponieważ jest to stary router
Vinz i Tonz

Jak powiedziałem, jeśli jest to problem pushState, nie jest on specyficzny dla Angulara i nie może być naprawiony przez Angular, ale zamiast tego musi zostać naprawiony na serwerze.
Günter Zöchbauer

Odpowiedzi:


141

Występujący błąd jest spowodowany żądaniem adresu http: // localhost / route, który nie istnieje. Według Simona .

Podczas korzystania z routingu HTML5 musisz zmapować wszystkie trasy w aplikacji (obecnie 404) na index.html po stronie serwera. Oto kilka opcji dla Ciebie:

  1. za pomocą serwera na żywo: https://www.npmjs.com/package/live-server

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

    error_page 404 /index.html
    
  3. Tomcat - konfiguracja pliku web.xml. Z komentarza Kunina

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

1
Ponieważ do obsługi html5 potrzebne jest wsparcie po stronie serwera, działa to doskonale. Dzięki
Prabhat

Czy mogę używać nginx jako proxy pub serve? W ten sposób nie muszę pub buildzbyt wiele podczas programowania. Próbowałem, ale proxy_passnie działa zbyt dobrze error_page.
Franklin Yu,

@FranklinYu Nie zrobiłem tego wcześniej. Czy masz to rozwiązane?
Quy Tang,

1
Używanie nginx. , error_page 404 /index.html w lokalizacji aplikacji działał dla mnie. Dziękuję Ci.
Richard K. Campion

2
Tomcat - konfiguracja web.xml <error-page> <error-code> 404 </error-code> <location> /index.html </location> </error-page>
A Kunin

65

Oświadczenie: ta poprawka działa z Alpha44

Miałem ten sam problem i rozwiązałem go, wdrażając HashLocationStrategy wymienioną w Angular.io API Preview.

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

Zacznij od zaimportowania niezbędnych dyrektyw

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

I w końcu tak to wszystko razem

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

Twoja trasa pojawi się jako http: // localhost / # / route, a po odświeżeniu przeładuje się we właściwym miejscu.

Mam nadzieję, że to pomaga!


1
ten kod będzie działał dobrze, ale jest pewien problem w tej technice, dzięki użyciu tego #zostanie dodany automatycznie w adresie URL. czy istnieje jakieś rozwiązanie, aby usunąć # z adresu URL za pomocą tego?
Pardeep Jain

Zgadzam się, próbowałem wdrożyć „PathLocationStrategy” wymieniony tutaj , ale nie udało mi się go uruchomić. Adres URL bez #byłby optymalny.
SimonHawesome

Tak, ja też próbowałem tego samego z, PathLocationStrategyale to nie działa dla mnie. albo użyłem niewłaściwej metody, albo nie wiem, jak korzystać z PathLocationStrategy.
Pardeep Jain,

1
To nie działa dla mnie w RC1. Importowanie LocationStrategy, HashLocationStrategy z '@ angular / router' kończy się niepowodzeniem.
infojolt

1
Przepraszam, że wróciłem do tych pytań po ponad 1 roku :) Ale czy HashLocationStrategy pomaga pozostać na tej samej ścieżce routera? W moim przypadku po odświeżeniu zabiera mnie do localhost / # / <domyślna trasa> tj. Domyślna trasa dla strony głównej. Jak przejść do bieżącej trasy, na której pierwotnie byłem, kiedy „Odświeżono”?
rajugaadu

47

Angular domyślnie używa pushstate HTML5 ( PathLocationStrategyw slangu Angular).
Potrzebujesz albo serwera, który przetwarza wszystkie żądania, o które prosił, index.htmlalbo przełączasz się na HashLocationStrategy(z # w adresie URL tras) https://angular.io/docs/ts/latest/api/common/index/HashLocationStrategy-class. HTML

Zobacz także https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/

Aby przejść do HashLocationStrategyużycia

aktualizacja dla> = wersja RC.5 i 2.0.0

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

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

lub krócej z useHash

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

upewnij się, że masz wszystkie wymagane przywozy

Dla nowego routera (RC.3)

<base href="."> 

może również powodować 404.

To wymaga zamiast tego

<base href="/">

aktualizacja dla> = 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';  

aktualizacja dla> = beta.16 Importy uległy zmianie

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

Zobacz także https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta16-2016-04-26 najnowsze zmiany


1
Dzięki! wydaje się, że przeniesiono pod angular / core: import {dostarczyć} z 'angular2 / core'
StrangeLoop 26.04.16

1
Uwaga: update for >= RC.x(RC.2) działa z router 3.0.0-alpha.7, ale provideopatrzony adnotacjami jako przestarzały bez informacji o tym, która funkcja go zastąpiła.
Mrusful

Użyj{provide: SomeClass, useClass: OtherClass}
Günter Zöchbauer

2
Najbardziej aktualna odpowiedź. Do najnowszej wersji kątowej 2.4.1 miałem <base href = "./">. Zmieniono na <base href = "/"> rozwiązałem problem, który miałem. Może być komuś pomocny.
Saiyaff Farouk

28

Myślę, że błąd, który widzisz, jest spowodowany żądaniem http: // localhost / route, który nie istnieje. Musisz upewnić się, że Twój serwer zamapuje wszystkie żądania na głównej stronie index.html.

Ponieważ Angular 2 domyślnie korzysta z routingu HTML5 zamiast skrótów na końcu adresu URL, odświeżenie strony wygląda jak żądanie innego zasobu.


7
więc jak to naprawić? Jak domyślnie mapujemy wszystkie żądania do głównego indeksu? czy jest zależny od serwera?
Ayyash,

1
Tak, zrobiłbyś to na serwerze, niezależnie od używanego frameworka. Alternatywą jest użycie HashLocationStrategy, jak opisano poniżej.
Simon

Będziesz przeładowywać kątowe SPA na każdej nieobecnej trasie. Czy tak należy sobie z tym poradzić?
Gary

Przeładowuje się tylko wtedy, gdy użytkownik kliknie przycisk odśwież w przeglądarce, a nie wtedy, gdy użytkownik zmieni trasy przez interfejs użytkownika. Naprawdę nie ma żadnego sposobu na przeładowanie, gdy użytkownik odświeża.
Wallace Howery

19

Jest to powszechna sytuacja we wszystkich wersjach routera, jeśli używasz domyślnej strategii lokalizacji HTML.

Co się dzieje, że adres URL w pasku przeglądarki jest normalnym pełnym Kopiuj adres URL, jak na przykład: http://localhost/route.

Kiedy więc naciśniemy Enter na pasku przeglądarki, do serwera wysyłane jest aktualne żądanie HTTP w celu uzyskania pliku o nazwie route.

Serwer nie ma takiego pliku i ani coś takiego, jak express nie jest skonfigurowane na serwerze do obsługi żądania i dostarczenia odpowiedzi, więc serwer zwraca 404 Not Found, ponieważ nie mógł znaleźć routepliku.

Chcielibyśmy, aby serwer zwrócił index.htmlplik zawierający aplikację jednostronicową. Następnie router powinien uruchomić się, przetworzyć /routeadres URL i wyświetlić zmapowany komponent.

Aby rozwiązać ten problem, musimy skonfigurować serwer do powrotu index.html (zakładając, że jest to nazwa pliku aplikacji na jednej stronie) na wypadek, gdyby nie można było obsłużyć żądania, w przeciwieństwie do błędu 404.

Sposób na zrobienie tego będzie zależeć od zastosowanej technologii po stronie serwera. Jeśli na przykład Java jest w stanie napisać serwlet, w Railsach będzie inaczej itp.

Aby podać konkretny przykład, jeśli na przykład używasz NodeJs, musisz napisać oprogramowanie pośrednie takie jak to:

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

A następnie zarejestruj go na samym końcu łańcucha oprogramowania pośredniego:

app.use(sendSpaFileIfUnmatched);

Będzie to służyć index.htmlzamiast zwracać 404, router się uruchomi i wszystko będzie działać zgodnie z oczekiwaniami.


To był dokładnie mój problem. Jeśli używasz NGINX, ta odpowiedź pomaga go rozwiązać: stackoverflow.com/questions/7027636/...
Nathan

Czy istnieje poradnik, jak to zrobić dla Java? Dzięki.
000000000000000000000

13

Upewnij się, że jest to umieszczone w elemencie head twojego index.html:

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

Przykład w Angular2 Routing & nawigacja zastosowań dokumentacji następujący kod w głowie zamiast (oni wyjaśnić, dlaczego w żywej Przykład Uwaga dokumentacji):

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

Po odświeżeniu strony dynamicznie ustawi się podstawowy href na bieżącą lokalizację document.location. Widziałem, że powoduje to zamieszanie wśród osób przeglądających dokumentację i próbujących odtworzyć plunker.


Dzięki za udostępnienie tego. Wyjaśnijmy, działało to tylko dla mnie, gdy wstawiłem <base href = "/"> bezpośrednio po załadowaniu całego css do <head> i przed załadowaniem DOWOLNYCH plików Js. Mam nadzieję, że to pomoże każdemu
wmehanna,

mam <base href = "./"> w index.html, a następnie usunąłem '.' z href i zadziałało ..
Saurabh Solanki,

10

Jeśli chcesz mieć możliwość wprowadzania adresów URL w przeglądarce bez konfigurowania serwera AppServer do obsługi wszystkich żądań do pliku index.html, musisz użyć HashLocationStrategy .

Najłatwiejszym sposobem konfiguracji jest użycie:

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

Zamiast:

RouterModule.forRoot(routes)

Dzięki HashLocationStrategy Twoje adresy URL będą wyglądać następująco:

http://server:port/#/path

Dzięki! to pomaga, ale nie chcę #z adresu URL, czy możemy to usunąć?
Hidayt Rahman,

7

Miałem ten sam problem z używaniem webpack-dev-server. Musiałem dodać opcję devServer do mojego pakietu.

Rozwiązanie:

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

Rodzaj magii voodoo: p Aby uzyskać więcej informacji, patrz: webpack.github.io/docs/…
Jissay,

7

Jeśli używasz Apache lub Nginx jako serwera, musisz utworzyć .htaccess(jeśli nie był wcześniej utworzony) i „On” RewriteEngine

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

Nie otrzymałem twojego pytania, ta metoda przetestowana na serwerze Apache i Nginx ( nginx.com )
Rakesh Roy

1
Dotyczy to tylko Apache; Format konfiguracji Nginx jest zupełnie inny.
Franklin Yu

5

Mój serwer to Apache, co zrobiłem, aby naprawić błąd 404 podczas odświeżania lub głębokiego linkowania, jest bardzo prosty. Wystarczy dodać jedną linię w konfiguracji apache vhost:

ErrorDocument 404 /index.html

Aby każdy błąd 404 został przekierowany do index.html, czego chce routing angular2.

Cały przykład pliku 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>

Bez względu na to, z jakiego serwera korzystasz, myślę, że cała sprawa polega na znalezieniu sposobów skonfigurowania serwera do przekierowania 404 do pliku index.html.


4

Konfiguracja serwera nie jest rozwiązaniem dla SPA, o czym nawet myślę. Nie chcesz ponownie ładować kątowego SPA, jeśli pojawi się zła droga, prawda? Więc nie będę zależeć od trasy serwera i przekierować na inną trasę, ale tak, pozwolę index.html obsłużyć wszystkie żądania dotyczące kątowych tras ścieżki aplikacji kątowej.

Spróbuj tego zamiast innych lub złych tras. To działa dla mnie, nie jestem pewien, ale wydaje się, że praca w toku. Natknąłem się na to, gdy miałem do czynienia z problemem.

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

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

Pamiętaj jednak, aby skonfigurować foldery na serwerze i mieć do nich prawo dostępu w przypadku, gdy masz skrypty HTML lub internetowe, które nie są SPA. W przeciwnym razie napotkasz problemy. Dla mnie w obliczu problemu takiego jak ty była to kombinacja konfiguracji serwera i więcej.


4

w przypadku szybkiej poprawki kątowej 5 edytuj app.module.ts i dodaj {useHash:true}po appRoutes.

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

3

Aplikacje Angular są idealnymi kandydatami do obsługi prostego statycznego serwera HTML. Nie potrzebujesz silnika po stronie serwera, aby dynamicznie komponować strony aplikacji, ponieważ Angular robi to po stronie klienta.

Jeśli aplikacja korzysta z routera Angular, należy skonfigurować serwer tak, aby zwracał stronę hosta aplikacji (index.html), gdy zostanie wyświetlony monit o plik, którego nie ma.

Rutowana aplikacja powinna obsługiwać „precyzyjne linki”. Głęboki link to adres URL, który określa ścieżkę do komponentu w aplikacji. Na przykład http://www.example.com/heroes/42 to głęboki link do strony ze szczegółowymi informacjami o bohaterze, która wyświetla bohatera o identyfikatorze: 42.

Nie ma problemu, gdy użytkownik przechodzi do tego adresu URL z uruchomionego klienta. Router Angular interpretuje adres URL i trasy do tej strony i bohatera.

Ale klikając link w wiadomości e-mail, wpisując go w pasku adresu przeglądarki lub po prostu odświeżając przeglądarkę na stronie szczegółów bohatera - wszystkie te czynności są obsługiwane przez samą przeglądarkę, poza uruchomioną aplikacją. Przeglądarka wysyła do serwera bezpośrednie żądanie dotyczące tego adresu URL, omijając router.

Serwer statyczny rutynowo zwraca index.html, gdy otrzyma żądanie dotyczące http://www.example.com/ . Ale odrzuca http://www.example.com/heroes/42 i zwraca błąd 404 - Nie znaleziono, chyba że jest skonfigurowany do zwracania index.html

Jeśli ten problem wystąpił podczas produkcji, wykonaj poniższe kroki

1) Dodaj plik Web.Config w folderze src aplikacji kątowej. Umieść w nim poniższy kod.

<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) Dodaj odniesienie do niego w angular-cli.json. W angular-cli.json umieść Web.config w bloku zasobów, jak pokazano poniżej.

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

3) Teraz możesz zbudować rozwiązanie do produkcji przy użyciu

ng build --prod

Spowoduje to utworzenie folderu dist. Pliki w folderze dist są gotowe do wdrożenia w dowolnym trybie.


Najlepsze rozwiązanie, można znaleźć szczegóły z angular : angular.io/guide/deployment#fallback Podczas tworzenia pliku web.config nie zapomnij dodać znacznika <configuration> </configuration>. Dzięki za odpowiedź Malatesh.
Palash Roy

3

Możesz użyć tego rozwiązania do średniej aplikacji, użyłem ejs jako silnika przeglądania:

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

a także ustawiony w angular-cli.json

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

będzie działać dobrze zamiast

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

problem z tworzeniem wywołań db i zwracaniem index.html


1
Działa to doskonale w październiku 2017 r. Dla aplikacji stosowej MEAN.
Mindsect Team,

2

Dla tych z nas, którzy zmagają się z życiem w IIS: użyj następującego kodu PowerShell, aby rozwiązać ten problem na podstawie oficjalnych dokumentów Angular 2 (które ktoś opublikował w tym wątku? 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

To przekierowuje 404 do pliku /index.html zgodnie z sugestią w dokumentach Angular 2 (link powyżej).


2

Możesz wypróbować poniżej. Mi to pasuje!

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

Możesz dodatkowo ulepszyć path.substr (2), aby podzielić na parametry routera. Używam kątowej 2.4.9


Było to bardzo pomocne w obsłudze odświeżania przeglądarki! W przypadku kąta 5 musiałem go nieco zmodyfikować, aby użyć window.location.pathname i porównać tę wartość z oczekiwanymi ścieżkami.
Wallace Howery

2

i Właśnie dodałem .htaccess w katalogu głównym.

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

tutaj po prostu dodaję kropkę „.” (katalog nadrzędny) w pliku /index.html do ./index.html
upewnij się, że plik index.html w ścieżce podstawowej jest ścieżką do katalogu głównego i jest ustawiony w kompilacji projektu.


1

Chciałem zachować ścieżkę URL podstron w trybie HTML5 bez przekierowania z powrotem do indeksu i żadne z dostępnych rozwiązań nie powiedziało mi, jak to zrobić, więc oto jak to zrobiłem:

Utwórz proste katalogi wirtualne w IIS dla wszystkich tras i wskaż je na katalog główny aplikacji.

Zawiń plik system.webServer w pliku Web.config.xml za pomocą tego znacznika lokalizacji, w przeciwnym razie podczas ładowania pliku Web.config po raz drugi w katalogu wirtualnym wystąpią zduplikowane błędy:

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

1

Sprawdziłem, jak działa ziarno kątowe 2.

Możesz użyć express-history-api-fallback, aby automatycznie przekierowywać po przeładowaniu strony.

Myślę, że jest to najbardziej elegancki sposób rozwiązania tego problemu IMO.



1

2017-lipiec-11: Ponieważ jest to związane z pytaniem mającym ten problem, ale z użyciem Angulara 2 z elektronem, dodam tutaj moje rozwiązanie.

Wszystko, co musiałem zrobić, to usunąć <base href="./">z mojego index.html i Electron zaczął ponownie ładować stronę ponownie.


1

Dodaj import:

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

A u dostawcy NgModule dodaj:

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

W głównym index.html pliku aplikacji zmień podstawowy href na ./index.htmlz/

Aplikacja po wdrożeniu na dowolnym serwerze poda prawdziwy adres URL strony, do której można uzyskać dostęp z dowolnej aplikacji zewnętrznej.


1

Dopiero dodanie .htaccess w katalogu głównym rozwiązało 404 podczas odświeżania strony w kątowym 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>

1

Myślę, że otrzymujesz 404, ponieważ żądasz http: // localhost / route, który nie istnieje na serwerze tomcat. Ponieważ Angular 2 domyślnie używa routingu HTML 5 zamiast skrótów na końcu adresu URL, odświeżenie strony wygląda jak żądanie innego zasobu.

Korzystając z routingu kątowego na tomcat, musisz upewnić się, że Twój serwer zamapuje wszystkie trasy w Twojej aplikacji na główny index.html podczas odświeżania strony. Istnieje wiele sposobów rozwiązania tego problemu. Niezależnie od tego, który Ci odpowiada, możesz na to pójść.

1) Umieść poniższy kod w pliku web.xml folderu wdrażania:

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

2) Możesz także spróbować użyć HashLocationStrategy z # w adresie URL dla tras:

Spróbuj użyć:

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

Zamiast:

RouterModule.forRoot (trasy)

Dzięki HashLocationStrategy Twoje adresy URL będą wyglądać następująco:

http: // localhost / # / route

3) Zawór przepisywania adresu URL Tomcat: przepisz adres URL, używając konfiguracji na poziomie serwera, aby przekierować do index.html, jeśli zasób nie zostanie znaleziony.

3.1) Wewnątrz folderu META-INF utwórz plik context.xml i skopiuj do niego poniższy kontekst.

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

3.2) Wewnątrz WEB-INF utwórz plik rewrite.config (plik ten zawiera regułę przepisywania adresów URL i używany przez tomcat do przepisywania adresów URL). Wewnątrz rewrite.config skopiuj poniższą treść:

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

0

To nie jest właściwa odpowiedź, ale po odświeżeniu możesz przekierować wszystkie martwe połączenia do strony głównej, poświęcając stronę 404, jest to tymczasowy hack, po prostu powtórka po pliku 404.html

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

0

Najlepszym rozwiązaniem rozwiązania problemu „router nie działa przy ponownym ładowaniu przeglądarki” jest to, że powinniśmy skorzystać z przywracania spa. Jeśli używasz aplikacji angular2 z rdzeniem asp.net, musimy to zdefiniować na stronie „StartUp.cs”. pod trasami MVC. Załączam kod.

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

0

Odpowiedź jest dość trudna. Jeśli używasz zwykłego starego serwera Apache (lub IIS), pojawia się problem, ponieważ strony Angular nie istnieją naprawdę. Są one „obliczane” z trasy kątowej.

Istnieje kilka sposobów rozwiązania tego problemu. Jednym z nich jest użycie HashLocationStrategy oferowanej przez Angular. Ale adres URL zawiera ostry znak. Dotyczy to głównie kompatybilności z Angularem 1 (zakładam). Faktem jest, że część po tym, jak sharp nie jest częścią adresu URL (wtedy serwer rozwiązuje tę część przed znakiem „#”). To może być idealne.

Oto ulepszona metoda (oparta na sztuczce 404). Zakładam, że masz „rozproszoną” wersję swojej aplikacji kątowej ( ng build --prodjeśli używasz Angular-CLI) i uzyskujesz dostęp do stron bezpośrednio na serwerze i PHP jest włączony.

Jeśli twoja strona oparta jest na stronach (na przykład Wordpress) i masz tylko jeden folder poświęcony Angularowi (w moim przykładzie nazwany „dist”), możesz zrobić coś dziwnego, ale na koniec prostego. Zakładam, że zapisałeś swoje strony Angulara w „/ dist” (zgodnie z tym <BASE HREF="/dist/">). Teraz użyj przekierowania 404 i pomocy PHP.

W konfiguracji Apache (lub w .htaccesspliku katalogu aplikacji kątowych) musisz dodaćErrorDocument 404 /404.php

Plik 404.php rozpocznie się od następującego kodu:

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

gdzie $angularjest wartość przechowywana w HREF twojego kąta index.html.

Zasada jest dość prosta, jeśli Apache nie znajdzie strony, następuje przekierowanie 404 do skryptu PHP. Sprawdzamy tylko, czy strona znajduje się w katalogu aplikacji kątowych. W takim przypadku wystarczy załadować plik index.html bezpośrednio (bez przekierowywania): jest to konieczne, aby adres URL pozostał niezmieniony. Zmieniamy również kod HTTP z 404 na 200 (po prostu lepiej dla robotów).

Co jeśli strona nie istnieje w aplikacji kątowej? Używamy „catch all” routera kątowego (patrz dokumentacja routera kątowego).

Ta metoda działa z osadzoną aplikacją Angular na podstawowej stronie internetowej (myślę, że tak będzie w przyszłości).

UWAGI:

  • Próba zrobienia tego samego z mod_redirect(poprzez przepisanie adresów URL) wcale nie jest dobrym rozwiązaniem, ponieważ pliki (takie jak zasoby) muszą być naprawdę ładowane, to jest o wiele bardziej ryzykowne niż samo użycie rozwiązania „nie znaleziono”.
  • Po prostu przekierowanie za pomocą ErrorDocument 404 /dist/index.htmldziała, ale Apache nadal odpowiada kodem błędu 404 (co jest złe dla przeszukiwaczy).

0

To nie jest trwałe rozwiązanie problemu, ale bardziej jak obejście lub włamanie

Miałem ten sam problem podczas wdrażania mojej aplikacji Angular na stronach gh. Najpierw przywitano mnie 404 wiadomościami podczas odświeżania moich stron na stronach gh.

Następnie, jak wskazał @gunter, zacząłem używać, HashLocationStrategyktóry został dostarczony z Angular 2.

Ale to przyszło z własnym zestawem problemów, ponieważ #w adresie URL było naprawdę źle, że wyglądał tak dziwnie https://rahulrsingh09.github.io/AngularConcepts/#/faq.

Zacząłem badać ten problem i natknąłem się na blog. Próbowałem spróbować i udało się.

Oto, co zrobiłem, jak wspomniano na tym blogu.

Musisz zacząć od dodania pliku 404.html do repozytorium gh-pages, który zawiera pusty dokument HTML - ale Twój dokument musi mieć łącznie ponad 512 bajtów (wyjaśnione poniżej). Następnie umieść następujący znacznik w nagłówku strony 404.html:

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

Ten kod ustawia adres URL próby wejścia do zmiennej w standardowym obiekcie sessionStorage i natychmiast przekierowuje do strony index.html projektu za pomocą metatagu odświeżania. Jeśli prowadzisz witrynę organizacji Github, nie umieszczaj nazwy repo w tekście zamiennika atrybutu treści, po prostu zrób to: content = "0; URL = '/'"

Aby przechwycić i przywrócić adres URL, do którego początkowo nawigował użytkownik, musisz dodać następujący znacznik skryptu do nagłówka strony index.html, zanim jakikolwiek inny skrypt JavaScript zadziała w bieżącym stanie strony:

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

Ten kawałek JavaScript pobiera adres URL, który buforowaliśmy w sessionStorage na stronie 404.html i zastępuje go bieżącym wpisem historii.

Referencyjny backalleycoder Podziękowania dla @Daniel za to obejście.

Teraz powyższy adres URL zmienia się na https://rahulrsingh09.github.io/AngularConcepts/faq


0

Naprawiłem to (używając backendu Java / Spring), dodając moduł obsługi, który pasuje do wszystkiego zdefiniowanego w moich trasach Angular, który wysyła z powrotem index.html zamiast 404. To wtedy (ponownie) ładuje aplikację i ładuje właściwą stronę. Mam również moduł obsługi 404 dla wszystkiego, co nie jest przez to złapane.

@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

Jeśli używasz Apache lub Nginx jako serwera, musisz utworzyć .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>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.