用 AngularJSHTML5模式重新加载页面会给出错误的 GET 请求

我想为我的应用程序启用 HTML5模式。我已经为配置放置了以下代码,如 给你所示:

return app.config(['$routeProvider','$locationProvider', function($routeProvider,$locationProvider) {


$locationProvider.html5Mode(true);
$locationProvider.hashPrefix = '!';


$routeProvider.when('/', {
templateUrl: '/views/index.html',
controller: 'indexCtrl'
});
$routeProvider.when('/about',{
templateUrl: '/views/about.html',
controller: 'AboutCtrl'
});

正如你所看到的,我使用了 $locationProvider.html5mode,并且我改变了我在 ng-href的所有链接,以排除 /#/

问题

目前,我可以转到 localhost:9000/,看到索引页面,并导航到其他页面,如 localhost:9000/about

然而,当我刷新 localhost:9000/about页面时,问题出现了

如果我看看网络呼叫:

Request URL:localhost:9000/about
Request Method:GET

然而,如果我首先到 localhost:9000/,然后点击一个导航到 /about的按钮,我会得到:

Request URL:http://localhost:9000/views/about.html

这样页面就完美地呈现出来了。

当我刷新的时候,我如何使角度得到正确的页面?

150878 次浏览

我相信你的问题是关于服务器的。关于 HTML5模式的角度文档(在你问题的链接处)说:

服务器端 使用这种模式需要在服务器端重写 URL,基本上你必须重写到应用程序入口点的所有链接(例如 index.html)

我相信您需要设置一个从/about 到/的 URL 重写。

来自 有棱角的医生

服务器端
使用这种模式需要在服务器端重写 URL,基本上你必须重写到应用程序入口点的所有链接(例如 index.html)

这是因为当你第一次访问这个页面(/about) ,例如刷新之后,浏览器无法知道这不是一个真正的 URL,所以它会继续加载它。但是,如果你已经加载了根页面,和所有的 javascript 代码,然后当你导航到 /about角度可以在浏览器尝试打击服务器,并相应地处理它之前进入那里

我编写了一个简单的连接中间件,用于模拟 grunt 项目中的 URL 重写

你可以这样用:

module.exports = function(grunt) {
var urlRewrite = require('grunt-connect-rewrite');


// Project configuration.
grunt.initConfig({
connect: {
server: {
options: {
port: 9001,
base: 'build',
middleware: function(connect, options) {
// Return array of whatever middlewares you want
return [
// redirect all urls to index.html in build folder
urlRewrite('build', 'index.html'),


// Serve static files.
connect.static(options.base),


// Make empty directories browsable.
connect.directory(options.base)
];
}
}
}
}
})
};

我也遇到过类似的问题,我用以下方法解决了它:

  • 在索引页中使用 <base href="/index.html">

  • 在我的 node/Express 服务器中使用 catch all 路由中间件,如下所示(将其放在路由器后面) :

app.use(function(req, res) {
res.sendfile(__dirname + '/Public/index.html');
});

我觉得这应该能让你振作起来。

如果使用 Apache 服务器,可能需要 mod _ rewrite 您的链接。这并不难做到。只是在配置文件中做了一些更改。

所有这些都假设您在 angularjs 上启用了 html5mode。 现在,请注意,在角度1.2中,实际上不再推荐声明一个基 URL。

我发现了一个更好的 Grunt 插件,如果你的 index.html 和 Gruntfile.js 在同一个目录中,它就可以工作;

https://npmjs.org/package/grunt-connect-pushstate

然后在你的报告里写道:

 var pushState = require('grunt-connect-pushstate/lib/utils').pushState;




connect: {
server: {
options: {
port: 1337,
base: '',
logger: 'dev',
hostname: '*',
open: true,
middleware: function (connect, options) {
return [
// Rewrite requests to root so they may be handled by router
pushState(),
// Serve static files
connect.static(options.base)
];
}
},
}
},

我们在 Express 中有一个服务器重定向:

app.get('*', function(req, res){
res.render('index');
});

即使在添加了 <base href="/" />之后,我们仍然会遇到页面刷新问题。

解决方案: 确保在页面中使用真实的链接导航; 不要在 URL 中键入路由,否则会得到页面刷新。(愚蠢的错误,我知道)

翻译: 小宝宝 P- 小宝宝 P- 小宝宝 P- 小宝宝 P- 小宝宝 P- 小宝宝 P- 小宝宝 P- 小宝宝 P- 小宝宝 P- 小宝宝 P- 小宝宝 P- 小宝宝

正如其他人所提到的,您需要重写服务器上的路由并设置 <base href="/"/>

对于 gulp-connect:

npm install connect-pushstate

var gulp = require('gulp'),
connect = require('gulp-connect'),
pushState = require('connect-pushstate/lib/pushstate').pushState;
...
connect.server({
...
middleware: function (connect, options) {
return [
pushState()
];
}
...
})
....

有一些事情要设置,以便您的链接在浏览器将看起来像 http://yourdomain.com/path,这些是您的角配置 + 服务器端

1) AngularJS

$routeProvider
.when('/path', {
templateUrl: 'path.html',
});
$locationProvider
.html5Mode(true);

2)服务器端, 只要把 .htaccess放到你的根文件夹中并粘贴这个

RewriteEngine On
Options FollowSymLinks


RewriteBase /


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /#/$1 [L]

更多关于 angularjs 中的 html5模式以及不同环境下所需配置的有趣内容 < a href = “ https://github.com/angle-ui/ui-router/wiki/  « How-to-configure-your-server-to-work-with-html5mode”rel = “ norefrer”> https://github.com/angular-ui/ui-router/wiki/frequently-asked-questions#how-to-configure-your-server-to-work-with-html5mode 此外,这个问题可能会帮助你在 html5和 hashbang 模式/链接重写之间切换

我解决了

test: {
options: {
port: 9000,
base: [
'.tmp',
'test',
'<%= yeoman.app %>'
],
middleware: function (connect) {
return [
modRewrite(['^[^\\.]*$ /index.html [L]']),
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static('app')
];
}
}
},
I solved same problem using modRewrite.
AngularJS is reload page when after # changes.
But HTML5 mode remove # and invalid the reload.
So we should reload manually.
# install connect-modrewrite
$ sudo npm install connect-modrewrite --save


# gulp/build.js
'use strict';
var gulp = require('gulp');
var paths = gulp.paths;
var util = require('util');
var browserSync = require('browser-sync');
var modRewrite  = require('connect-modrewrite');
function browserSyncInit(baseDir, files, browser) {
browser = browser === undefined ? 'default' : browser;
var routes = null;
if(baseDir === paths.src || (util.isArray(baseDir) && baseDir.indexOf(paths.src) !== -1)) {
routes = {
'/bower_components': 'bower_components'
};
}


browserSync.instance = browserSync.init(files, {
startPath: '/',
server: {
baseDir: baseDir,
middleware: [
modRewrite([
'!\\.\\w+$ /index.html [L]'
])
],
routes: routes
},
browser: browser
});
}

我在开发环境中使用 apache (xampp) ,在生产环境中使用 apache, 补充:

errorDocument 404 /index.html

访问为我解决这个问题。

BrowserSync 和 Gulp 解决方案。

来自 https://github.com/BrowserSync/browser-sync/issues/204#issuecomment-102623643

首次安装 connect-history-api-fallback:

npm --save-dev install connect-history-api-fallback

然后把它添加到你的 Gulpfile.js:

var historyApiFallback = require('connect-history-api-fallback');


gulp.task('serve', function() {
browserSync.init({
server: {
baseDir: "app",
middleware: [ historyApiFallback() ]
}
});
});

如果你愿意的话。NET 堆栈与 MVC 和 AngularJS,这是你必须做的删除’#’从网址:

  1. 在您的 _ Layout 页面中设置基础 href: <head> <base href="/"> </head>

  2. 然后,添加以下在您的角度应用程序配置: $locationProvider.html5Mode(true)

  3. 以上将删除“ #”从网址,但页面刷新不会工作,例如,如果你在“ yoursite.com/about”页面刷新将给你一个404。这是因为 MVC 不知道角度路由,根据 MVC 模式,它会寻找一个在 MVC 路由路径中不存在的“ about”的 MVC 页面。解决方法是将所有 MVC 页面请求发送到一个 MVC 视图,您可以通过添加一个捕获所有 URL 的路由来实现这一点


routes.MapRoute(
name: "App",
url: "{*url}",
defaults: new { controller = "Home", action = "Index" }
);

我有同样的问题与 爪哇咖啡 + 角度应用程序生成与 JHipster。 我解决了它与过滤器和列表的所有角度页的属性:

项目名称:

angular-pages:
- login
- settings
...

AngularPageReloadFilter.java

public class AngularPageReloadFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.getRequestDispatcher("index.html").forward(request, response);
}
}

