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