当我通过浏览器刷新时出现Angular 2:404错误

时间:2016-02-09 06:04:18

标签: angular angular2-routing

我是Angular 2的新手。我已将我的单页应用程序存储在名为“myapp”的文件夹中的服务器中。我已将基础中的网址更改为http://example.com/myapp/`。

我的项目有两页。所以我实现了Angular 2路由。我将默认页面设置为登录。当我在浏览器中输入header("Content-type:application/json");时,它会自动重定向到http://example.com/myapp/。但是,如果刷新该页面,则会收到http://example.com/myapp/login错误,说明找不到404

但如果我使用lite服务器运行我的项目,一切正常。在这种情况下,index.html中的网址将为http://example.com/myapp/login。如何解决?

7 个答案:

答案 0 :(得分:212)

Angular 2 final 版本

的更新

在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}参数一起使用。

示例: (来自angular docs

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

答案 1 :(得分:110)

事实上,刷新应用程序时出现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}
]);

在这种情况下,当您刷新页面时,它会再次显示(但您的地址中会有#。)

此链接也可以为您提供帮助:When I refresh my website I get a 404. This is with Angular2 and firebase

希望它可以帮到你, 亨利

答案 2 :(得分:86)

对于真正想要PathLocationStrategy(即html5Mode)而不是HashLocationStrategy的人(比如我),请参阅第三方维基中的 How to: Configure your server to work with html5Mode :< / p>

  

如果启用了html5Mode,则您的网址中将不再使用#字符。 #符号很有用,因为它不需要服务器端配置。没有#,URL看起来更好,但它也需要服务器端重写。

这里我只复制了wiki中的三个例子,以防Wiki丢失。通过搜索关键字“URL重写”(例如Firebase的this answer)可以找到其他示例。

的Apache

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

Documentation for rewrite module

nginx的

server {
    server_name my-app;

    root /path/to/app;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

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

答案 3 :(得分:24)

我遇到了同样的问题。我的Angular应用程序正在Windows服务器上运行。

我通过在 root 目录中创建 web.config 文件解决了这个问题。

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

答案 4 :(得分:17)

也许您可以在使用RouterModule注册root时执行此操作。您可以使用属性&#34; useHash:true&#34;传递第二个对象。如下所示:

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

答案 5 :(得分:5)

对于使用Angular 2 rc4或更高版本的人来说,看起来LocationStrategy已从路由器移动到公共端。你必须从那里导入它。

另请注意&#39;周围的花括号提供&#39;线。

<强> 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}
]);

答案 6 :(得分:5)

如果您在Visual Studio 2015中通​​过ASP.NET Core 1运行Angular 2,您可能会发现JürgenGutsch的此解决方案很有帮助。他在a blog post中对此进行了描述。这对我来说是最好的解决方案。在app.UseStaticFiles();

之前,将下面提供的C#代码放在Startup.cs public void Configure()中
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();
    }
});