Перезагрузка страницы дает неправильный запрос GET в режиме AngularJS HTML5
я хочу включить режим 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
страница. Я получаю следующий вывод: Cannot GET /about
если я посмотрю на сетевые вызовы:
Request URL:localhost:9000/about
Request Method:GET
а если я сначала пойду в localhost:9000/
, а затем нажмите на кнопку, которая переходит к /about
Я:
Request URL:http://localhost:9000/views/about.html
который отлично отображает страницу.
Как включить angular, чтобы получить правильную страницу при обновлении?
24 ответов
сервер
Использование этого режима требует перезаписи URL на стороне сервера, в основном вам нужно переписать все ваши ссылки на точку входа вашего приложения (например, индекс.html)
причина этого в том, что при первом посещении страницы (/about
), например, после обновления, браузер не может знать, что это не реальный URL, поэтому он идет вперед и загружает его. Однако если вы сначала загрузили корневую страницу и весь код javascript, а затем при переходе к /about
Angular может попасть туда, прежде чем браузер попытается ударить по серверу и обработать его соответственно
есть несколько вещей, чтобы настроить, так что ваша ссылка в браузере будет выглядеть как 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 ^(.*)$ /#/ [L]
более интересные вещи, чтобы прочитать о режиме html5 в angularjs и конфигурации, необходимой для разных сред https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode Также этот вопрос может помочь вам $location / переключение между html5 и режимом hashbang / переписывание ссылок
у меня была похожая проблема и я решил ее:
используя
<base href="/index.html">
на странице индексаиспользование промежуточного программного обеспечения catch all route в моем узле / Express server следующим образом (поместите его после маршрутизатора):
app.use(function(req, res) {
res.sendfile(__dirname + '/Public/index.html');
});
Я думаю, что это должно получить вас и работает.
Если вы используете сервер apache, вы можете захотеть mod_rewrite свои ссылки. Это не трудно сделать. Всего несколько изменений в конфигурации файлы.
все это предполагает, что у вас включен html5mode на angularjs. Сейчас. обратите внимание, что в angular 1.2 объявление базового url-адреса больше не рекомендуется.
решение для 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() ]
}
});
});
Я написал простое промежуточное ПО connect для моделирования перезаписи url-адресов в проектах grunt. https://gist.github.com/muratcorlu/5803655
вы можете использовать так:
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)
];
}
}
}
}
})
};
Если вы находитесь в стеке .NET с MVC с AngularJS, это то, что вам нужно сделать, чтобы удалить " # " из url:
настройте свой базовый href на странице _Layout:
<head> <base href="/"> </head>
затем добавьте следующее В конфигурацию angular app:
$locationProvider.html5Mode(true)
выше удалит " # " из url, но обновление страницы не будет работать, например, если вы находитесь в "yoursite.com/about" обновление страницы даст вам 404. Это потому, что MVC не знает об угловой маршрутизации и шаблоном MVC он будет искать страницу MVC для "О", которая не существует в пути маршрутизации MVC. Обходной путь для этого-отправить весь запрос страницы MVC в одно представление MVC, и вы можете сделать это, добавив маршрут, который ловит все url
routes.MapRoute(
name: "App",
url: "{*url}",
defaults: new { controller = "Home", action = "Index" }
);
правило перезаписи URL IIS для предотвращения ошибки 404 после обновления страницы в html5mode
для углового запуска под IIS в Windows
<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 для предотвращения ошибки 404 после обновления страницы в html5mode
для углового хода под узлом / 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-включить обновление страницы режима HTML5 без 404 ошибок в NodeJS и IIS
как уже упоминалось, вам нужно переписать маршруты на сервере и установить <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()
];
}
...
})
....
Я использую apache (xampp) в моей среде разработки и apache на производстве, добавить:
errorDocument 404 /index.html
на .htaccess решить для меня эту проблему.
решил
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')
];
}
}
},
я отвечаю на этот вопрос более важный вопрос:
когда я добавляю $locationProvider.html5Mode (true), мой сайт не позволит вставлять URL-адреса. Как настроить мой сервер для работы, когда html5Mode имеет значение true?
когда у вас включен html5Mode, символ # больше не будет использоваться в ваших URL-адресах. Символ # полезен, поскольку не требует настройки на стороне сервера. Без # url-адрес выглядит намного лучше, но он также требует серверной стороны переписывает. Вот несколько примеров:
для Express переписывает с AngularJS, вы можете решить эту проблему со следующими обновлениями:
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'));
для 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
}
}
}
},
Я считаю, что ваша проблема связана с сервером. Угловая документация в отношении режима HTML5 (по ссылке в вашем вопросе) гласит:
сервер Использование этого режима требует перезаписи URL на стороне сервера, в основном вам нужно переписать все ваши ссылки на точку входа вашего приложения (например, индекс.html)
Я считаю, что вам нужно будет настроить перезапись url из /О в /.
у нас был перенаправление сервера в Express:
app.get('*', function(req, res){
res.render('index');
});
и мы все еще получали проблемы с обновлением страницы, даже после того, как мы добавили <base href="/" />
.
решение: убедитесь, что вы используете реальные ссылки на странице для навигации; не вводите маршрут в URL-адрес или вы получите обновление страницы. (глупая ошибка, Я знаю)
: - P
наконец, у меня есть способ решить эту проблему на стороне сервера, поскольку это больше похоже на проблему с AngularJs, я использую 1.5 Angularjs, и у меня такая же проблема при перезагрузке страницы.
Но после добавления ниже кода в my server.js
файл это сохранить мой день но это не правильное решение или не хороший способ .
app.use(function(req, res, next){
var d = res.status(404);
if(d){
res.sendfile('index.html');
}
});
Я нашел еще лучший плагин Grunt, который работает, если у вас есть индекс.html и Gruntfile.js в том же каталоге;
https://npmjs.org/package/grunt-connect-pushstate
после этого в вашем Gruntfile:
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)
];
}
},
}
},
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
});
}
у меня была такая же проблема с java + angular приложение генерируется с JHipster. Я решил это с помощью фильтра и списка всех угловых страниц в свойствах:
приложение.в формате YML:
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);
}
}
WebConfigurer.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:
установите connect-history-api-fallback через npm, позже настройте свою задачу serve gulp
var historyApiFallback = require('connect-history-api-fallback');
gulp.task('serve', function() {
browserSync.init({
proxy: {
target: 'localhost:' + port,
middleware: [ historyApiFallback() ]
}
});
});
ваш серверный код JAVA, затем выполните следующие действия
Шаг 1: Скачать urlrewritefilter JAR Нажмите Здесь и сохранить, чтобы построить путь WEB-INF/lib
Шаг 2: включить режим HTML5 $locationProvider.html5Mode (true);
Шаг 3: Установите базовый URL <base href="/example.com/"/>
Шаг 4: скопируйте и вставьте в свой интернет.В 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>
у меня есть это простое решение, которое я использовал, и его работы.
В Приложения/Исключения/Обработчик.в 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);
}
Я решил проблему, добавив ниже фрагмент кода в узел.файл js.
app.get("/*", function (request, response) {
console.log('Unknown API called');
response.redirect('/#' + request.url);
});
Примечание: когда мы обновляем страницу, она будет искать API вместо угловой страницы (из-за отсутствия # tag в URL.) . Используя приведенный выше код, я перенаправляю на url-адрес с помощью #
просто напишите правило в интернете.config
<system.webServer>
<rewrite>
<rules>
<rule name="AngularJS Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
в индексе добавьте это
<base href="/">
это работает для меня, возможно, вы забыли установить приложение Html5Mode.config
app.config(function ($stateProvider, $urlRouterProvider, $locationProvider){
$locationProvider.html5Mode({ enabled: true, requireBase: true });
$locationProvider.hashPrefix('!');
}