Angular 2.0 маршрутизатор не работает при перезагрузке браузера

Я использую версию Angular 2.0.0-alpha.30. При перенаправлении на другой маршрут обновите браузер, показывая, что он не может GET/route.

Можете ли вы помочь мне понять, почему эта ошибка произошла.

Ответ 1

Ошибка, которую вы видите, заключается в том, что вы запрашиваете http://localhost/route, который не существует. Согласно Саймон.

При использовании маршрутизации html5 вам необходимо отобразить все маршруты в вашем приложении (в настоящее время 404) на index.html на вашей стороне сервера. Вот несколько вариантов для вас:

Ответ 2

Отказ от ответственности: это исправление работает с 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, и при обновлении он перезагрузится в нужном месте.

Надеюсь, что это поможет!

Ответ 3

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

Ответ 4

Я думаю, что ошибка, которую вы видите, связана с тем, что вы запрашиваете http://localhost/route, который не существует. Вы должны убедиться, что ваш сервер будет отображать все запросы на главную страницу index.html.

Поскольку Angular 2 использует html5-маршрутизацию по умолчанию, а не использование хэшей в конце URL-адреса, обновление страницы выглядит как запрос для другого ресурса.

Ответ 5

Это обычная ситуация во всех версиях маршрутизатора, если вы используете стратегию определения местоположения по умолчанию.

Что происходит, так это то, что 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, маршрутизатор начнет работать, и все будет работать так, как ожидалось.

Ответ 6

Убедитесь, что это помещено в элемент head вашего index.html:

<base href="/">

Example в документации Angular2 Маршрутизация и Навигация использует следующий код в (они объясняют, почему в живом примере примечание документации):

<script>document.write('<base href="' + document.location + '" />');</script>

Когда вы обновляете страницу, это будет динамически устанавливать базовый href в текущую документацию. Я мог видеть, что это вызывает некоторую путаницу, когда люди просматривают документацию и пытаются воспроизвести плункер.

Ответ 7

У меня была такая же проблема с использованием webpack-dev-сервера. Мне пришлось добавить параметр devServer в свой веб-пакет.

Решение:

// in webpack
devServer: {
    historyApiFallback: true,
    stats: 'minimal'
}

Ответ 8

Если вы используете Apache в качестве сервера, вам нужно создать .htaccess (если не созданный ранее) и "On" RewriteEngine

    RewriteEngine On  
      RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
      RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
      RewriteRule ^ - [L]
      RewriteRule ^ /index.html

Ответ 9

Мой сервер 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.

Ответ 10

Конфигурация сервера не является решением для SPA, что я даже думаю. Вы не хотите повторно загружать SPA angular, если приходит неправильный маршрут, не так ли? Поэтому я не буду зависеть от маршрута сервера и перенаправлять на другой маршрут, но да, я передам index.html все запросы для angular маршрутов пути angular.

Попробуйте это вместо других или неправильных маршрутов. Он работает для меня, не уверен, но кажется, что работа продолжается. Наткнулся на это сам, столкнувшись с проблемой.

@RouteConfig([
  { path: '/**', redirectTo: ['MycmpnameCmp'] }, 
   ...
  }
])

https://github.com/angular/angular/issues/4055

Однако не забудьте настроить папки вашего сервера и права доступа, если у вас есть HTML или веб-скрипты, которые не являются СПА. Иначе вы столкнетесь с проблемами. Для меня, когда вы столкнулись с проблемой, подобной вам, это было сочетание конфигурации сервера и выше.

Ответ 11

Если вы хотите вводить URL-адреса в браузере, не настраивая AppServer для обработки всех запросов к index.html, вы должны использовать HashLocationStrategy.

Самый простой способ настройки:

RouterModule.forRoot(routes, { useHash: true })

Вместо:

RouterModule.forRoot(routes)

С HashLocationStrategy ваши URL будут выглядеть следующим образом:

http://server:port/#/path

Ответ 12

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

Ответ 13

Для тех из нас, кто переживает жизнь в 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 (ссылка выше).

Ответ 14

Я хотел сохранить 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>

Ответ 15

Я проверил в angular 2 семени, как это работает.

Вы можете использовать express-history-api-fallback для автоматической переадресации при перезагрузке страницы.

Я думаю, что это самый элегантный способ решить эту проблему IMO.

Ответ 16

Если вы хотите использовать PathLocationStrategy:

  • Конфигурация Wildfly:
    • Создайте файл ento-handlers.conf, который будет размещен в WEB-INF
    • Содержание: (исключайте конечные точки отдыха!)
      • regex ['(./overview/?.?$)'], а не regex ['(./endpoints.)'] → rewrite ['/index.html']
      • regex ['(./deployments/?.?$)'], а не regex ['(./endpoints.)'] → rewrite ['/index.html']

Одностраничное приложение с Java EE/Wildfly: настройка на стороне сервера

Ответ 17

Вы можете попробовать ниже. Это работает для меня!

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

Ответ 18

Это неправильный ответ, но On-refresh вы можете перенаправить все мертвые звонки на главную страницу, жертвуя 404 страницей, это временный взлом, просто повторяющийся после файла 404.html

<!doctype html>
<html>
    <head>
        <script type="text/javascript">
            window.location.href = "http://" + document.location.host;
        </script>
    </head>
</html>

Ответ 19

Лучшим решением проблемы "роутер-не-работа на перезагрузке-браузером" является то, что мы должны использовать спа-спад. Если вы используете приложение 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" });
        });

Ответ 20

2017-July-11: Поскольку это связано из вопроса, имеющего эту проблему, но используя Angular 2 с Electron, я добавлю свое решение здесь.

Все, что мне нужно было сделать, это удалить <base href="./"> из моего index.html, и Electron снова перезагрузил страницу.

Ответ 21

Ответ довольно сложный. Если вы используете простой старый 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 (что плохо для искателей).

Ответ 22

Это не постоянное исправление проблемы, но более похоже на обходной путь или взлом

У меня возникла такая же проблема при развертывании моего приложения 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

Ответ 23

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 готовы для развертывания в любом режиме.

Ответ 24

Ответ Саймона был верным для меня. Я добавил этот код:

app.get('*', function(req, res, next) {
  res.sendfile("dist/index.html");
});