首页 文章

Angular 2.0路由器无法重新加载浏览器

提问于
浏览
148

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

你能帮我弄清楚这个错误发生的原因吗?

29 回答

  • 1

    添加进口:

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

    在NgModule提供程序中,添加:

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

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

    部署在任何服务器中的应用程序将为页面提供可从任何外部应用程序访问的真实URL .

  • 1

    2017年7月11日:由于这是一个有问题但是使用Angular 2和Electron的问题linked,我会在这里添加我的解决方案 .

    我所要做的就是从index.html中删除 <base href="./"> ,Electron开始重新成功重新加载页面 .

  • 0

    我检查了角2种子怎么样有用 .

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

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

  • 1

    如果您希望能够在浏览器中输入URL而不将AppServer配置为处理对index.html的所有请求,则必须使用 HashLocationStrategy .

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

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

    代替:

    RouterModule.forRoot(routes)
    

    随着 HashLocationStrategy 你的网址会像:

    http://server:port/#/path
    
  • 0

    这不是正确的答案,但是在On-refresh上你可以通过牺牲404页面将所有死方的呼叫重定向到主页这是一个临时黑客只是在404.html文件上重播

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

    免责声明:此修复程序适用于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,当您刷新时,它将在适当的位置重新加载 .

    希望有所帮助!

  • 0

    如果您使用默认的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

    我想在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>
    
  • 0

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

    @NgModule(
    {
      imports:[RouterModule.forRoot(appRoutes,{useHash:true})]
    })
    
  • 5
    you can use this solution for mean application
    
    i used ejs as view engine
    
     // 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');
    });
    
    and also set in angular- cli .json
    "apps": [
        {
          "root": "src",
          "outDir": "views",
    
    it will work fine instead of 
    
     app.get('*', function (req, res, next) {
        res.sendFile('dist/index.html', { root: __dirname });
     });
    
    its creating issue with get db calls and returning index.html
    
  • 38

    答案非常棘手 . 如果您使用普通的旧Apache服务器(或IIS),则会出现问题,因为Angular页面不存在真实存在 . 它们是从Angular路线“计算”出来的 .

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

    这里有一个增强的方法(基于404技巧) . 我假设您有一个"distributed"版本的角度应用程序(如果您使用Angular-CLI,则为 ng build --prod )并且您直接使用服务器访问页面并启用了PHP .

    如果您的网站基于页面(例如Wordpress)并且您只有一个专门用于Angular的文件夹(在我的示例中名为"dist"),您可以做一些奇怪的事情,但最后,简单 . 我假设你已经将你的Angular页面存储在"/dist"中(根据 <BASE HREF="/dist/"> ) . 现在使用404重定向和PHP的帮助 .

    在您的Apache配置中(或在角度应用程序目录的 .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应用程序(我认为将来会是这种情况) .

    笔记:

    • 尝试对 mod_redirect (通过重写URL)做同样的事情根本不是一个好的解决方案,因为文件(如资产)必须真正加载然后它比使用"not found"解决方案风险更大 .

    • 只是使用 ErrorDocument 404 /dist/index.html 重定向工作,但Apache仍然响应404错误代码(这对爬虫不好) .

  • 12

    我修复了这个(使用Java / Spring后端),添加了一个处理程序,该处理程序匹配我的Angular路由中定义的所有内容,它们发回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";
        }
    }
    
  • 126

    我使用webpack-dev-server时遇到了同样的问题 . 我不得不将devServer选项添加到我的webpack中 .

    解决方案:

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

    你可以在下面试试 . 这个对我有用!

    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

  • 0

    只需在root 4解析404中添加 .htaccess ,同时在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>
    
  • 0

    This is not a permanent Fix for the problem but more like a workaround or hack

    将Angular App部署到gh-pages时,我遇到了同样的问题 . 首先,当我在gh-pages上刷新页面时,我收到了404条消息 .

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

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

    我开始研究这个问题并且发现了一个博客 . 我试过给它一个镜头,它工作 .

    这就是我在博客中所提到的 .

    您需要首先在您的gh-pages repo中添加一个404.html文件,其中包含一个空的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 Organization站点,请不要在内容属性替换器文本中放置repo名称,只需执行以下操作:content =“0; URL ='/'”为了捕获和恢复用户最初的URL导航到,您需要在页面的当前状态上执行任何其他JavaScript操作之前,将以下脚本标记添加到index.html页面的头部:

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

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

    参考backalleycoder感谢@Daniel的解决方法 .

    现在上面的URL更改为https://rahulrsingh09.github.io/AngularConcepts/faq

  • 18

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

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

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

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

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

  • 4

    如果您使用Apache或Nginx作为服务器,则必须创建 .htaccess (如果之前未创建)和"On" RewriteEngine

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

    解决“路由器 - 不重新加载 - 浏览器”的最佳解决方案是我们应该使用spa-fall . 如果您正在使用带有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" });
            });
    
  • 7

    默认情况下,Angular使用HTML5 pushstate(Angular slang中的 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 使用

    update for >= RC.5 and 2.0.0 final

    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="/">
    

    update for >= 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';
    

    update for >= 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';
    

    < beta.16

    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-26破坏性变化

  • 0

    西蒙的回答对我来说是对的 . 我添加了这段代码:

    app.get('*', function(req, res, next) {
      res.sendfile("dist/index.html");
    });
    
  • 0

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

    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>
    

    No matter what server you are using, I think the whole point is finding out the ways to config the server to redirect 404 to your index.html.

  • 58

    Angular应用程序是使用简单的静态HTML服务器的理想选择 . 您不需要服务器端引擎来动态组合应用程序页面,因为Angular在客户端执行此操作 .

    如果应用程序使用Angular路由器,那么必须将服务器配置为在被要求输入它没有的文件时返回应用程序的主机页面(index.html) .

    路由应用程序应支持"deep links" . 深层链接是一个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

    If this issue occurred in production, follow below steps

    1)在角度应用程序的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文件夹中的文件可以通过任何模式进行部署 .

  • 3

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

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

  • -3

    您看到的错误是因为您要求http:// localhost / route不存在 . 据西蒙说 .

    使用html5路由时,您需要在服务器端 map all routes in your app(currently 404) to index.html . 以下是一些选项:

    $live-server --entry-file=index.html

    error_page 404 /index.html

    • Tomcat - web.xml的配置 . 从Kunin的评论

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

  • 2

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

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

    1) Put below code in web.xml of your deployment folder :

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

    2) You can also try using HashLocationStrategy with # in the URL for routes :

    尝试使用:

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

    代替:

    RouterModule.forRoot(路由)

    使用HashLocationStrategy你的网址将是:

    http://localhost/#/route

    3) Tomcat URL Rewrite Valve : Re-write the url's using a server level configuration to redirect to index.html if the resource is not found.

    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]
    
  • 1

    对于我们这些在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文件 .

  • 2

    如果要使用PathLocationStrategy:

    • Wildfly配置:

    • 创建要放在WEB-INF中的undertow-handlers.conf文件

    • 内容:(排除您的休息终点!)

    • regex ['( . / overview /? . ?$)'] and not regex['(./ endpoints . )'] -> rewrite[' /index.html']

    • regex ['(./ deployments /? . ?$)'] and not regex['(./ endpoints . )'] -> rewrite[' /index.html']

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

  • 0

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

    <base href="/">
    

    Angular2 Routing & Navigation文档中的Example使用头部中的以下代码(它们解释了为什么在文档的实例示例中):

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

    刷新页面时,这将动态地将基本href设置为当前document.location . 我可以看到这导致一些混淆,人们浏览文档并试图复制plunker .

相关问题