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

问题描述 投票:0回答:7

我已将单页应用程序存储在服务器中名为“myapp”的文件夹中。我已将库中的 URL 更改为 http://example.com/myapp/`.

我的项目有两个页面。所以我实现了 Angular 2 路由。我将默认页面设置为登录。当我在浏览器中输入

http://example.com/myapp/
时,它会自动重定向到
http://example.com/myapp/login
。但如果刷新该页面,我会收到
404
错误,指出未找到
http://example.com/myapp/login

但是如果我使用精简版服务器运行我的项目,一切都会正常。在这种情况下,index.html 中的基本 URL 将为

"/"
。怎么解决?

angular angular2-routing
7个回答
294
投票

更新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 文档

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

181
投票

对于真正想要

PathLocationStrategy
(即 html5Mode)而不是
HashLocationStrategy
的人(比如我),请参阅第三方 wiki 中的 如何:配置您的服务器以使用 html5Mode

启用 html5Mode 后,URL 中将不再使用

#
字符。
#
符号很有用,因为它不需要服务器端配置。没有
#
,URL 看起来更好,但它也需要服务器端重写。

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

Apache(根目录下文件名为.htaccess)

<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(文件名为根目录下的web.config)

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

155
投票

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

希望对您有帮助, 蒂埃里


37
投票

我也有同样的问题。我的 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>

32
投票

也许您可以在使用

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

8
投票

对于使用 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
投票

如果您在 Visual Studio 2015 中通过 ASP.NET Core 1 运行 Angular 2,您可能会发现 Jürgen Gutsch 提供的此解决方案很有帮助。他在博客文章中描述了这一点。这对我来说是最好的解决方案。将下面提供的 C# 代码放置在 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(); } });
    
© www.soinside.com 2019 - 2024. All rights reserved.