Angular 2.0路由器无法重新加载浏览器
我正在使用Angular 2.0.0-alpha.30版本。 当redirect到不同的路由时,然后刷新浏览器,显示无法获取/路由。
你能帮我找出这个错误发生的原因吗?
您所看到的错误是因为您正在请求不存在的http:// localhost / route 。 据西蒙说 。
当使用html5路由时,您需要将您应用中的所有路由(当前为404)映射到服务器端的index.html 。 以下是您的一些select:
- 使用live-server: https : //www.npmjs.com/package/live-server
$live-server --entry-file=index.html
- 使用nginx: http :
error_page 404 /index.html
免责声明:此修补程序与Alpha44一起使用
我遇到了同样的问题,并通过实现Angular.io API Preview中列出的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 ,当您刷新时,它将重新加载到适当的位置。
希望有所帮助!
Angular默认使用HTML5 pushstate(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 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}), ...
确保你有所有必需的import
对于新的(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.16import已更改
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破坏性变化;
我认为你所看到的错误是因为你正在请求不存在的http:// localhost / route 。 您需要确保您的服务器将所有请求映射到您的主要index.html页面。
由于Angular 2默认使用html5路由,而不是在url末尾使用散列,因此刷新页面看起来像是请求其他资源。
如果您使用的是默认的HTML位置策略,则这是所有路由器版本中的常见情况。
会发生什么事是浏览器栏上的URL是一个正常的完整的HTMLurl,例如: http://localhost/route
。
所以当我们在浏览器栏中点击Enter时,就会有一个实际的HTTP请求发送到服务器来获取一个名为route
的文件。
服务器没有这样的文件,服务器上没有configuration类似express的东西来处理请求并提供响应,所以服务器返回404 Not Found,因为找不到route
文件。
我们希望服务器返回包含单页面应用程序的index.html
文件。 然后,路由器应该启动并处理/route
url并显示映射到它的组件。
所以要解决这个问题,我们需要configuration服务器来返回index.html
(假设这是您的单页面应用程序文件的名称),以防万一请求无法处理,而不是404 Not Found。
这样做的方式将取决于所使用的服务器端技术。 如果它的Java,例如你可能不得不写一个servlet,在Rails中,它将是不同的,等等。
举一个具体的例子,如果你正在使用NodeJs,你将不得不写一个像这样的中间件:
function sendSpaFileIfUnmatched(req,res) { res.sendFile("index.html", { root: '.' }); }
然后在中间件链的最后注册它:
app.use(sendSpaFileIfUnmatched);
这将服务于index.html
而不是返回一个404,路由器将踢,一切都会按预期工作。
确保将它放置在index.html的head元素中:
<base href="/">
Angular2 路由和导航文档中的例子在头部使用了下面的代码(他们解释了为什么在文档的实例中):
<script>document.write('<base href="' + document.location + '" />');</script>
刷新页面时,会dynamic地将基础href设置为当前的document.location。 我可以看到这造成人们略读文档和试图复制重击者的一些混淆。
我有使用webpack-dev-server的同样的问题。 我不得不将devServer选项添加到我的webpack。
解:
// in webpack devServer: { historyApiFallback: true, stats: 'minimal' }
我的服务器是Apache,我刷新或深层链接时所做的修复404操作非常简单。 只需在apache vhost config中添加一行:
ErrorDocument 404 /index.html
所以任何404错误将被redirect到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>
无论您使用的服务器是什么,我认为整个过程就是find将服务器configuration为将404redirect到index.html的方法。
如果你使用Apache作为服务器,你必须创build一个.htaccess (如果以前没有创build)和“On”RewriteEngine
RewriteEngine On RewriteCond%{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR] RewriteCond%{DOCUMENT_ROOT}%{REQUEST_URI} -d 重写规则^ - [L] RewriteRule ^ /index.html
服务器configuration不是SPA的解决scheme,甚至我觉得。 如果出现错误的路线,你不想重新加载angular度SPA,是吗? 所以我不会依赖于服务器路由并redirect到其他路由,但是我会让index.html处理angular应用path的angular路由的所有请求。
试试这个,而不是别的或错误的路线。 它适用于我,不知道,但似乎正在进行中的工作。 遇到问题时自己碰到这个问题。
@RouteConfig([ { path: '/**', redirectTo: ['MycmpnameCmp'] }, ... } ])
https://github.com/angular/angular/issues/4055
但是请记得configuration您的服务器文件夹和访问权限,如果您有不是SPA的HTML或Web脚本。 否则你将面临问题。 对于像我这样的问题,这是一个服务器configuration和以上的混合。
如果您希望能够在浏览器中inputurl,而无需将您的AppServerconfiguration为处理对index.html的所有请求,则必须使用HashLocationStrategy 。
最简单的configuration方法是使用:
RouterModule.forRoot(routes, { useHash: true })
代替:
RouterModule.forRoot(routes)
随着HashLocationStrategy您的url会像:
http://server:port/#/path
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
对于我们这些在IIS中苦苦挣扎的人来说:使用下面的PowerShell代码来解决这个基于官方Angular 2文档的问题(在这个post中有人发布了这个问题? 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文档中的build议(上面的链接)将404redirect到/index.html文件。
我想在HTML5模式下保留子页面的URLpath,而不用redirect到索引,并且没有任何解决scheme告诉我如何做到这一点,所以这是我如何做到的:
在IIS中为所有路由创build简单的虚拟目录,并将它们指向应用程序根目录。
用这个位置标记将你的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>
我检查了angular2种子是如何工作的。
当页面重新加载时,您可以使用express-history-api-fallback自动redirect。
我认为这是解决这个问题IMO最优雅的方式。
如果你想使用PathLocationStrategy:
- Wild configurationconfiguration:
- 创build要放置在WEB-INF中的undertow-handlers.conf文件
- 内容:(排除你的rest终点!)
- 正则expression式['(./ overview / ?. ?$)']而不是正则expression式['(。/ endpoints。 )'] – > rewrite ['/ index.html']
- 正则expression式['(。/ deployments / ?. ?$)']而不是正则expression式['(。/ endpoints。 )'] – > rewrite ['/ index.html']
Java EE / Wildfly的单页面应用程序:服务器端configuration
你可以试试下面。 它适合我!
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)以分割路由器参数。 我正在使用angular2.4.9
这不是正确的答案,但在刷新你可以redirect所有死亡的电话到首页牺牲404页这是一个临时的黑客只是重播404.html文件
<!doctype html> <html> <head> <script type="text/javascript"> window.location.href = "http://" + document.location.host; </script> </head> </html>
解决“路由器不工作在浏览器重新加载”的最佳解决scheme是我们应该使用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" }); });
2017年7月11日:由于这是一个有问题的问题,但与电子使用Angular 2,我会在这里添加我的解决scheme。
我所要做的就是从我的index.html中删除<base href="./">
,Electron开始重新加载页面。
答案是非常棘手的。 如果您使用普通的旧Apache服务器(或IIS),则会出现问题,因为Angular页面不是真实存在的。 他们是从angular路线“计算”的。
有几种方法可以解决这个问题。 一个是使用Angular提供的HashLocationStrategy 。 但是URL中添加了一个尖锐的符号。 这主要是为了兼容Angular 1(我认为)。 事实上,sharp之后的部分不是URL的一部分(然后服务器parsing“#”符号之前的部分)。 那可以是完美的。
这里有一个增强的方法(基于404的技巧)。 我假设你有一个你的angular度应用程序的“分布式”版本(如果你使用Angular-CLI, ng build --prod
),你直接用你的服务器访问这个页面,并启用PHP。
如果你的网站是基于页面(例如Wordpress),并且你只有一个文件夹专用于Angular(在我的例子中命名为“dist”),那么你可以做一些奇怪的事情,但最后很简单。 我假设你已经把你的Angular页面存储在“/ dist”中(使用<BASE HREF="/dist/">
)。 现在使用404redirect和PHP的帮助。
在您的Apacheconfiguration中(或在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
是存储在你的angular index.html
的HREF中的值。
原理很简单,如果Apache没有find该页面,那么对PHP脚本进行404redirect。 我们只是检查页面是否在angular度应用程序目录内。 如果是这样,我们直接加载index.html(不redirect):这是必要的,以保持URL不变。 我们也将HTTP代码从404更改为200(对于爬虫来说更好)。
如果该页面不存在于angular度应用程序中呢? 那么,我们使用angular度路由器的“全部”(参见Angular路由器文档)。
这种方法与基本网站内embedded的Angular应用程序一起工作(我想将来会是这种情况)。
笔记:
- 试图用
mod_redirect
(通过重写URL)做同样的mod_redirect
也不是一个好的解决scheme,因为文件(如资产)必须真正加载,然后比使用“未find”解决scheme风险更大。 - 只要使用
ErrorDocument 404 /dist/index.html
redirect,但Apache仍然会响应404错误代码(这对于抓取工具不利)。
这不是问题的永久性修复,而更像是解决方法或破解
将我的Angular App部署到gh页面时,我遇到了同样的问题。 首先,当刷新我的页面时,我收到了404条消息。
然后,就像@gunter指出的那样,我开始使用Angular 2提供的HashLocationStrategy
。
但是,它带来了自己的一系列问题,在url中的#
这是非常糟糕的,使url看起来像这样https://rahulrsingh09.github.io/AngularConcepts/#/faq
。
我开始研究这个问题,并遇到了一个博客。 我试图给它一个镜头,它的工作。
这是我在那个博客中提到的。
您需要先在您的gh-pages库中添加一个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对象上的variables,并立即使用元刷新标记redirect到项目的index.html页面。 如果你正在做一个Github组织网站,不要在内容属性replace文本中放置一个回购站名,只要这样做: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检索我们在404.html页面的sessionStorage中caching的URL,并用它replace当前的历史logging。
参考backalleycoder感谢@Daniel这个解决方法。
现在上面的URL变成了https://rahulrsingh09.github.io/AngularConcepts/faq
angular度的应用程序是一个简单的静态HTML服务器的完美候选人。 您不需要服务器端引擎来dynamic组合应用程序页面,因为Angular会在客户端进行这样的操作。
如果应用程序使用Angular路由器,则必须将服务器configuration为在要求input不具有的文件时返回应用程序的主机页面(index.html)。
路由应用程序应该支持“深层链接”。 深层链接是指定应用程序内部组件的path的URL。 例如, http://www.example.com/heroes/42是英雄详细信息页面的深层链接,显示英雄ID为42。
用户从正在运行的客户端导航到该URL时没有问题。 Angular路由器解释URL和路由到那个页面和英雄。
但是单击电子邮件中的链接,将其input到浏览器地址栏中,或者仅在英雄详细信息页面上刷新浏览器 – 所有这些操作都由浏览器本身在正在运行的应用程序之外处理。 浏览器直接向服务器请求该URL,绕过路由器。
静态服务器在收到http://www.example.com/的请求时,会定期返回index.html。; 但它拒绝http://www.example.com/heroes/42并返回一个404 – Not Found错误,除非它被configuration为返回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", "favicon.ico", "Web.config" ],
3)现在,您可以使用生成生产解决scheme
ng build --prod
这将创build一个dist文件夹。 dist文件夹内的文件已准备好以任何模式进行部署。
西蒙的回答对我来说是正确的。 我添加了这个代码:
app.get('*', function(req, res, next) { res.sendfile("dist/index.html"); });