Java

private void initAngularNonRootRedirectFilter(ServletContext servletContext,
EnumSet<DispatcherType> disps) {
log.debug("Registering angular page reload Filter");
FilterRegistration.Dynamic angularRedirectFilter =
servletContext.addFilter("angularPageReloadFilter",
new AngularPageReloadFilter());
int index = 0;
while (env.getProperty("angular-pages[" + index + "]") != null) {
angularRedirectFilter.addMappingForUrlPatterns(disps, true, "/" + env.getProperty("angular-pages[" + index + "]"));
index++;
}
angularRedirectFilter.setAsyncSupported(true);
}

霍普,这会对某些人有帮助的。

Gulp + BrowserSync:

通过 npm 安装 connect-history-api-falback,稍后配置您的服务吞噬任务

var historyApiFallback = require('connect-history-api-fallback');


gulp.task('serve', function() {
browserSync.init({
proxy: {
target: 'localhost:' + port,
middleware: [ historyApiFallback() ]
}
});
});

我是从更大的问题来回答这个问题的:

当我添加 $locationProvider.html5Mode (true)时,我的站点将不允许粘贴 URL。当 html5Mode 为 true 时,如何配置服务器以使其工作?

当您启用 html5Mode 时,# 字符将不再在您的 URL 中使用。符号 # 很有用,因为它不需要服务器端配置。如果没有 # ,URL 看起来会更好,但是它也需要服务器端重写。下面是一些例子:

