【问题标题】:Angular 2 Routing Does Not Work When Deployed to Http ServerAngular 2 路由在部署到 Http 服务器时不起作用
【发布时间】:2017-09-18 00:05:53
【问题描述】:

我将开发一个简单的 Angular 2 应用程序。我使用 Angular CLI 创建了一个带有路由的项目,并使用“ng generate component”命令向应用程序添加了几个组件。然后我在 app-routing.module.ts 中指定路由如下。

从'@angular/core'导入{ NgModule };
从'@angular/router'导入{路由,RouterModule};
从'./home/home.component'导入{ HomeComponent };
从'./about/about.component'导入{ AboutComponent };
从'./user/user.component'导入{用户组件};
从'./error/error.component'导入{ErrorComponent};
从'./specialpage/specialpage.component'导入{ SpecialpageComponent };

常量路线:路线= [
  {
    小路: '',
    组件:HomeComponent
  },
  {
    路径:'关于',
    组件:关于组件
  },
    {
    路径:'用户',
    组件:用户组件
  },
  {
    路径:'特殊页面',
    组件:特殊页面组件
  },
  {
    小路: '**',
    组件:错误组件
  }

];

@NgModule({
  进口:[RouterModule.forRoot(routes)],
  出口:[路由器模块],
  提供者:[]
})
导出类 AppRoutingModule { }

app.module.ts如下。

从“@angular/platform-b​​rowser”导入 { BrowserModule }; 从'@angular/core'导入{ NgModule }; 从“@angular/forms”导入 { FormsModule }; 从“@angular/http”导入 { HttpModule }; 从'./app-routing.module'导入{AppRoutingModule}; 从'./app.component'导入{AppComponent}; 从'./home/home.component'导入{ HomeComponent }; 从'./about/about.component'导入{ AboutComponent }; 从'./error/error.component'导入{ErrorComponent}; 从'./user/user.component'导入{用户组件}; 从'./specialpage/specialpage.component'导入{ SpecialpageComponent }; @NgModule({ 声明:[ 应用组件, 家庭组件, 关于组件, 错误组件, 用户组件, 特殊页面组件 ], 进口:[ 浏览器模块, 表单模块, Http模块, 应用路由模块 ], 提供者:[], 引导程序:[AppComponent] }) 导出类 AppModule { }

我没有为其他组件添加任何修改。 然后我使用“ng serve”命令部署了应用程序,该应用程序可以正常使用链接。 例如:http://localhost:4200/about

但是当我在 http-server 中部署项目时,链接无法按预期工作。我使用“http-server ./dist”命令部署了应用程序,应用程序部署良好,但链接不起作用。当我转到“http://localhost:4200/about”时,会出现 404 错误。

我做错了吗?为什么“ng-serve”有效而“http-server”无效?

任何帮助将不胜感激。提前致谢。

我已将我的项目上传到github

【问题讨论】:

  • 试试imports: [RouterModule.forRoot(routes, {useHash: true})],。如果它以这种方式工作,您需要在生产服务器上启用 HTML5 pushState。
  • @GünterZöchbauer,我试过了,但没有成功
  • 是的,不要使用useHash:true :D。正如我在最初的评论中所说。您必须配置服务器以支持 HTML5 pushState。 useHash:true 只是为了调试问题的原因。
  • @GünterZöchbauer,感谢您提供有关此事的宝贵信息。我将尝试为此找到解决方案。再次感谢
  • 你找到解决办法了吗。我有同样的问题。

标签: angular npm angular2-routing angular-cli angular2-template


【解决方案1】:

