Я использую версию Angular 2.0.0-alpha.30. При перенаправлении на другой маршрут обновите браузер, показывая, что он не может GET/route.
Можете ли вы помочь мне понять, почему эта ошибка произошла.
Я использую версию Angular 2.0.0-alpha.30. При перенаправлении на другой маршрут обновите браузер, показывая, что он не может GET/route.
Можете ли вы помочь мне понять, почему эта ошибка произошла.
Ошибка, которую вы видите, заключается в том, что вы запрашиваете http://localhost/route, который не существует. Согласно Саймон.
При использовании маршрутизации html5 вам необходимо отобразить все маршруты в вашем приложении (в настоящее время 404) на index.html на вашей стороне сервера. Вот несколько вариантов для вас:
используя live-сервер: 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. Из Kunin комментарий
<error-page>
<error-code>404</error-code>
<location>/index.html</location>
</error-page>
Отказ от ответственности: это исправление работает с Alpha44
У меня была такая же проблема и я решил ее реализовать, выполнив HashLocationStrategy, перечисленные в Angular.io API Preview.
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 по умолчанию использует pushstate HTML5 (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 final
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';
< beta.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 break-changes
Я думаю, что ошибка, которую вы видите, связана с тем, что вы запрашиваете http://localhost/route, который не существует. Вы должны убедиться, что ваш сервер будет отображать все запросы на главную страницу index.html.
Поскольку Angular 2 использует html5-маршрутизацию по умолчанию, а не использование хэшей в конце URL-адреса, обновление страницы выглядит как запрос для другого ресурса.
Это обычная ситуация во всех версиях маршрутизатора, если вы используете стратегию определения местоположения по умолчанию.
Что происходит, так это то, что URL-адрес на панели браузера является нормальным полным URL-адресом HTML, например: http://localhost/route
.
Итак, когда мы нажимаем Enter в строке браузера, на сервер отправляется фактический HTTP-запрос, чтобы получить файл с именем route
.
У сервера нет такого файла, и на сервере не настроено что-то вроде express, чтобы обрабатывать запрос и предоставлять ответ, поэтому сервер возвращает 404 Not Found, потому что он не смог найти файл route
.
Нам бы хотелось, чтобы сервер возвращал файл index.html
, содержащий одностраничное приложение. Затем маршрутизатор должен запустить и обработать URL /route
и отобразить компонент, сопоставленный с ним.
Итак, чтобы исправить проблему, нам нужно настроить сервер для возврата index.html
(при условии, что это имя вашего файла приложения одной страницы) в случае, если запрос не может быть обработан, в отличие от 404 Not Found.
Способ сделать это будет зависеть от используемой технологии на стороне сервера. Если его Java, например, вам, возможно, придется написать сервлет, в Rails он будет другим и т.д.
Чтобы привести конкретный пример, если, например, вы используете NodeJs, вам придется написать такое промежуточное ПО:
function sendSpaFileIfUnmatched(req,res) {
res.sendFile("index.html", { root: '.' });
}
И затем зарегистрируйте его в самом конце цепи промежуточного программного обеспечения:
app.use(sendSpaFileIfUnmatched);
Это приведет к index.html
вместо возврата 404, маршрутизатор начнет работать, и все будет работать так, как ожидалось.
Убедитесь, что это помещено в элемент head вашего index.html:
<base href="/">
Example в документации Angular2 Маршрутизация и Навигация использует следующий код в (они объясняют, почему в живом примере примечание документации):
<script>document.write('<base href="' + document.location + '" />');</script>
Когда вы обновляете страницу, это будет динамически устанавливать базовый href в текущую документацию. Я мог видеть, что это вызывает некоторую путаницу, когда люди просматривают документацию и пытаются воспроизвести плункер.
У меня была такая же проблема с использованием webpack-dev-сервера. Мне пришлось добавить параметр devServer в свой веб-пакет.
// in webpack
devServer: {
historyApiFallback: true,
stats: 'minimal'
}
Если вы используете Apache в качестве сервера, вам нужно создать .htaccess (если не созданный ранее) и "On" 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 angular, если приходит неправильный маршрут, не так ли? Поэтому я не буду зависеть от маршрута сервера и перенаправлять на другой маршрут, но да, я передам index.html все запросы для angular маршрутов пути angular.
Попробуйте это вместо других или неправильных маршрутов. Он работает для меня, не уверен, но кажется, что работа продолжается. Наткнулся на это сам, столкнувшись с проблемой.
@RouteConfig([
{ path: '/**', redirectTo: ['MycmpnameCmp'] },
...
}
])
https://github.com/angular/angular/issues/4055
Однако не забудьте настроить папки вашего сервера и права доступа, если у вас есть HTML или веб-скрипты, которые не являются СПА. Иначе вы столкнетесь с проблемами. Для меня, когда вы столкнулись с проблемой, подобной вам, это было сочетание конфигурации сервера и выше.
Если вы хотите вводить URL-адреса в браузере, не настраивая AppServer для обработки всех запросов к index.html, вы должны использовать HashLocationStrategy.
Самый простой способ настройки:
RouterModule.forRoot(routes, { useHash: true })
Вместо:
RouterModule.forRoot(routes)
С HashLocationStrategy ваши URL будут выглядеть следующим образом:
http://server:port/#/path
you can use this solution for mean application
i used ejs as view engine
// 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');
});
and also set in angular- cli .json
"apps": [
{
"root": "src",
"outDir": "views",
it will work fine instead of
app.get('*', function (req, res, next) {
res.sendFile('dist/index.html', { root: __dirname });
});
its creating issue with get db calls and returning index.html
Для тех из нас, кто переживает жизнь в 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
Это перенаправляет файл 404 в файл /index.html в соответствии с предложением в документе Angular 2 (ссылка выше).
Я хотел сохранить URL-адрес вспомогательных страниц в режиме HTML5 без перенаправления обратно в индекс, и ни одно из решений там не рассказывало мне, как это сделать, так вот как я это сделал:
Создайте простые виртуальные каталоги в 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 семени, как это работает.
Вы можете использовать express-history-api-fallback для автоматической переадресации при перезагрузке страницы.
Я думаю, что это самый элегантный способ решить эту проблему IMO.
Если вы хотите использовать PathLocationStrategy:
Одностраничное приложение с Java EE/Wildfly: настройка на стороне сервера
Вы можете попробовать ниже. Это работает для меня!
main.component.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), чтобы разбить на параметры маршрутизатора. Я использую angular 2.4.9
Это неправильный ответ, но On-refresh вы можете перенаправить все мертвые звонки на главную страницу, жертвуя 404 страницей, это временный взлом, просто повторяющийся после файла 404.html
<!doctype html>
<html>
<head>
<script type="text/javascript">
window.location.href = "http://" + document.location.host;
</script>
</head>
</html>
Лучшим решением проблемы "роутер-не-работа на перезагрузке-браузером" является то, что мы должны использовать спа-спад. Если вы используете приложение angular2 с ядром asp.net, нам необходимо определить его на странице "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" });
});
2017-July-11: Поскольку это связано из вопроса, имеющего эту проблему, но используя Angular 2 с Electron, я добавлю свое решение здесь.
Все, что мне нужно было сделать, это удалить <base href="./">
из моего index.html, и Electron снова перезагрузил страницу.
Ответ довольно сложный. Если вы используете простой старый Apache Server (или IIS), возникает проблема, потому что страницы Angular не существуют на самом деле. Они "вычисляются" из маршрута Angular.
Существует несколько способов устранения проблемы. Один из них - использовать HashLocationStrategy, предлагаемый Angular. Но в 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
- это значение, сохраненное в HREF вашего Angular index.html
.
Принцип довольно прост, если Apache не находит страницу, перенаправление 404 делается на PHP script. Мы просто проверяем, находится ли страница в каталоге приложения Angular. Если это так, мы просто загружаем index.html напрямую (без перенаправления): это необходимо для сохранения URL-адреса без изменений. Мы также изменяем код HTTP от 404 до 200 (лучше для сканеров).
Что делать, если страница не существует в приложении Angular? Ну, мы используем "catch all" маршрутизатора Angular (см. Документацию маршрутизатора Angular).
Этот метод работает со встроенным приложением Angular на базовом веб-сайте (я думаю, что это будет в будущем).
ПРИМЕЧАНИЯ:
mod_redirect
(путем переписывания URL-адресов) вовсе не является хорошим решением, потому что файлы (например, активы) должны быть действительно загружены, то это гораздо более рискованно, чем просто использование "не найдено" ".ErrorDocument 404 /dist/index.html
работает, но Apache все еще отвечает кодом ошибки 404 (что плохо для искателей).Это не постоянное исправление проблемы, но более похоже на обходной путь или взлом
У меня возникла такая же проблема при развертывании моего приложения Angular на gh-страницах. Сначала я был встречен 404 сообщениями при обновлении моих страниц на gh-страницах.
Затем, как заметил @gunter, я начал использовать HashLocationStrategy
, который был снабжен Angular 2.
Но пришла с собой собственный набор проблем #
в URL-адресе, который был действительно плохим, так что url выглядел странно, как этот https://rahulrsingh09.github.io/AngularConcepts/#/faq
.
Я начал изучать эту проблему и наткнулся на блог. Я попытался дать ему шанс, и это сработало.
Вот что я сделал, как упоминалось в этом блоге.
Вам нужно начать с добавления файла 404.html в репозиторий gh-pages который содержит пустой HTML-документ внутри него, но ваш документ должен содержать более 512 байт (объясняется ниже). Затем поставьте следующая разметка в вашем элементе заголовка страницы размером 404.html:
<script>
sessionStorage.redirect = location.href;
</script>
<meta http-equiv="refresh" content="0;URL='/REPO_NAME_HERE'"></meta>
Этот код устанавливает попытку ввода URL-адреса переменной на стандартный объект sessionStorage и сразу перенаправляет на ваш project index.html, используя тег meta refresh. Если вы делаете Сайт организации Github, не помещайте имя репо в контент текст-заменитель атрибута, просто выполните это: content = "0; URL = '/'"
Чтобы захватить и восстановить URL-адрес, с которого пользователь сначала перешел to, вам нужно добавить следующий тег script в голову вашего index.html перед тем, как любой другой JavaScript действует на текущих страницах состояние:
<script>
(function(){
var redirect = sessionStorage.redirect;
delete sessionStorage.redirect;
if (redirect && redirect != location.href) {
history.replaceState(null, null, redirect);
}
})();
</script>
Этот бит JavaScript возвращает URL-адрес, который мы кэшировали в sessionStorage на странице 404.html и заменяет текущую запись истории он.
Ссылка backalleycoder Благодаря @Daniel для этого обходного пути.
Теперь приведенный выше URL-адрес изменяется на https://rahulrsingh09.github.io/AngularConcepts/faq
Angular приложения - идеальные кандидаты для работы с простым статическим HTML-сервером. Вам не нужен серверный механизм для динамической компоновки страниц приложений, поскольку Angular делает это на стороне клиента.
Если приложение использует маршрутизатор Angular, вы должны настроить сервер для возврата страницы хоста приложения (index.html) при запросе файла, которого у него нет.
Маршрутизируемое приложение должно поддерживать "глубокие ссылки". Глубокая ссылка - это URL-адрес, указывающий путь к компоненту внутри приложения. Например, http://www.example.com/heroes/42 является глубокой ссылкой на страницу подробностей героя, которая отображает героя с id: 42.
Нет проблем, когда пользователь переходит к этому URL-адресу из работающего клиента. Маршрутизатор Angular интерпретирует URL-адрес и маршрутизирует эту страницу и героя.
Но нажав ссылку в сообщении электронной почты, введя ее в адресной строке браузера или просто обновляя браузер на странице подробностей героя, все эти действия обрабатываются самим браузером, за пределами запущенного приложения. Браузер делает прямой запрос на сервер для этого URL-адреса, минуя маршрутизатор.
Статический сервер обычно возвращает index.html, когда он получает запрос http://www.example.com/. Но он отклоняет http://www.example.com/heroes/42 и возвращает ошибку 404 - Not Found, если она не настроена на возврат index.html вместо
Если эта проблема возникла в процессе производства, выполните следующие шаги
1) Добавьте файл Web.Config в папку src вашего приложения Angular. Поместите в него код ниже.
<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",
"favicon.ico",
"Web.config"
],
3) Теперь вы можете построить решение для производства, используя
ng build --prod
Это создаст папку dist. Файлы в папке dist готовы для развертывания в любом режиме.
Ответ Саймона был верным для меня. Я добавил этот код:
app.get('*', function(req, res, next) {
res.sendfile("dist/index.html");
});