对于使用 AngularJS 的 Express Rewrite,您可以通过以下更新来解决这个问题:

app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/index.html'));
});

还有

<!-- FOR ANGULAR ROUTING -->
<base href="/">

还有

app.use('/',express.static(__dirname + '/public'));

IISURL 重写规则,以防止在 html5mode 中刷新页面后出现404错误

用于在 Windows 的 IIS 下角度运行

<rewrite>
<rules>
<rule name="AngularJS" 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>

NodeJS/ExpressJS Routes 防止在 html5模式下刷新页面后出现404错误

用于在 Node/Express 下进行角度运行

var express = require('express');
var path = require('path');
var router = express.Router();


// serve angular front end files from root path
router.use('/', express.static('app', { redirect: false }));


// rewrite virtual urls to angular app to enable refreshing of internal pages
router.get('*', function (req, res, next) {
res.sendFile(path.resolve('app/index.html'));
});


module.exports = router;

更多信息: AngularJS-在 NodeJS 和 IIS 中启用 HTML5模式页面刷新而不会出现404错误

对于 Grunt 和 Browsersync,请使用 connect-modrewrite给你

var modRewrite = require('connect-modrewrite');




browserSync: {
dev: {
bsFiles: {


src: [
'app/assets/css/*.css',
'app/*.js',
'app/controllers/*.js',
'**/*.php',
'*.html',
'app/jade/includes/*.jade',
'app/views/*.html',
],
},
options: {
watchTask: true,
debugInfo: true,
logConnections: true,
server: {
baseDir :'./',
middleware: [
modRewrite(['!\.html|\.js|\.jpg|\.mp4|\.mp3|\.gif|\.svg\|.css|\.png$ /index.html [L]'])
]
},


ghostMode: {
scroll: true,
links: true,
forms: true
}
}
}
},

您的服务器端代码是 JAVA,然后按照下面的步骤操作

步骤1: 下载 urlrewritefilter JAR < a href = “ https://mvnRepository.com/artif/org.tuckey/urlrewritefilter/4.0.3”rel = “ nofollow”> Click Here 并保存为构建路径 WEB-INF/lib

步骤2: 启用 HTML5模式 $locationProvider.html5Mode (true) ;

步骤3: 设置基本 URL <base href="/example.com/"/>

步骤4: 复制并粘贴到 WEB.XML

 <filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>


<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>

步骤5: 在 WEN-INF/urlrewrite.xml 中创建文件

 <urlrewrite default-match-type="wildcard">




<rule>
<from>/</from>
<to>/index.html</to>
</rule>


<!--Write every state dependent on your project url-->
<rule>
<from>/example</from>
<to>/index.html</to>
</rule>
</urlrewrite>

最后,我得到了一个方法来解决这个问题的服务器端,因为它更像一个问题 AngularJs 本身我使用1.5 AngularJs 和我得到了同样的问题重新加载页面。 但是在我的 server.js文件中添加了下面的代码之后,它就成了我的救命稻草。但是这不是一个合适的解决方案,也不是一个好的方法。

app.use(function(req, res, next){
var d = res.status(404);
if(d){
res.sendfile('index.html');
}
});

我有这个简单的解决方案,我一直在使用和它的工程。

在 App/Exception/Handler.php 中

把这个放在上面:

use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

然后在呈现方法内部

public function render($request, Exception $exception)
{
.......


if ($exception instanceof NotFoundHttpException){


$segment = $request->segments();


//eg. http://site.dev/member/profile
//module => member
// view => member.index
//where member.index is the root of your angular app could be anything :)
if(head($segment) != 'api' && $module = $segment[0]){
return response(view("$module.index"), 404);
}


return response()->fail('not_found', $exception->getCode());


}
.......


return parent::render($request, $exception);
}

我已经通过在 node.js 文件中添加以下代码片段解决了这个问题。

app.get("/*", function (request, response) {
console.log('Unknown API called');
response.redirect('/#' + request.url);
});

注意: 当我们刷新页面时,它将查找 API 而不是 Angular 页面(因为 URL 中没有 # 标记).使用上面的代码,我用 # 重定向到 url