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

Posted

技术标签:

【中文标题】Angular 2:当我通过浏览器刷新时出现 404 错误[重复]【英文标题】:Angular 2: 404 error occur when I refresh through the browser [duplicate] 【发布时间】:2016-05-19 00:30:47 【问题描述】:

我是 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 服务器运行我的项目,一切正常。在这种情况下,index.html 中的基本 URL 将是 "/"。如何解决?

【问题讨论】:

目前,我使用 Angular 9 应用程序并将其部署在带有 web.config 文件的 IIS 服务器上,当我们刷新页面时,它会正确加载 Angular 应用程序。我认为这不是角度应用程序的问题。但是当我将代码部署到 Ubuntu 服务器应用程序时,由于我们没有配置 URL 重写规则,所以出现 404 not found 错误。添加用于重写 URL 的 .htaccess 文件后,它可以在刷新时工作。 我在生产中遇到了同样的问题,在开发中很好。这个答案解决了这个问题:***.com/a/39103122/12603542,与useHash: true,我只需要弄清楚如何摆脱/#/ 【参考方案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
]);

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

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

希望对你有帮助 蒂埃里

【讨论】:

这解决了我的问题,非常感谢。但是,使用 HashBang 方法有什么缺点吗?我的意思是在 SEO 或其他方面? 如果我们不想使用 HashLocationStrategy 而使用 PathLocationStrategy 怎么办? @Ben 正如 Thierry 提到的,“如果您不想出现 404 错误,您需要更新您的服务器,以便为您定义的每个路由路径提供 index.html 文件。”各个服务器软件的详细方法在Angular Wiki about working with html5Mode,或者参考Thierry提供的链接进行Firebase配置。 下面的答案是 angular2 最终版本的更新 Franklin Yu 的答案实际上应该是公认的答案。 Thierry Templier 的回答只是说放回 # 以解决问题,这不是答案,或者使用提供的链接假设发布者使用的是 firebase,而发布者可能不是。 Franklin 提供的 wiki 回答了这些问题,并附带说明,对于 Apache,您可以在 .htaccess 文件中添加相同的配置。【参考方案2】:

对于阅读本文的使用 Angular 2 rc4 或更高版本的人来说,LocationStrategy 似乎已从路由器移至通用。您必须从那里导入它。

还要注意“提供”行周围的大括号。

ma​​in.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
]);

【讨论】:

【参考方案3】:

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

示例:(来自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  

【讨论】:

答案可能会根据受欢迎程度重新排列,因此不会保留相对定位。请在您的答案中提供指向其他答案的链接。 这对我有用。谢谢你。但是有没有办法丢失#? 是的,这也适用于我。但我使用 auth0 进行身份验证,我必须提供允许的 url。当我现在刷新添加哈希的页面时,然后登录它不会接受 url。刷新页面时有什么建议可以解决此问题或删除主题标签? 添加提供者这个答案的第一个解决方案(提供者:[provide:LocationStrategy,useClass:HashLocationStrategy],引导程序:[AppComponent],)DID WORK!万分感谢! /\! 使用 Angular 4.2.6 :)【参考方案4】:

也许您可以在使用RouterModule 注册您的root 时这样做。您可以传递具有属性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 

【讨论】:

如果您只想让某些东西快速运行,这是最简单的方法。但是,anuglar.io 建议不要“坚持使用默认值,除非您有令人信服的理由诉诸哈希路由。” angular.io/docs/ts/latest/guide/router.html 只是添加 useHash: true 解决了我的问题,谢谢!【参考方案5】:

如果您在 Visual Studio 2015 中通过 ASP.NET Core 1 运行 Angular 2,您可能会发现 Jürgen Gutsch 提供的这个解决方案很有帮助。他在a blog post 中对此进行了描述。这对我来说是最好的解决方案。将下面提供的 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();
    
);

【讨论】:

【参考方案6】:

对于真正想要 PathLocationStrategy(即 html5Mode)而不是 HashLocationStrategy 的人(如我),请参阅来自第三方 wiki 的 How to: Configure your server to work with html5Mode

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

这里我只复制 wiki 中的三个示例,以防 Wiki 丢失。其他示例可以通过搜索关键字“URL rewrite”找到(例如,this answer for 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>

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>

【讨论】:

本主题与 Angular 2(4) 相关 - 您的回复与 AngularJS 相关 @Playnox 这里提到的所有内容也适用于 Angular 2 到 4。(实际上我从 2 开始就没有开始使用 Angular。)您可能已经通过 Angular-UI wiki 的链接得出结论,其中代码示例是 AngularJS。 因为诬告,我被否决了。好吧,至少有一些反馈...... @FranklinYu 你见过 WebLogic 服务器的配置吗?没有运气。 这个答案在我看来是正确的,它保留了 Angular 的 HTML5 特性并使服务器正常运行。【参考方案7】:

我遇到了同样的问题。我的 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>

【讨论】:

@DaneVinson The Angular Wiki 甚至更早。无论如何,他可能应该给予某人信任。 在 WebApi 服务的情况下(对于服务器)。请注意,角度应用程序未放置在 WebApi 的同一文件夹中。您可以创建另一个文件夹,并更改 index.html 中的 href

以上是关于Angular 2:当我通过浏览器刷新时出现 404 错误[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用 Angular 7、NGINX 和 Docker 刷新页面时出现 404 错误

Angular 2 应用程序部署到 Azure 时出现错误 404

发出 HTTP 请求时出现跨域错误

通过 Angular JS $http.post 使用 slim 框架时出现 404 无效的 http 状态代码

当我尝试在 python 中创建浏览器时出现错误

在 JWT 刷新时出现 401 时重定向