Я хочу включить режим 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-ref, чтобы исключить /#/
.
На данный момент я могу перейти на 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 для получения правильной страницы при обновлении?
Спасибо заранее.
Из angular docs
Серверная сторона
Использование этого режима требует перезаписи URL-адресов на стороне сервера, в основном вы должны переписать все свои ссылки на точку входа вашего приложения (например, index.html)
Причиной этого является то, что при первом посещении страницы (/about
), например. после обновления браузер не знает, что это не настоящий URL, поэтому он идет вперед и загружает его. Однако, если вы сначала загрузили корневую страницу и все javascript-код, тогда, когда вы перейдете к /about
Angular, можете попасть туда до того, как браузер попытается попасть на сервер и обработать его соответственно.
$routeProvider
и изменить пути каждого templateUrl
например, с templateUrl : '/views/about.html',
на templateUrl : 'example.com/views/about.html',
templateUrl : '/views/about.html',
Есть несколько вещей, которые нужно настроить, чтобы ваша ссылка в браузере выглядела как http://yourdomain.com/path
, и это ваша сторона angular config + server
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]
Более интересные материалы для чтения о режиме 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/link rewriting
У меня была аналогичная проблема, и я решил ее:
Используя <base href="/index.html">
на индексной странице
Используя уловить все промежуточное ПО маршрутизации на моем сервере node/Express следующим образом (поместите его после маршрутизатора):
app.use(function(req, res) {
res.sendfile(__dirname + '/Public/index.html');
});
Я думаю, что это должно помочь вам.
Если вы используете сервер apache, вам может понадобиться mod_rewrite ваши ссылки. Это не сложно. Всего несколько изменений в файлах конфигурации.
Все, что предполагает, что html5mode включен в angularjs. Теперь. обратите внимание, что в angular 1.2 объявление базового url больше не рекомендуется.
<base href="/">
и добавлением предложенной вами экспресс-маршрутизации. Большое спасибо.
<base href="/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() ]
}
});
});
Вам нужно настроить сервер для перезаписи всего на index.html для загрузки приложения:
try_files $uri $uri/ /index.php?...
соответствующая строка nginx как try_files $uri $uri/ /index.php?...
вместо необходимого index.html
. Спасибо за ссылку!
Я написал простую связующую среду для моделирования url-rewriting в проектах 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)
];
}
}
}
}
})
};
$routeProvider
?
urlRewrite
не определено при попытке запустить его, и мне трудно найти правильное соединение с перезаписью, которое я могу использовать.
Правила перезаписи URL-адреса IIS для предотвращения ошибки 404 после обновления страницы в html5mode
Для angular работает под 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
Для angular работает под 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
Если вы находитесь в стеке .NET с MVC с помощью AngularJS, это то, что вам нужно сделать, чтобы удалить "#" из URL:
Настройте свой базовый href на странице _Layout: <head> <base href="/"> </head>
Затем добавьте следующее в конфигурацию приложения angular: $locationProvider.html5Mode(true)
Выше будет удалять '#' из URL-адреса, но обновление страницы не будет работать, например. если вы находитесь на странице "yoursite.com/about", обновление будет дано вам 404. Это связано с тем, что MVC не знает о маршрутизации angular, а по шаблону MVC он будет искать страницу MVC для "about", которая не существует в пути маршрутизации MVC. Обходным путем для этого является отправка всех запросов страницы MVC в одно представление MVC, и вы можете сделать это, добавив маршрут, который ловит все URL
routes.MapRoute(
name: "App",
url: "{*url}",
defaults: new { controller = "Home", action = "Index" }
);
Как уже упоминалось, вам нужно переписать маршруты на сервере и установить <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) в моей среде dev и apache на производстве, добавить:
errorDocument 404 /index.html
.htaccess решит для меня эту проблему.
Для 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
}
}
}
},
npm install connect-modrewrite --save
2. require in gruntfile
3. скопируйте указанный выше серверный объект
Я отвечаю на этот вопрос из более крупного вопроса:
Когда я добавляю $locationProvider.html5Mode (true), мой сайт не позволит вставлять URL-адреса. Как настроить мой сервер для работы, когда html5Mode является истинным?
Когда у вас включен html5Mode, символ # больше не будет использоваться в ваших URL-адресах. Символ # полезен, так как он не требует конфигурации на стороне сервера. Без # URL выглядит намного приятнее, но также требует перезаписывания на стороне сервера. Вот несколько примеров:
Для Express Rewrites с 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'));
Я решил
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')
];
}
}
},
Если вы работаете локально, вы можете использовать: connect-modrewrite
См. этот учебник: http://ericduran.io/2013/05/31/angular-html5Mode-with-yeoman/
Мы перенаправили сервер в Express:
app.get('*', function(req, res){
res.render('index');
});
и мы все еще получали проблемы с обновлением страницы, даже после добавления <base href="/" />
.
Решение: убедитесь, что вы используете реальные ссылки на своей странице для навигации; не вводите маршрут в URL-адрес, или вы получите обновление страницы. (глупая ошибка, я знаю)
: - P
Я считаю, что ваша проблема связана с сервером. Документация angular в отношении режима HTML5 (по ссылке в вашем вопросе) гласит:
Серверная сторона Использование этого режима требует перезаписи URL-адресов на стороне сервера, в основном вы должны переписать все свои ссылки на точку входа вашего приложения (например, index.html)
Я считаю, что вам нужно будет настроить переписывание URL из /about в/.
Просто напишите правило в web.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="/">
У меня есть это простое решение, которое я использовал и его работы.
В приложении/Исключения/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);
}
Наконец, у меня есть способ решить эту проблему на стороне сервера, так как это больше похоже на проблему с AngularJs. Я использую 1.5 Angularjs, и у меня возникла такая же проблема при перезагрузке страницы.
Но после добавления кода в мой файл server.js
он сохраняет мой день , но это не правильное решение или не очень хороший способ.
app.use(function(req, res, next){
var d = res.status(404);
if(d){
res.sendfile('index.html');
}
});
Код вашей серверной части - JAVA, затем выполните следующие шаги.
Шаг 1: Загрузите urlrewritefilter JAR Нажмите здесь и сохранить для построения пути 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>
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 + angular, сгенерированным с помощью JHipster. Я решил его с помощью фильтра и списка всех страниц angular в свойствах:
application.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);
}
Надеюсь, это будет полезно для кого-то.
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
});
}
У меня была такая же проблема, прежде чем при обновлении страниц браузер отправил значение своего адресного знака на сервер, что, очевидно, потерпит неудачу (с тех пор как это переписанный адрес).
Вы также должны заполнить логику reqwritting URL-адресов на стороне сервера. См. Ссылку ниже, это лучший пример, который я нашел о том, как это сделать, и это отлично работает для меня:
https://github.com/bdunklau/LittleBlueBird/wiki/URL-Rewriting-and-HTML5-in-AngularJS
В основном вам просто нужно перенаправить все запросы в контейнер содержимого главной страницы (в большинстве случаев - index.html).
Я нашел еще лучший плагин Grunt, который работает, если у вас есть index.html и Gruntfile.js в том же каталоге;
https://npmjs.org/package/grunt-connect-pushstate
После этого в вашем файле Grunt:
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)
];
}
},
}
},