Перезагрузка страницы дает неправильный запрос 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 middleware в моем узле / Экспресс-сервере следующим образом (поместите его после маршрутизатора):
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
затем добавьте его в свой файл глотка.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>
затем добавьте следующее в свою угловую конфигурацию приложения:
$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
для углового запуска под 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-включить обновление страницы в режиме 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 выглядит намного лучше, но он также требует серверной стороны переписывает. Вот несколько примеров:
для экспресс переписывает с 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 из /about в /.
у нас был редирект сервера в Express:
app.get('*', function(req, res){ res.render('index'); });
и мы все еще получали проблемы с обновлением страницы, даже после того, как мы добавили
<base href="/" />
.решение: убедитесь, что вы используете реальные ссылки на своей странице для навигации; не вводите маршрут в URL-адрес, или вы получите обновление страницы. (глупая ошибка, Я знаю)
: - P
наконец-то я получил способ решить эту проблему на стороне сервера, так как это больше похоже на проблему с AngularJs сам я использую 1.5 Angularjs и я получил ту же проблему при перезагрузке страницы. Но после добавления ниже кода в мой
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 + угловой приложение, созданное с 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, позже настройте свою задачу подачи глотка
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 вместо угловой страницы (из-за отсутствия тега # в URL.) . Используя приведенный выше код, я перенаправляю на url-адрес с #
просто напишите правило в интернете.конфигурации
<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 приложение.конфигурации
app.config(function ($stateProvider, $urlRouterProvider, $locationProvider){ $locationProvider.html5Mode({ enabled: true, requireBase: true }); $locationProvider.hashPrefix('!'); }