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

DAN*_*DAN 164 angular2-routing angular

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

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

但如果我使用lite服务器运行我的项目,一切正常.在这种情况下,index.html中的URL将是"/".如何解决?

Asa*_*nel 230

Angular 2最终版本的更新

在app.module.ts中:

示例(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 {}
Run Code Online (Sandbox Code Playgroud)

替代

将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 { }
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用.谢谢.但有没有办法失去#? (16认同)
  • 答案可能会根据受欢迎程度重新排列,因此不会保留相对定位.请在答案中提供其他答案的链接. (2认同)
  • 是的,这对我也有用。但我使用 auth0 进行身份验证,并且必须提供允许的网址。当我刷新现在添加哈希的页面时,然后登录它不会接受该网址。刷新页面时修复此问题或删除主题标签的建议是什么? (2认同)
  • 致力于Angular 4.2.6 :) (2认同)

Thi*_*ier 123

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

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

这个链接也可以帮到你:当我刷新我的网站时,我得到了404.这是使用Angular2和firebase.

希望它对你有帮助,蒂埃里

  • 富兰克林·于的答案实际上应该是被接受的答案。Thierry Templier的答案只是说放回#来摆脱问题,这不是答案,或者使用提供的链接假定​​海报使用的是火力基地,而海报使用的不是。富兰克林(Franklin)提供的Wiki附带了一个注释,回答了Apache的问题,您可以在.htaccess文件中添加相同的配置。 (3认同)
  • 这解决了我的问题,非常感谢。但是,使用HashBang方法有什么缺点吗?我是说在SEO或其他方面呢? (2认同)
  • 如果我们不想使用 HashLocationStrategy 而想使用 PathLocationStrategy 怎么办? (2认同)
  • @Ben正如Thierry所说,"如果您不想出现404错误,则需要更新服务器以为您定义的每个路径路径提供index.html文件." 每个服务器软件的详细方法都在[Angular Wiki中使用`html5Mode`](https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your -server-to-work-with-html5mode),或者参考Thierry为Firebase配置提供的linke. (2认同)

Fra*_* Yu 103

对于真正想要PathLocationStrategy(例如html5Mode)的人(比如我)HashLocationStrategy,请参阅如何:配置您的服务器以使用来自第三方wiki的html5Mode:

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

在这里我只复制wiki中的三个例子,万一Wiki丢失了.通过搜索关键字"URL重写"(例如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>
Run Code Online (Sandbox Code Playgroud)

重写模块的文档

nginx的

server {
    server_name my-app;

    root /path/to/app;

    location / {
        try_files $uri $uri/ /index.html;
    }
}
Run Code Online (Sandbox Code Playgroud)

文档 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>
Run Code Online (Sandbox Code Playgroud)

  • 我认为这个答案是正确的,它保留了 Angular 的 HTML5 特性并使服务器正常运行。 (4认同)
  • @Playnox 这里提到的所有内容也适用于 Angular 2 到 4。(实际上我从 2 开始就没有开始使用 Angular。)您可能已经通过 Angular-UI wiki 的链接跳到了结论,其中代码示例是 AngularJS。 (3认同)
  • 由于错误的指控,我被否决了。好吧,至少有一些反馈...... (3认同)

小智 24

我有同样的问题.我的Angular应用程序在Windows服务器上运行.

我通过在目录中创建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>
Run Code Online (Sandbox Code Playgroud)

  • 这很好但看起来你可能在这里找到了:http://jasonwatmore.com/post/2016/07/26/angularjs-enable-html5-mode-page-refresh-without-404-errors-in-nodejs -and-iis如果是这样的话,你至少应该给予那个家伙信用. (7认同)

Niy*_*yaz 20

也许您可以在使用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 {}
Run Code Online (Sandbox Code Playgroud)

  • 如果您只想快速完成某项工作,这是最简单的方法.然而,anuglar.io建议反对它"坚持默认,除非你有令人信服的理由采用哈希路线." https://angular.io/docs/ts/latest/guide/router.html (3认同)

Koe*_*uck 6

对于使用Angular 2 rc4或更高版本的人来说,看起来LocationStrategy已经从路由器转移到了普通路由器.你必须从那里导入它.

另请注意'provide'行周围的花括号.

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}
]);
Run Code Online (Sandbox Code Playgroud)


Sta*_*ser 5

如果您在Visual Studio 2015中通​​过ASP.NET Core 1运行Angular 2,您可能会发现JürgenGutsch的此解决方案很有帮助.他在一篇博文中描述了这一点.这对我来说是最好的解决方案.在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();
    }
});
Run Code Online (Sandbox Code Playgroud)