我正在使用 Angular 2.0.0-alpha.30 版本。当重定向到不同的路由,然后刷新浏览器,它显示Cannot GET /route。
你能帮我弄清楚为什么会发生这个错误。
我正在使用 Angular 2.0.0-alpha.30 版本。当重定向到不同的路由,然后刷新浏览器,它显示Cannot GET /route。
你能帮我弄清楚为什么会发生这个错误。
您看到的错误是因为您请求的 http://localhost/route 不存在。据西蒙.
使用 html5 路由时,您需要将应用程序中的所有路由(当前为 404)映射到服务器端的 index.html。以下是一些供您选择的选项:
使用实时服务器:https ://www.npmjs.com/package/live-server
$live-server --entry-file=index.html`
使用 nginx: http: //nginx.org/en/docs/beginners_guide.html
error_page 404 /index.html
Tomcat - web.xml 的配置。来自库宁的评论
<error-page>
<error-code>404</error-code>
<location>/index.html</location>
</error-page>
免责声明:此修复适用于 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(PathLocationStrategy
在 Angular 俚语中)。
您要么需要一个像请求一样处理所有请求的服务器,要么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';
< 测试版.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 是正常的完整 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,路由器将启动,一切都会按预期工作。
确保将其放置在 index.html 的 head 元素中:
<base href="/">
Angular2 Routing & Navigation文档中的示例在头部使用了以下代码(他们在文档的实时示例注释中解释了原因):
<script>document.write('<base href="' + document.location + '" />');</script>
当您刷新页面时,这会将基本 href 动态设置为您当前的 document.location。我可以看到这会给浏览文档并试图复制 plunker 的人造成一些混乱。
如果您希望能够在浏览器中输入 url 而无需配置 AppServer 来处理对 index.html 的所有请求,则必须使用HashLocationStrategy。
最简单的配置方法是使用:
RouterModule.forRoot(routes, { useHash: true })
代替:
RouterModule.forRoot(routes)
使用HashLocationStrategy你的网址会是这样的:
http://server:port/#/path
我在使用 webpack-dev-server 时遇到了同样的问题。我必须将 devServer 选项添加到我的 webpack 中。
// in webpack
devServer: {
historyApiFallback: true,
stats: 'minimal'
}
如果您使用 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,我在刷新或深度链接时修复 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 的方法。
服务器配置不是 SPA 的解决方案,我什至认为。如果出现错误的路线,您不想再次重新加载角度 SPA,对吗?因此,我不会依赖服务器路由并重定向到其他路由,但是是的,我会让 index.html 处理对角度应用程序路径的角度路由的所有请求。
试试这个,而不是其他或错误的路线。它对我有用,不确定,但似乎正在进行中。遇到问题时自己偶然发现了这个。
@RouteConfig([
{ path: '/**', redirectTo: ['MycmpnameCmp'] },
...
}
])
https://github.com/angular/angular/issues/4055
但是请记住配置您的服务器文件夹和访问权限,以防您拥有不是 SPA 的 HTML 或 Web 脚本。否则你将面临问题。对我来说,当遇到像你这样的问题时,它是服务器配置及以上配置的混合。
对于 Angular 5 快速修复,编辑app.module.ts并{useHash:true}
在 appRoutes 之后添加。
@NgModule(
{
imports:[RouterModule.forRoot(appRoutes,{useHash:true})]
})
您可以将此解决方案用于平均应用程序,我使用 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 相关的创建问题
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 文件夹中的文件已准备好以任何模式部署。
对于我们这些在 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 文件。
你可以在下面试试。这个对我有用!
主要组件.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
我只是在根目录中添加 .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 文件是主目录路径并在项目构建中设置。
我想在 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>
我检查了 angular 2 seed 它是如何工作的。
您可以使用express-history-api-fallback在页面重新加载时自动重定向。
我认为这是解决这个问题 IMO 的最优雅的方法。
如果你想使用 PathLocationStrategy :
2017 年 7 月 11 日:由于这与存在此问题但使用 Angular 2 和 Electron 的问题相关联,因此我将在此处添加我的解决方案。
我所要做的就是<base href="./">
从我的 index.html 中删除,然后 Electron 又开始成功地重新加载页面。
添加进口:
import { HashLocationStrategy, LocationStrategy } from '@angular/common';
在 NgModule 提供者中,添加:
providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]
在应用程序的主 index.html 文件中,将基本 href 更改为./index.html
from/
部署在任何服务器中的应用程序将为页面提供一个真实的 url,该页面可以从任何外部应用程序访问。
只需在根目录中添加.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>
我认为您收到 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(路由,{ useHash: true })
代替:
RouterModule.forRoot(路由)
使用 HashLocationStrategy 你的网址会是这样的:
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]
您可以使用位置策略,useHash: true
在路由文件中添加。
imports: [RouterModule.forRoot(routes, { useHash: true })]
这不是正确的答案,但是在刷新时,您可以通过牺牲 404 页面将所有无效调用重定向到主页,这是一个临时黑客,只需在 404.html 文件上重播
<!doctype html>
<html>
<head>
<script type="text/javascript">
window.location.href = "http://" + document.location.host;
</script>
</head>
</html>
解决“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" });
});
答案相当棘手。如果您使用普通的旧 Apache 服务器(或 IIS),您会遇到问题,因为 Angular 页面并不真实存在。它们是从 Angular 路由“计算”出来的。
有几种方法可以解决此问题。一种是使用 Angular 提供的HashLocationStrategy。但是在 URL 中添加了一个尖锐的符号。这主要是为了与 Angular 1 兼容(我假设)。事实上,尖后的部分不是 URL 的一部分(然后服务器解析“#”符号之前的部分)。这可以是完美的。
这里是一种增强的方法(基于 404 技巧)。我假设您拥有 Angular 应用程序的“分布式”版本(ng build --prod
如果您使用 Angular-CLI),并且您可以直接使用服务器访问页面并启用 PHP。
如果您的网站基于页面(例如 Wordpress)并且您只有一个专用于 Angular 的文件夹(在我的示例中名为“dist”),那么您可以做一些奇怪的事情,但最终很简单。我假设您已将 Angular 页面存储在“/dist”中(带有相应的<BASE HREF="/dist/">
)。现在使用 404 重定向和 PHP 的帮助。
在您的 Apache 配置中(或在.htaccess
您的 Angular 应用程序目录的文件中),您必须添加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 的 HREF 中的值在哪里index.html
。
原理很简单,如果 Apache 没有找到页面,就会对 PHP 脚本进行 404 重定向。我们只检查页面是否在 Angular 应用程序目录中。如果是这种情况,我们只需直接加载 index.html(无需重定向):这是保持 URL 不变的必要条件。我们还将 HTTP 代码从 404 更改为 200(对爬虫更好)。
如果页面在 Angular 应用程序中不存在怎么办?好吧,我们使用 Angular 路由器的“包罗万象”(参见 Angular 路由器文档)。
此方法适用于基本网站内的嵌入式 Angular 应用程序(我认为将来会如此)。
笔记:
mod_redirect
(通过重写 URL)做同样的事情根本不是一个好的解决方案,因为必须真正加载文件(如资产),然后它比仅使用“未找到”解决方案风险更大。ErrorDocument 404 /dist/index.html
但 Apache 仍然响应 404 错误代码(这对爬虫不利)。这不是问题的永久解决方案,而更像是一种解决方法或破解
在将我的 Angular 应用程序部署到 gh-pages 时,我遇到了同样的问题。首先,在 gh-pages 上刷新我的页面时,我收到了 404 条消息。
然后正如@gunter 指出的那样,我开始使用HashLocationStrategy
Angular 2 提供的。
但这带来了它自己的一系列问题,#
在 url 中它真的很糟糕,使得 url 看起来像这样奇怪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,您需要在任何其他 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
我通过添加一个与我的 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";
}
}
如果您使用 Apache 或 Nginx 作为服务器,您需要创建一个 .htaccess
<IfModule mime_module>
AddHandler application/x-httpd-ea-php72 .php .php7 .phtml
</IfModule>
# php -- END cPanel-generated handler, do not edit
<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>
西蒙的回答对我来说是正确的。我添加了这段代码:
app.get('*', function(req, res, next) {
res.sendfile("dist/index.html");
});