它会发生,因为它会找到一个页面 about,它根本不存在因此 404。可能的选项:

  1. 如果您想使用 http-server,请使用代理,它将所有内容重定向到 http://localhost:your-port

    选项: -P--proxy 代理所有无法在本地解析到给定 url 的请求。例如:-P http://someurl.com

  2. 根本不要使用快递。使用 express 创建您自己的 http-server 并将所有内容重定向到 index.html

    假设 public 是你保存所有转译的东西的文件夹。

    var express = require('express');
    var app = express();
    
    var path = __dirname + '/public';
    var port = 8080;
    
    app.use(express.static(path));
    app.get('*', function(req, res) {
        res.sendFile(path + '/index.html');
    });
    app.listen(port);
    

【讨论】:

  • 很抱歉,我没有让你很好。我真的是 Angular 的新手。我在这里没有做任何复杂的事情。关于您的第一个选项,我尝试托管我的服务器并且我在没有端口的情况下访问了 URL。只有根 URL 有效。无法导航到其他链接。
【解决方案2】:
export const routes: Routes =[
   **{ path: '', redirectTo: '/', pathMatch: 'full'},**
     { path: 'about', component: AboutComponent},
     { path: 'user',  component: UserComponent},
     { path: 'specialpage',  component: SpecialpageComponent},
     { path: '**',  component: ErrorComponent}
    ];

查看blockquote的内容。 然后在 app.module.ts 中的 providers:[] 处给出“HttpModule”的名称

谢谢。

【讨论】:

【解决方案3】:

这个问题通过实现HashLocationStrategy 来解决,它将# 添加到你的所有路由中。您可以通过将HashLocationStrategy 添加到AppModule providers 来实现此目的。

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

并添加相应的导入

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

这将解决您的问题。

如果你不想使用HashLocationStrategy,你可以使用PathLocationStrategy,这样你的Angular应用就不会在URL中显示Hash。

【讨论】:

  • 我有同样的问题,我的 app.modules.ts 中也有这个问题。我没有收到任何 404 错误。在应用程序组件 init 方法之后,没有任何内容加载,就好像我的路线不起作用一样。 ng serve 工作正常,但我的本地主机不行..
  • 谢谢!帮助过我。但是在已部署的网站 url 中始终显示主题标签是否可以?嗯
  • @ninjaxlite 如果您不想在 URL 中显示 Hashtag,我更新了我的答案
  • 我觉得这不应该成为一件事。修复这个谷歌。改变整个互联网的结构来安抚我。
  • 这个。我已经尝试了各种方法让它在我的 nginx 和 IIS 上运行 - 无济于事。直到我遇到了这个。我们不是都希望 Angular 默认使用 HashLocationStrategy 吗?或者,更进一步,它甚至不应该是不使用它的选项?
【解决方案4】:

您可以在注册 RouterModule.forRoot 时执行此操作,您可以通过属性 {useHash: true} 传递第二个对象,如下所示:

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {AppComponent} from './app.component';
import {appRoutes} from './app.routes';

@NgModule({
   declarations: [AppComponent],
   imports: [BrowserModule],
   RouterModule.forRoot(appRoutes , {useHash: true})],
   providers: [],
   bootstrap: [AppComponent],
})
export class AppModule {}

【讨论】:

  • 我有同样的问题,但解决方案不起作用
  • 我也有同样的问题。 ng serve 效果很好,但是当我部署到本地时,localhost/ 不起作用
  • 测试的时候别忘了在你的url中使用hash,比如:127.0.0.1/#/home
【解决方案5】:

这是因为 http-server 不支持 fallback 像 lite-server 或 web pack-dev server。这就是它显示 404 not found 的原因。 有两种解决方案可以解决此问题:

  1. 您可以像上面提到的那样使用 HashLocationStrategy
  2. 如果您将其部署到 Apache 或 IIS 服务器,那么您可以简单地添加上面提到的配置 here!

注意:对于开发,您可以使用 lite-server。

希望这会对你有所帮助。

