Angular Ошибка 2: 404 возникает при обновлении через браузер
Я новичок в Angular 2. Я сохранил одностраничное приложение на своем сервере в папке с именем "myapp". Я изменил URL-адрес базы в http://example.com/myapp/`.
Мой проект состоит из двух страниц. Поэтому я реализую маршрутизацию Angular 2. Я установил страницу по умолчанию как логин. Когда я набираю http://example.com/myapp/
в своем браузере, он автоматически перенаправляется на http://example.com/myapp/login
. Но если обновить эту страницу, я получаю ошибку 404
, говоря, что http://example.com/myapp/login
не найден.
Но если я запускаю свой проект с использованием сервера Lite, все работает. В этом случае базовый URL-адрес в index.html будет "/"
. Как это исправить?
Ответы
Ответ 1
Фактически, это нормально, что у вас возникает ошибка 404 при обновлении приложения, поскольку обновляется фактический адрес в браузере (и без подхода #/hashbang). По умолчанию история HTML5 используется для повторного использования в Angular2.
Чтобы исправить ошибку 404, вам нужно обновить сервер, чтобы он обслуживал файл index.html
для каждого заданного вами маршрута.
Если вы хотите переключиться на подход HashBang, вам нужно использовать эту конфигурацию:
import {bootstrap} from 'angular2/platform/browser';
import {provide} from 'angular2/core';
import {ROUTER_PROVIDERS} from 'angular2/router';
import {LocationStrategy, HashLocationStrategy} from '@angular/common';
import {MyApp} from './myapp';
bootstrap(MyApp, [
ROUTER_PROVIDERS,
{provide: LocationStrategy, useClass: HashLocationStrategy}
]);
В этом случае, когда вы обновите страницу, она будет отображаться снова (но у вас будет #
в вашем адресе).
Эта ссылка также может вам помочь: когда я обновляю свой сайт, я получаю 404. Это с Angular2 и firebase.
Надеюсь, это поможет тебе, Тьерри
Ответ 2
Обновление для Angular 2 финальной версии
В app.module.ts:
-
Добавить импорт:
import { HashLocationStrategy, LocationStrategy } from '@angular/common';
-
А в провайдере NgModule добавьте:
{provide: LocationStrategy, useClass: HashLocationStrategy}
Пример (app.module.ts):
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { HashLocationStrategy, LocationStrategy } from '@angular/common';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}],
bootstrap: [AppComponent],
})
export class AppModule {}
альтернатива
Используйте RouterModule.forRoot с аргументом {useHash: true}.
Пример: (из угловых документов)
import { NgModule } from '@angular/core';
...
const routes: Routes = [//routes in here];
@NgModule({
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot(routes, { useHash: true })
],
bootstrap: [AppComponent]
})
export class AppModule { }
Ответ 3
Для людей (таких как я), которые действительно хотят PathLocationStrategy
(то есть html5Mode) вместо HashLocationStrategy
, см. Как: настроить сервер для работы с html5Mode из сторонней вики:
Когда у вас включен html5Mode, символ #
больше не будет использоваться в ваших URL. Символ #
полезен, поскольку не требует настройки на стороне сервера. Без #
, URL выглядит намного лучше, но он также требует переписывания на стороне сервера.
Здесь я скопирую только три примера из вики, на случай, если вики заблудятся. Другие примеры можно найти, выполнив поиск по ключевому слову "URL rewrite" (например, этот ответ для Firebase).
апаш
<VirtualHost *:80>
ServerName my-app
DocumentRoot /path/to/app
<Directory /path/to/app>
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]
</Directory>
</VirtualHost>
Документация для модуля перезаписи
Nginx
server {
server_name my-app;
root /path/to/app;
location / {
try_files $uri $uri/ /index.html;
}
}
Документация для try_files
IIS
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" 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>
Ответ 4
У меня была та же проблема. Приложение Angular работает на сервере Windows.
Я решил эту проблему, создав файл web.config в каталоге root.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="AngularJS" 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>
Ответ 5
Возможно, вы сможете сделать это при регистрации вашего root
с помощью RouterModule
. Вы можете передать второй объект со свойством useHash:true
, как показано ниже:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ROUTES } from './app.routes';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
RouterModule.forRoot(ROUTES ,{ useHash: true }),],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Ответ 6
Для людей, читающих это, используя Angular 2 rc4 или более поздней версии, появляется LocationStrategy, перемещенный из маршрутизатора в обычный. Вам придется импортировать его оттуда.
Также обратите внимание на фигурные скобки вокруг строки "обеспечить".
main.ts
// Imports for loading & configuring the in-memory web api
import { XHRBackend } from '@angular/http';
// The usual bootstrapping imports
import { bootstrap } from '@angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '@angular/http';
import { AppComponent } from './app.component';
import { APP_ROUTER_PROVIDERS } from './app.routes';
import { Location, LocationStrategy, HashLocationStrategy} from '@angular/common';
bootstrap(AppComponent, [
APP_ROUTER_PROVIDERS,
HTTP_PROVIDERS,
{provide: LocationStrategy, useClass: HashLocationStrategy}
]);
Ответ 7
Если вы используете Angular 2 через ASP.NET Core 1 в Visual Studio 2015, вы можете найти это решение от Jürgen Gutsch полезным. Он описывает это в сообщении в блоге. Это было лучшее решение для меня. Поместите код С#, приведенный ниже в вашем Startup.cs public void Configure() непосредственно перед app.UseStaticFiles();
app.Use( async ( context, next ) => {
await next();
if( context.Response.StatusCode == 404 && !Path.HasExtension( context.Request.Path.Value ) ) {
context.Request.Path = "/index.html";
await next();
}
});