【问题标题】:Angular 2.0 router not working on reloading the browserAngular 2.0 路由器无法重新加载浏览器
【发布时间】:2015-10-03 14:06:13
【问题描述】:

我使用的是 Angular 2.0.0-alpha.30 版本。当重定向到不同的路由,然后刷新浏览器,显示Cannot GET /route。

你能帮我弄清楚为什么会发生这个错误吗?

【问题讨论】:

  • 感谢您的回复,但该回复适用于 Angular 1.x 版本。我在 Angular 2.0 中遇到了这个问题。
  • Angular 2.0 使用了全新的路由器,因此链接的帖子现在没有用了,因为它是旧路由器
  • 正如我所说,如果它是 pushState 问题,它不是 Angular 特定的,不能由 Angular 修复,而是需要在服务器上修复。
  • 需要一些服务器配置,查看这篇文章了解更多详细信息(在下面添加答案)。不建议切换到哈希定位策略blog.angular-university.io/angular2-router

标签: angular angular2-routing


【解决方案1】:

您看到的错误是因为您请求的 http://localhost/route 不存在。根据Simon.

使用 html5 路由时,您需要将应用中的所有路由(当前为 404)映射到服务器端的 index.html。以下是一些供您选择的选项:

  1. 使用实时服务器:https://www.npmjs.com/package/live-server

    $live-server --entry-file=index.html`
    
  2. 使用 nginx:http://nginx.org/en/docs/beginners_guide.html

    error_page 404 /index.html
    
  3. Tomcat - web.xml 的配置。来自Kunin的评论

    <error-page>
          <error-code>404</error-code>
          <location>/index.html</location>
    </error-page>
    

【讨论】:

  • 因为需要服务器端支持 html5 路由,所以效果很好。谢谢
  • 我可以使用 nginx 作为pub serve 的代理吗?这样我在开发过程中就不需要pub build 很多。我试过了,但proxy_pass 不能很好地与error_page 配合使用。
  • 使用 nginx。 , error_page 404 /index.html 在应用程序的位置为我工作。谢谢。
  • Tomcat - web.xml 的配置 404/index.html
  • @AKunin 这个 tomcat 配置不适用于 tomcat 9 吗?我在 tomcat 9 中尝试过同样的方法,但它不起作用
【解决方案2】:

免责声明:此修复适用于 Alpha44

我遇到了同样的问题,并通过实现 Angular.io API 预览中列出的 HashLocationStrategy 解决了它。

https://angular.io/docs/ts/latest/api/common/index/HashLocationStrategy-class.html

从导入必要的指令开始

import {provide} from 'angular2/angular2';
import {
  ROUTER_PROVIDERS,
  LocationStrategy,
  HashLocationStrategy
} from 'angular2/router';

最后,像这样将它们引导在一起

bootstrap(AppCmp, [
  ROUTER_PROVIDERS,
  provide(LocationStrategy, {useClass: HashLocationStrategy})
]);

您的路线将显示为http://localhost/#/route,当您刷新时,它会在适当的位置重新加载。

希望有帮助!

【讨论】:

  • 此代码可以正常工作,但此技术存在一些问题,使用此# 将自动添加到 URL 中。有什么解决方案可以使用这个从 URL 中删除 # 吗?
  • 同意,我尝试实施here 列出的“PathLocationStrategy”,但无法使其工作。没有# 的 URL 将是最佳的。
  • 是的,我也尝试过使用PathLocationStrategy,但这对我不起作用。要么我使用了错误的方法,要么我不知道如何使用 PathLocationStrategy。
  • 这在 RC1 中对我不起作用。从“@angular/router”导入 LocationStrategy、HashLocationStrategy 失败。
  • 很抱歉在 1 年多之后回到这个问题 :) 但是 HashLocationStrategy 是否有助于保持在相同的路由器路径上?在我的情况下,当我刷新时,它会将我带到localhost/#/<default route>,即主页的默认路由。当我“刷新”时,如何前往我最初所在的当前路线?
【解决方案3】:

Angular 默认使用 HTML5 推送状态(Angular 俚语中的PathLocationStrategy)。
您要么需要一个服务器来处理所有请求,就像它请求 index.html 一样,要么切换到 HashLocationStrategy(在路由的 URL 中带有 #)https://angular.io/docs/ts/latest/api/common/index/HashLocationStrategy-class.html

另见https://ngmilk.rocks/2015/03/09/angularjs-html5-mode-or-pretty-urls-on-apache-using-htaccess/

要切换到HashLocationStrategy,请使用

更新 >= RC.5 和 2.0.0 最终版

import {HashLocationStrategy, LocationStrategy} from '@angular/common';

@NgModule({
  declarations: [AppCmp], 
  bootstrap: [AppCmp],
  imports: [BrowserModule, routes],
  providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]
]);

useHash 或更短

imports: [RouterModule.forRoot(ROUTER_CONFIG, {useHash: true}), ...

确保您拥有所有必需的导入

对于新的(RC.3)路由器

<base href="."> 

也可能导致 404。

需要

<base href="/">

更新 >= RC.x

bootstrap(AppCmp, [
  ROUTER_PROVIDERS,
  provide(LocationStrategy, {useClass: HashLocationStrategy})
  // or since RC.2
  {provide: LocationStrategy, useClass: HashLocationStrategy} 
]);

import {provide} from '@angular/core';
import {  
  PlatformLocation,  
  Location,  
  LocationStrategy,  
  HashLocationStrategy,  
  PathLocationStrategy,  
  APP_BASE_HREF}  
from '@angular/common';  

更新为 >= beta.16 导入已更改

import {BrowserPlatformLocation} from '@angular/platform-browser';

import {provide} from 'angular2/core';
import {
  // PlatformLocation,
  // Location,
  LocationStrategy,
  HashLocationStrategy,
  // PathLocationStrategy,
  APP_BASE_HREF}
from 'angular2/router';
import {BrowserPlatformLocation} from 'angular2/src/router/location/browser_platform_location';

import {provide} from 'angular2/core';
import {
  HashLocationStrategy
  LocationStrategy,
  ROUTER_PROVIDERS,
} from 'angular2/router';

另见https://github.com/angular/angular/blob/master/CHANGELOG.md#200-beta16-2016-04-26break-changes

【讨论】:

  • 谢谢!提供似乎已移至 angular/core: import {provide} from 'angular2/core'
  • 请注意:update for &gt;= RC.x (RC.2) 与 router 3.0.0-alpha.7 一起使用,但 provide 被注释为已弃用,而没有关于哪个函数替换它的信息。
  • 使用{provide: SomeClass, useClass: OtherClass}
  • 最新答案。对于 angular 2.4.1 的最新版本,我有 。更改为 解决了我遇到的问题。可能对某人有帮助。
【解决方案4】:

我认为您看到的错误是因为您请求的 http://localhost/route 不存在。您需要确保您的服务器将所有请求映射到您的主 index.html 页面。

由于 Angular 2 默认使用 html5 路由,而不是在 url 末尾使用哈希,因此刷新页面看起来像是对不同资源的请求。

【讨论】:

  • 那么我们该如何解决呢?我们如何默认将所有请求映射到主索引?它依赖于服务器吗?
  • 是的,您可以在服务器上使用您使用的任何 Web 框架执行此操作。另一种方法是使用 HashLocationStrategy,如下所述。
  • 您将在每条不存在的路线中重新加载角度 SPA。是不是应该怎么处理?
  • 只有当用户在浏览器上点击刷新时才会重新加载,而不是当用户通过 UI 更改路由时。当用户刷新时,没有任何方法可以重新加载。
【解决方案5】:

如果您使用默认的 HTML 定位策略,这在所有路由器版本中都很常见。

浏览器栏上的 URL 是正常的完整 HTML url,例如:http://localhost/route

因此,当我们在浏览器栏中按 Enter 时,会向服务器发送一个实际的 HTTP 请求,以获取名为 route 的文件。

服务器没有这个文件,服务器上也没有配置express之类的东西来处理请求并提供响应,所以服务器返回404 Not Found,因为它找不到route文件。

我们希望服务器返回包含单页应用程序的index.html 文件。然后路由器应该启动并处理/route url并显示映射到它的组件。

因此,要解决此问题,我们需要将服务器配置为在无法处理请求的情况下返回 index.html(假设这是您的单页应用程序文件的名称),而不是 404 Not Found。

执行此操作的方式取决于所使用的服务器端技术。如果它的 Java 例如你可能必须编写一个 servlet,在 Rails 中它会有所不同,等等。

举个具体的例子,例如,如果你使用 NodeJs,你将不得不编写这样的中间件:

function sendSpaFileIfUnmatched(req,res) {
    res.sendFile("index.html", { root: '.' });
}

然后在中间件链的最末端注册:

app.use(sendSpaFileIfUnmatched);

这将服务index.html 而不是返回 404,路由器将启动,一切都会按预期工作。

【讨论】:

【解决方案6】:

确保将其放置在 index.html 的 head 元素中:

<base href="/">

Angular2 Routing & Navigation 文档中的 Example 在头部使用了以下代码(他们在文档的实时示例注释中解释了原因):

<script>document.write('<base href="' + document.location + '" />');</script>

当您刷新页面时,这会将基本 href 动态设置为您当前的 document.location。我可以看到这会给浏览文档并试图复制 plunker 的人造成一些混乱。

【讨论】:

  • 感谢分享。让我们明确一点,它仅在我将 加载到 中的所有 css 之后,并且在加载 ANY Js 文件之前直接对我有用。我希望它可以帮助任何人
  • 我在 index.html 中有 然后删除了 '.'来自href,它起作用了..
【解决方案7】:

如果您希望能够在浏览器中输入 url 而无需配置您的 AppServer 来处理对 index.html 的所有请求,您必须使用 HashLocationStrategy

最简单的配置方法是使用:

RouterModule.forRoot(routes, { useHash: true })

代替:

RouterModule.forRoot(routes)

使用 HashLocationStrategy 你的网址会是这样的:

http://server:port/#/path

【讨论】:

  • 谢谢!这有帮助,但我不希望来自 url 的 #,我们可以删除它吗?
【解决方案8】:

我在使用 webpack-dev-server 时遇到了同样的问题。我必须将 devServer 选项添加到我的 webpack。

解决方案:

// in webpack
devServer: {
    historyApiFallback: true,
    stats: 'minimal'
}

【讨论】:

【解决方案9】:

如果您使用 Apache 或 Nginx 作为服务器,您必须创建一个 .htaccess(如果之前没有创建)和“开启”RewriteEngine

RewriteEngine On  
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html

【讨论】:

  • 没有得到你的问题,这个方法在 Apache 和 Nginx (nginx.com)服务器上测试过
  • 这仅适用于 Apache; Nginx 配置格式完全不同。
【解决方案10】:

我的服务器是 Apache,我在刷新或深度链接时修复 404 的操作非常简单。只需在 apache vhost 配置中添加一行:

ErrorDocument 404 /index.html

这样任何 404 错误都会被重定向到 index.html,这正是 angular2 路由想要的。

整个 vhost 文件示例:

<VirtualHost *:80>
  ServerName fenz.niwa.local
  DirectoryIndex index.html
  ErrorDocument 404 /index.html

  DocumentRoot "/Users/zhoum/Documents/workspace/fire/fire_service/dist"
  ErrorLog /Users/zhoum/Documents/workspace/fire/fire_service/logs/fenz.error.log
  CustomLog /Users/zhoum/Documents/workspace/fire/fire_service/logs/fenz.access.log combined

  <Directory "/Users/zhoum/Documents/workspace/fire/fire_service/dist">
    AllowOverride All
    Options Indexes FollowSymLinks
    #Order allow,deny
    #Allow from All
    Require all granted
  </Directory>

  Header set Access-Control-Allow-Origin "*"
  Header set Access-Control-Allow-Methods "GET, POST"
  Header set Access-Control-Allow-Credentials "true"
  Header set Access-Control-Allow-Headers "Accept-Encoding"
</VirtualHost>

无论您使用什么服务器,我认为重点在于找出配置服务器以将 404 重定向到您的 index.html 的方法。

【讨论】:

    【解决方案11】:

    我认为服务器配置不是 SPA 的解决方案。如果出现错误的路线,您不想再次重新加载角度 SPA,对吗?所以我不会依赖服务器路由并重定向到其他路由,但是是的,我会让 index.html 处理对角度应用路径的角度路由的所有请求。

    试试这个,而不是其他或错误的路线。它对我有用,不确定,但似乎正在进行中。遇到问题时自己偶然发现。

    @RouteConfig([
      { path: '/**', redirectTo: ['MycmpnameCmp'] }, 
       ...
      }
    ])
    

    https://github.com/angular/angular/issues/4055

    但是,请记住配置您的服务器文件夹和访问权限,以防您拥有非 SPA 的 HTML 或 Web 脚本。否则你将面临问题。对我来说,当遇到像你这样的问题时,它是服务器配置及以上配置的混合。

    【讨论】:

      【解决方案12】:

      对于 Angular 5 快速修复,编辑 app.module.ts 并在 appRoutes 后添加 {useHash:true}

      @NgModule(
      {
        imports:[RouterModule.forRoot(appRoutes,{useHash:true})]
      })
      

      【讨论】:

        【解决方案13】:

        Angular 应用程序非常适合使用简单的静态 HTML 服务器进行服务。您不需要服务器端引擎来动态组合应用程序页面,因为 Angular 是在客户端完成的。

        如果应用程序使用 Angular 路由器,您必须将服务器配置为在请求提供它没有的文件时返回应用程序的主机页面 (index.html)。

        路由应用程序应支持“深层链接”。深层链接是一个 URL,它指定应用程序内部组件的路径。例如,http://www.example.com/heroes/42 是指向英雄详情页面的深层链接,该页面显示 id 为 42 的英雄。

        当用户从正在运行的客户端导航到该 URL 时没有问题。 Angular 路由器解释 URL 并路由到该页面和英雄。

        但是单击电子邮件中的链接,在浏览器地址栏中输入链接,或者只是在英雄详细信息页面上刷新浏览器——所有这些操作都由浏览器本身在正在运行的应用程序之外处理。浏览器绕过路由器直接向服务器请求该 URL。

        当静态服务器收到http://www.example.com/ 的请求时,它通常会返回 index.html。但它拒绝 http://www.example.com/heroes/42 并返回 404 - Not Found 错误,除非它被配置为返回 index.html

        如果在生产中出现此问题,请按照以下步骤操作

        1) 在 Angular 应用程序的 src 文件夹中添加一个 Web.Config 文件。将以下代码放入其中。

        <configuration>
        <system.webServer>
        <rewrite>
            <rules>
            <rule name="Angular Routes" 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>
        

        2) 在 angular-cli.json 中添加对它的引用。在 angular-cli.json 中将 Web.config 放入 assets 块中,如下所示。

        "assets": [
            "assets",
            "favicon.ico",
            "Web.config"
          ],
        

        3) 现在您可以使用

        构建生产解决方案
        ng build --prod
        

        这将创建一个 dist 文件夹。 dist 文件夹中的文件可以通过任何模式进行部署。

        【讨论】:

        • 最佳解决方案,可以从 angular:angular.io/guide/deployment#fallback 找到详细信息,在创建 web.config 文件时不要忘记添加 标签。感谢马拉泰什的回答。
        • 不工作,我用了 1. HashLocationStrategy 2. htaac​​ess 3. web.config。请提出任何其他解决方案。
        【解决方案14】:

        您可以将此解决方案用于平均应用程序,我使用 ejs 作为视图引擎:

        // view engine setup
        app.set('views', path.join(__dirname, 'views'));
        app.set('view engine', 'ejs');
        app.engine('html', require('ejs').renderFile);
        app.use(function (req, res, next) {
            return res.render('index.html');
        });
        

        并在 angular-cli.json 中设置

        "apps": [
            {
              "root": "src",
              "outDir": "views",
        

        它会正常工作而不是

        app.get('*', function (req, res, next) {
            res.sendFile('dist/index.html', { root: __dirname });
         });
        

        get db 调用和返回 index.html 的创建问题

        【讨论】:

        • 这在 2017 年 10 月完美适用于 MEAN 堆栈应用程序。
        【解决方案15】:

        对于我们这些在 IIS 中苦苦挣扎的人:使用以下 PowerShell 代码根据官方 Angular 2 文档解决此问题(有人在此线程中发布?http://blog.angular-university.io/angular2-router/

        Import-WebAdministration
        # Grab the 404 handler and update it to redirect to index.html.
        $redirect = Get-WebConfiguration -filter "/system.WebServer/httperrors/error[@statusCode='404']" -PSPath IIS:\Sites\LIS 
        $redirect.path = "/index.html"
        $redirect.responseMode = 1
        # shove the updated config back into IIS
        Set-WebConfiguration -filter "/system.WebServer/httperrors/error[@statusCode='404']" -PSPath IIS:\Sites\LIS -value $redirect
        

        根据 Angular 2 文档(上面的链接)中的建议,这会将 404 重定向到 /index.html 文件。

        【讨论】:

          【解决方案16】:

          您可以在下面尝试。它对我有用!

          main.component.ts

          import { Component, OnInit } from '@angular/core';
          import { Router } from '@angular/router';
          
          ...
          export class MainComponent implements OnInit {
              constructor(private router: Router) {
                  let path: string = window.location.hash;
                  if (path && path.length > 0) {
                      this.router.navigate([path.substr(2)]);
                  }
              }
          
              public ngOnInit() { }
          }
          

          您可以进一步增强 path.substr(2) 以拆分为路由器参数。我正在使用角度 2.4.9

          【讨论】:

          • 这对处理浏览器刷新很有帮助!对于 angular 5,我不得不对其进行一些修改以使用 window.location.pathname,并将该值与预期路径进行比较。
          【解决方案17】:

          我只是在根目录中添加 .htaccess。

          <IfModule mod_rewrite.c>
              RewriteEngine On
              RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
              RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
              RewriteRule ^ - [L]
              RewriteRule ^ ./index.html
          </IfModule>
          

          这里我只是将 /index.html 中的点“.”(父目录)添加到 ./index.html
          确保基本路径中的 index.html 文件是主目录路径并在项目构建中设置。

          【讨论】:

            【解决方案18】:

            我想在 HTML5 模式下保留子页面的 URL 路径,而不需要重定向回索引,并且没有一个解决方案告诉我如何做到这一点,所以我就是这样做的:

            在 IIS 中为所有路由创建简单的虚拟目录,并将它们指向应用根目录。

            使用此位置标记将您的 system.webServer 包装在您的 Web.config.xml 中,否则您将在使用虚拟目录第二次加载 Web.config 时得到重复的错误:

            <configuration>
                <location path="." inheritInChildApplications="false">
                <system.webServer>
                    <defaultDocument enabled="true">
                        <files>
                            <add value="index.html" />
                        </files>
                    </defaultDocument>
                </system.webServer>
              </location>
            </configuration>
            

            【讨论】:

              【解决方案19】:

              我检查了 Angular 2 种子的工作原理。

              您可以使用express-history-api-fallback 在页面重新加载时自动重定向。

              我认为这是解决这个 IMO 问题的最优雅的方法。

              【讨论】:

                【解决方案20】:

                如果你想使用 PathLocationStrategy :

                • 野蝇配置:
                  • 创建要放置在 WEB-INF 中的 undertow-handlers.conf 文件
                  • 内容:(不包括您的休息端点!)
                    • regex['(./overview/?.?$)'] 而不是 regex['(./endpoints.)'] -> rewrite[' /index.html']
                    • regex['(./deployments/?.?$)'] 而不是 regex['(./endpoints.)'] -> rewrite[' /index.html']

                Single page application with Java EE/Wildfly: server-side configuration

                【讨论】:

                  【解决方案21】:

                  2017 年 7 月 11 日:由于这是 linked 来自有此问题但使用 Angular 2 和 Electron 的问题,我将在此处添加我的解决方案。

                  我所要做的就是从我的 index.html 中删除 &lt;base href="./"&gt;,然后 Electron 开始再次成功地重新加载页面。

                  【讨论】:

                    【解决方案22】:

                    添加导入:

                    import { HashLocationStrategy, LocationStrategy } from '@angular/common';
                    

                    在 NgModule 提供者中,添加:

                    providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]
                    

                    在应用程序的主 index.html 文件中,将基本 href 从 / 更改为 ./index.html

                    应用程序部署在任何服务器上时,都会为页面提供一个真实的 url,可以从任何外部应用程序访问。

                    【讨论】:

                      【解决方案23】:

                      只需在根目录中添加 .htaccess 即可解析 404,同时在 Angular 4 apache2 中刷新页面。

                      <IfModule mod_rewrite.c>
                          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]
                      </IfModule>
                      

                      【讨论】:

                        【解决方案24】:

                        我认为您收到 404 是因为您请求的 http://localhost/route 在 tomcat 服务器上不存在。由于 Angular 2 默认使用 html 5 路由,而不是在 URL 末尾使用哈希,因此刷新页面看起来像是对不同资源的请求。

                        在 tomcat 上使用角度路由时,您需要确保服务器在刷新页面时将应用程序中的所有路由映射到主 index.html。有多种方法可以解决此问题。无论哪种适合您,您都可以选择。

                        1) 将以下代码放入部署文件夹的 web.xml 中:

                        <error-page>
                             <error-code>404</error-code>
                             <location>/index.html</location>
                        </error-page>
                        

                        2) 您也可以尝试在路由的 URL 中使用带有 # 的 HashLocationStrategy :

                        尝试使用:

                        RouterModule.forRoot(routes, { useHash: true })

                        代替:

                        RouterModule.forRoot(路由)

                        使用 HashLocationStrategy 你的网址会是这样的:

                        http://localhost/#/route

                        3) Tomcat URL Rewrite Valve:如果找不到资源,则使用服务器级配置重写 url 以重定向到 index.html。

                        3.1) 在 META-INF 文件夹中创建一个文件 context.xml 并在其中复制以下上下文。

                        <? xml version='1.0' encoding='utf-8'?>
                        <Context>
                          <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
                        </Context>
                        

                        3.2) 在WEB-INF中,创建rewrite.config文件(该文件包含URL重写规则,tomcat使用URL重写)。在 rewrite.config 中,复制以下内容:

                          RewriteCond %{SERVLET_PATH} !-f
                          RewriteRule ^/(.*)$ /index.html [L]
                        

                        【讨论】:

                          【解决方案25】:

                          可以使用定位策略,在路由文件中添加useHash: true

                          imports: [RouterModule.forRoot(routes, { useHash: true })]

                          【讨论】:

                            【解决方案26】:

                            这不是正确的答案,但是在刷新时,您可以通过牺牲 404 页面将所有无效调用重定向到主页,这是一个临时黑客,只需在 404.html 文件上重播即可

                            <!doctype html>
                            <html>
                                <head>
                                    <script type="text/javascript">
                                        window.location.href = "http://" + document.location.host;
                                    </script>
                                </head>
                            </html>
                            

                            【讨论】:

                              【解决方案27】:

                              解决“router-not-working-on-reloading-the-browser”的最佳解决方案是我们应该使用 spa-fall back。如果您正在使用带有 asp.net 核心的 angular2 应用程序,那么我们需要在“StartUp.cs”页面上定义它。在 MVC 路由下。我附上代码。

                               app.UseMvc(routes =>
                                      {
                                          routes.MapRoute(
                                              name: "default",
                                              template: "{controller=Home}/{action=Index}/{id?}");
                                          routes.MapSpaFallbackRoute("spa-fallback", new { controller = "Home", action = "Index" });
                                      });
                              

                              【讨论】:

                                【解决方案28】:

                                答案相当棘手。如果您使用普通的旧 Apache 服务器(或 IIS),您会遇到问题,因为 Angular 页面并不真实存在。它们是从 Angular 路由“计算”出来的。

                                有几种方法可以解决此问题。一种是使用 Angular 提供的HashLocationStrategy。但是在 URL 中添加了一个尖锐的符号。这主要是为了与 Angular 1 兼容(我假设)。事实上,尖后的部分不是 URL 的一部分(然后服务器解析“#”符号之前的部分)。这可以是完美的。

                                这里是一种增强的方法(基于 404 技巧)。我假设你有一个“分布式”版本的 Angular 应用程序(ng build --prod,如果你使用 Angular-CLI)并且你直接使用你的服务器访问页面并且启用了 PHP。

                                如果您的网站基于页面(例如 Wordpress),并且您只有一个专用于 Angular 的文件夹(在我的示例中名为“dist”),您可以做一些奇怪的事情,但最终很简单。我假设您已将 Angular 页面存储在“/dist”中(带有相应的&lt;BASE HREF="/dist/"&gt;)。现在使用 404 重定向和 PHP 的帮助。

                                在您的 Apache 配置中(或在您的 Angular 应用程序目录的 .htaccess 文件中),您必须添加 ErrorDocument 404 /404.php

                                404.php 将以以下代码开头:

                                <?php
                                $angular='/dist/';
                                if( substr($_SERVER['REQUEST_URI'], 0, strlen($angular)) == $angular ){
                                    $index = $_SERVER['DOCUMENT_ROOT'] . $angular . "index.html";
                                    http_response_code(200);
                                    include $index;
                                    die;
                                }
                                
                                // NOT ANGULAR...
                                echo "<h1>Not found.</h1>"
                                

                                其中$angular 是存储在您的角度index.html 的HREF 中的值。

                                原理很简单,如果Apache没有找到页面,就对PHP脚本进行404重定向。我们只检查页面是否在 Angular 应用程序目录中。如果是这种情况,我们只需直接加载 index.html(无需重定向):这是保持 URL 不变的必要条件。我们还将 HTTP 代码从 404 更改为 200(对爬虫更好)。

                                如果页面在 Angular 应用程序中不存在怎么办?好吧,我们使用 Angular 路由器的“包罗万象”(参见 Angular 路由器文档)。

                                此方法适用于基本网站内的嵌入式 Angular 应用程序(我认为将来会如此)。

                                注意事项:

                                • 尝试对mod_redirect 做同样的事情(通过重写 URL)根本不是一个好的解决方案,因为必须真正加载文件(如资产)然后它比仅使用“未找到”风险更大" 解决方案。
                                • 仅使用 ErrorDocument 404 /dist/index.html 进行重定向有效,但 Apache 仍然响应 404 错误代码(这对爬虫不利)。

                                【讨论】:

                                  【解决方案29】:

                                  这不是对问题的永久修复,而更像是一种解决方法或破解

                                  在将 Angular 应用程序部署到 gh-pages 时,我遇到了同样的问题。 首先,在 gh-pages 上刷新我的页面时,我收到了 404 条消息。

                                  然后正如@gunter 指出的那样,我开始使用 Angular 2 提供的HashLocationStrategy

                                  但这带来了它自己的一系列问题,网址中的# 真的很糟糕,让网址看起来像https://rahulrsingh09.github.io/AngularConcepts/#/faq 这样的怪异。

                                  我开始研究这个问题并发现了一个博客。我试过试一试,它奏效了。

                                  这是我在该博客中提到的。

                                  您需要首先将 404.html 文件添加到您的 gh-pages 存储库中 其中包含一个空的 HTML 文档 - 但您的文档 总长度必须超过 512 个字节(如下所述)。接下来放 在 404.html 页面的 head 元素中添加以下标记:

                                  <script>
                                    sessionStorage.redirect = location.href;
                                  </script>
                                  <meta http-equiv="refresh" content="0;URL='/REPO_NAME_HERE'"></meta>
                                  

                                  此代码将尝试的入口 URL 设置为 标准 sessionStorage 对象并立即重定向到您的 项目的 index.html 页面使用元刷新标签。如果你正在做一个 Github 组织站点,不要在内容中添加 repo 名称 属性替换文本,只需这样做: content="0;URL='/'"

                                  为了捕获和恢复用户最初导航的 URL 要,您需要将以下脚本标签添加到您的头部 index.html 页面在任何其他 JavaScript 作用于页面的当前 状态:

                                  <script>
                                    (function(){
                                      var redirect = sessionStorage.redirect;
                                      delete sessionStorage.redirect;
                                      if (redirect && redirect != location.href) {
                                        history.replaceState(null, null, redirect);
                                      }
                                    })();
                                  </script>
                                  

                                  这段 JavaScript 检索我们在 sessionStorage 中缓存的 URL 在 404.html 页面上,并将当前历史记录条目替换为 它。

                                  参考backalleycoder 感谢@Daniel 提供此解决方法。

                                  现在上面的网址变成https://rahulrsingh09.github.io/AngularConcepts/faq

                                  【讨论】:

                                    【解决方案30】:

                                    我通过添加一个与我的 Angular 路由中定义的所有内容相匹配的处理程序来解决此问题(使用 Java / Spring 后端),该处理程序发送回 index.html 而不是 404。然后有效地(重新)引导应用程序并加载正确的页。我还有一个 404 处理程序,用于处理任何没有被这个捕获的东西。

                                    @Controller         ////don't use RestController or it will just send back the string "index.html"
                                    public class Redirect {
                                    
                                        private static final Logger logger = LoggerFactory.getLogger(Redirect.class);
                                    
                                        @RequestMapping(value = {"comma", "sep", "list", "of", "routes"})
                                        public String redirectToIndex(HttpServletRequest request) {
                                            logger.warn("Redirect api called for URL {}. Sending index.html back instead. This will happen on a page refresh or reload when the page is on an Angular route", request.getRequestURL());
                                            return "/index.html";
                                        }
                                    }
                                    

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 2023-03-23
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2018-08-07
                                      • 1970-01-01
                                      • 2018-10-16
                                      • 2021-11-29
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多