【讨论】:

    【解决方案6】:

    改变你的 index.html

    <base href="/">
     to 
    <base href="./">
    

    因为我们使用的是 Tomcat,所以我们提到了这个(。) 因为路由是基于this(/)所以和http-server一样

    我的意思是正常运行 ng serve 你只见过 http://localhost:4200/

    但是在服务器上运行你已经将你的构建放入(dist)的 webapps

    所以它来了

    http://localhost:8080/dist/
    

    所以你需要添加&lt;base href="./"&gt;

    我认为这是你可能解决的问题。

    【讨论】:

      【解决方案7】:

      在项目文件夹中创建 .htaccess 文件然后写入

      RewriteEngine On
      RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
      RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
      
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule ^ index.html [L]
      

      点击此链接: https://angular.io/guide/deployment

      【讨论】:

        【解决方案8】:

        对于 Apache 服务器:

        在生产服务器中

        在项目根目录中添加或创建“.htaccess”文件,如图所示为.htaccess文件添加重写规则

        RewriteEngine On
          # If an existing asset or directory is requested go to it as it is
          RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
          RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
          RewriteRule ^ - [L]
          # If the requested resource doesn't exist, use index.html
        RewriteRule ^ /index.html
        

        【讨论】:

          【解决方案9】:

          这样解决:

          案例 1:对于低于 Angular 5.1 的版本

          1) 使用 HashLocationStrategy,如下所述: 在 AppModule 中执行以下操作。

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

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

          案例 2:对于等于或高于 Angular 5.1 的版本

          2.1) Angular 引入了这个属性 onSameUrlNavigation 来克服服务器上的刷新问题。

          2.2) 将 onSameUrlNavigation 添加到 imports 数组 中的RouterModule.forRoot 中。

          a) 在Application主路由模块,即app.routing.module.ts / app.routing.ts添加属性

          见下文:

          @ngModule({
          
              imports: 
              [
                 RouterModule.forRoot(routes, {onSameUrlNavigation: ‘reload’})
              ],
          
              exports: [RouterModule],
           });
          

          希望对某人有所帮助。

          【讨论】:

            【解决方案10】:

            我已经通过在 AppModule Providers 中添加这个解决了这个问题:

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

            和导入

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

            然后我创建了 .htaccess:

            RewriteEngine On
            # If an existing asset or directory is requested go to it as it is
            RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
            RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
            RewriteRule ^ - [L]
            # If the requested resource doesn't exist, use index.html
            RewriteRule ^ /index.html
            

            如果没有 # 在 URL 中,一切都很好 :)

            【讨论】:

            • 我必须在哪里添加 .htaccess 文件?
            • @jaykhatri 在您的 Web 服务器上的主目录(Angular 应用程序所在的位置)中。可能是 public_html。
            【解决方案11】:

            对于 Apache 服务器

            • 创建文件名.htaccess
            • 编辑该文件并写入index.html 而不是index.php
            • 对于没有任何代码的人,可以将以下代码写入您的.htaccess文件中: RewriteEngine On # If an existing asset or directory is requested go to it as it is RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR] RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d RewriteRule ^ - [L] # If the requested resource doesn't exist, use index.html RewriteRule ^ /index.html

            • 此代码可能不适用于 SSL 证书 - 请联系您的托管服务提供商或访问 https://httpd.apache.org/docs/current/howto/htaccess.html 以参考文档。

            【讨论】:

              【解决方案12】:

              根据https://angular.io/guide/deployment 的文档(Apache,您也可以查找 nginx) 您需要使用 .htaccess 文件将服务器指向 index.html

              RewriteEngine On
              # If an existing asset or directory is requested go to it as it is
              RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
              RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
              RewriteRule ^ - [L]
              # If the requested resource doesn't exist, use index.html
              RewriteRule ^ /index.html
              

              【讨论】:

                【解决方案13】:

                如果您和我一样,根本不想更改代码,只需使用它即可:

                https://www.npmjs.com/package/angular-http-server

                【讨论】:

                  【解决方案14】:

                  您应该尝试从应用程序初始化的点开始指定构建中的 url:

                  Ng build --prod --base-href="http://your.url.com/subdirectory/etc"
                  

                  【讨论】:

                    【解决方案15】:

                    遇到此特定问题的确切原因是您的服务器设置。

                    因此,当您实施应用程序时,您必须采取某些步骤。 基本步骤之一是标记路径的特定部分说: http://domain-name/main 其中 ma​​in 作为路径段必须用作服务器设置中的标识符,例如您的 server.jsapp.js用于 IIS 和 Tomcat 部署的节点后端或 webconfig 文件。

                    标记特定段的原因是,当服务器接收到带有该特定段的任何请求+附加信息时,您将其重新路由到 www 或公共文件夹中的应用程序,以便角路由器启动。

                    这个过程称为url 重写。 因此,如果取决于应用程序大小的 Web 服务器或应用服务器不在您的控制范围内,请使用 hashLocationStratergy 否则使用 pathLocationStartergy 总是很整洁,因为它在以下情况下很有帮助涉及到历史跟踪以及其他美学和性能优势。

                    要了解更多信息,您可以访问以下链接:

                    对于 IIShttps://blog.angularindepth.com/deploy-an-angular-application-to-iis-60a0897742e7

                    【讨论】:

                      【解决方案16】:

                      在基本 href 字符串中添加一个点。

                      正确

                      <base href="./home">
                      

                      错误

                      <base href="/home">
                      

                      http://www.wisdomofjim.com/blog/solved-problems-with-resource-loading-failures-when-deploying-angular-2-webapps-live

                      【讨论】:

                        【解决方案17】:

                        我使用了精简服务器。

                        npm i -D  lite-server
                        

                        然后在我的 package.json 文件中:

                        "scripts": {
                           "ci:serve:employee-onboarding": "ng build --prod --project=employee-onboarding && lite-server -c lite-server-config.json"
                        }
                        

                        运行它:npm run ci:serve:employee-onboarding

                        我的 lite-server-config.json 文件看起来像这样

                        {
                          "port": 4201,
                          "server": { "baseDir": "dist/apps/employee-onboarding" }
                        }
                        

                        【讨论】:

                          【解决方案18】:

                          我也遇到了这个问题,找到了一个不需要HashLocationStrategy的解决方案。

                          问题是,像 tomcat 这样的服务器会查找 Angular 应用程序中不存在的实际文件夹(例如: /about ),作为其单页应用程序。所以每个请求都需要重定向到 index.html。

                          解决此问题的最简单方法是添加以下 java 类并覆盖 addResourceHandlers() 方法,如下所示:

                          @Configuration
                          class WebMVCCustomConfiguration implements WebMvcConfigurer {
                          
                          @Override
                          public void addResourceHandlers(ResourceHandlerRegistry registry) {
                              registry.addResourceHandler("/**").addResourceLocations("classpath:static").resourceChain(true)
                                      .addResolver(new PathResourceResolver() {
                                          @Override
                                          protected Resource getResource(String resourcePath, Resource location) {
                                              String path = "static/";
                                              path += (resourcePath.contains(".") && !resourcePath.equals("index.html")) ? resourcePath : "index.html";
                          
                                              Resource resource = new ClassPathResource(path);
                                              return resource.exists() ? resource : null;
                                          }
                                      });
                              }
                            }
                          

                          这将解决所有问题,并且此解决方案在任何地方都不存在。

                          【讨论】:

                          • 很高兴知道有这样的解决方案,但我认为最好使用 Angular 提供的机制,就像上面提到的那样 -> HashLocationStrategy。干杯:)
                          【解决方案19】:

                          如果你使用href,把它们改成routerlink。

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 2019-08-08
                            • 2022-12-15
                            • 2022-08-23
                            • 1970-01-01
                            • 1970-01-01
                            • 2017-03-03
                            • 2017-09-10
                            • 1970-01-01
                            相关资源
                            最近更新 更多