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

190

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

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

Винз и Тонз
источник
1
Я полагаю, это stackoverflow.com/questions/16569841
Гюнтер Цохбауэр
Спасибо за ответ, но это для угловых версий 1.x. Я сталкиваюсь с проблемой в угловой 2.0.
Винц и Тонз
1
Связанный вопрос - это общая проблема с pushState, а не Angular. Ваш вопрос не содержит достаточно информации, чтобы знать, связан ли он.
Гюнтер Цохбауэр
5
В Angular 2.0 используется совершенно новый маршрутизатор, поэтому связанный пост теперь бесполезен, поскольку это старый маршрутизатор
Vinz and Tonz
Как я уже сказал, если это проблема pushState, она не является специфичной для Angular и не может быть исправлена ​​Angular, но вместо этого должна быть исправлена ​​на сервере.
Гюнтер Цохбауэр

Ответы:

141

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

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

  1. используя live-сервер: https://www.npmjs.com/package/live-server

    $live-server --entry-file=index.html`
    
  2. используя nginx: http://nginx.org/en/docs/beginners_guide.html

    error_page 404 /index.html
    
  3. Tomcat - настройка файла web.xml. Из комментария Кунина

    <error-page>
          <error-code>404</error-code>
          <location>/index.html</location>
    </error-page>
    
Quy Tang
источник
1
Поскольку для маршрутизации html5 требуется поддержка на стороне сервера, это прекрасно работает. Спасибо
Прабхат
Могу ли я использовать nginx в качестве прокси для pub serve? Таким образом, мне не нужно pub buildмного во время разработки. Я пытался, но proxy_passне очень хорошо работает с error_page.
Франклин Ю
@FranklinYu Я не делал этого раньше. Вы понимаете это?
Quy Tang
1
Используя nginx. , error_page 404 /index.html в расположении приложения работал для меня. Спасибо.
Ричард К. Кэмпион
2
Tomcat - настройка файла web.xml <страница ошибки> <код ошибки> 404 </ error-code> <местоположение> /index.html </ location> </ error-page>
Кунин
65

Отказ от ответственности: это исправление работает с Alpha44

У меня была та же проблема, и я решил ее, реализовав HashLocationStrategy, указанный в предварительной версии Angular.io API.

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

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

SimonHawesome
источник
1
этот код будет работать нормально, но в этом методе есть некоторая проблема, использование которой #будет автоматически добавлено в URL. Есть ли решение, чтобы удалить # из URL с помощью этого?
Пардип Джейн
Согласен, я попытался реализовать перечисленную здесь PathLocationStrategy , но не смог заставить ее работать. URL без #будет оптимальным.
SimonHawesome
Да, я тоже попробовал то же самое с, PathLocationStrategyно это не работает для меня. Либо я использовал неправильный метод, либо я не знаю, как использовать PathLocationStrategy.
Пардип Джейн
1
Это не работает для меня в RC1. Не удается импортировать LocationStrategy, HashLocationStrategy из '@ angular / router'.
infojolt
1
Извините, что вернулся к этим вопросам спустя более 1 года :) Но помогает ли HashLocationStrategy оставаться на том же пути маршрутизатора? В моем случае, когда я обновляюсь, он переводит меня на localhost / # / < маршрут по умолчанию >, то есть маршрут по умолчанию для домашней страницы. Как мне перейти к текущему маршруту, по которому я был изначально, когда я «обновился»?
Раджугааду
47

Angular по умолчанию использует HTML5 pushstate ( 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 критические изменения

Гюнтер Цохбауэр
источник
1
Спасибо! кажется, что поставка переместилась под angular / core: import {provide} из 'angular2 / core'
StrangeLoop
1
Просто чтобы заметить: update for >= RC.x(RC.2) работает router 3.0.0-alpha.7, но помечен provideкак устаревший без информации о том, какая функция его заменила.
Mrusful
Использование{provide: SomeClass, useClass: OtherClass}
Гюнтер Цохбауэр
2
Самый обновленный ответ. Для последней версии Angular 2.4.1 у меня было <base href = "./">. Перейдя в <base href = "/">, я решил проблему. Может быть полезно для кого-то.
Сайяфф Фарук
28

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

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

Саймон
источник
7
так как мы можем это исправить? как мы сопоставляем все запросы с основным индексом по умолчанию? это зависит от сервера?
Ayyash
1
Да, вы должны делать это на сервере с любой веб-платформой, которую вы используете. Альтернативой является использование HashLocationStrategy, как описано ниже.
Симон
Вы будете перезагружать угловой SPA на каждом не существующем маршруте. Это как с этим надо обращаться?
Гэри
Он перезагружается только в том случае, если пользователь нажимает кнопку «Обновить» в браузере, а не когда пользователь изменяет маршруты через пользовательский интерфейс. На самом деле нет никакого способа перезагрузки, когда пользователь обновляется.
Уоллес Ховери
19

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

Что происходит, что URL в строке браузера является нормальным полным HTML URL, как, например: http://localhost/route.

Поэтому, когда мы нажимаем Enter на панели браузера, на сервер отправляется фактический HTTP-запрос для получения файла с именем route.

На сервере такого файла нет, и на сервере не настроено что-то вроде express для обработки запроса и предоставления ответа, поэтому сервер возвращает 404 Not Found, поскольку не смог найти routeфайл.

Мы хотим, чтобы сервер возвращал index.htmlфайл, содержащий одностраничное приложение. Затем маршрутизатор должен запустить и обработать /routeURL-адрес и отобразить сопоставленный ему компонент.

Таким образом, чтобы решить эту проблему, нам нужно настроить сервер на возврат index.html(при условии, что это имя вашего одностраничного файла приложения) в случае, если запрос не может быть обработан, в отличие от 404 Not Found.

Способ сделать это будет зависеть от используемой технологии на стороне сервера. Например, если это Java, вам может понадобиться написать сервлет, в Rails он будет другим и т. Д.

Чтобы привести конкретный пример, если, например, вы используете NodeJ, вам нужно написать промежуточное программное обеспечение, например:

function sendSpaFileIfUnmatched(req,res) {
    res.sendFile("index.html", { root: '.' });
}

А затем зарегистрируйте его в самом конце цепочки промежуточного программного обеспечения:

app.use(sendSpaFileIfUnmatched);

Это будет служить index.htmlвместо возврата 404, маршрутизатор сработает, и все будет работать, как ожидалось.

Угловой университет
источник
Это была именно моя проблема. Если вы используете NGINX, этот ответ поможет решить эту проблему: stackoverflow.com/questions/7027636/…
Натан
Есть ли учебник о том, как сделать это для Java? Спасибо.
000000000000000000000
13

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

<base href="https://stackoverflow.com/">

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

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

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

user2263572
источник
Спасибо, что поделились этим. Давайте просто поясним, что это сработало только для меня, когда я поместил <base href = "/"> непосредственно после загрузки всех css в <head> и перед загрузкой ЛЮБЫХ Js-файлов. Надеюсь, это кому-нибудь поможет
wmehanna
у меня есть <base href = "./"> в index.html, а затем удален '.' от HREF и он работал ..
Саурабе Solanki
10

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

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

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

Вместо того:

RouterModule.forRoot(routes)

С HashLocationStrategy ваши URL будут выглядеть так:

http://server:port/#/path
felipecrp
источник
Спасибо! это помогает, но я не хочу #от URL, мы можем удалить это?
Хидайт Рахман
7

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

Решение:

// in webpack
devServer: {
    historyApiFallback: true,
    stats: 'minimal'
}
angmerica
источник
Вид магии вуду: p Для получения дополнительной информации см .: webpack.github.io/docs/…
Jissay
7

Если вы используете Apache или Nginx в качестве сервера, вы должны создать .htaccessRewriteEngine (если он не был создан ранее) и «On»

RewriteEngine On  
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html
Ракеш Рой
источник
Не получил ваш вопрос, этот метод проверен на сервере Apache и Nginx ( nginx.com )
Ракеш Рой
1
Это только для Apache; Формат конфигурации Nginx совершенно другой.
Франклин Ю
5

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

Вилли Z
источник
4

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

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

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

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

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

Gary
источник
4

для angular 5 quick fix, отредактируйте app.module.ts и добавьте {useHash:true}после appRoutes.

@NgModule(
{
  imports:[RouterModule.forRoot(appRoutes,{useHash:true})]
})
Адеш Шах
источник
3

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 - Не найдено, если только он не настроен на возврат index.html.

Если эта проблема возникла в производстве, выполните следующие действия

1) Добавьте файл Web.Config в папку src вашего углового приложения. Поместите ниже код в нем.

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

Малатеш Патил
источник
Лучшее решение - узнать подробности из angular: angular.io/guide/deployment#fallback. При создании файла web.config не забудьте добавить тег <configuration> </ configuration>. Спасибо за ответ, Малатеш.
Палаш Рой
3

Вы можете использовать это решение для среднего приложения, я использовал ejs в качестве движка представления:

// 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');
});

а также установить в angular-cli.json

"apps": [
    {
      "root": "src",
      "outDir": "views",

это будет нормально работать вместо

app.get('*', function (req, res, next) {
    res.sendFile('dist/index.html', { root: __dirname });
 });

проблема создания с вызовами get db и возвращением index.html

Шоаиб Куреши
источник
1
Это отлично сработало в октябре 2017 года для стекового приложения MEAN.
Mindsect Team
2

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

Джим Хьюм
источник
2

Вы можете попробовать ниже. Меня устраивает!

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) для разделения на параметры маршрутизатора. Я использую угловой 2.4.9

kaifeong
источник
Это было действительно полезно для обработки обновлений браузера! Для углового 5 мне пришлось немного изменить его, чтобы использовать window.location.pathname, и сравнить это значение с ожидаемыми путями.
Уоллес Ховери
2

Я просто добавляю .htaccess в корень.

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

здесь я просто добавляю точку '.' (родительский каталог) в /index.html в ./index.html,
чтобы убедиться, что ваш файл index.html в базовом пути является основным путем к каталогу и задан в сборке проекта.

хадия випул
источник
1

Я хотел сохранить 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>
Девин Маккуини
источник
1

Я проверил в угловых 2 семян, как это работает.

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

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

Lievno
источник
1

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

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

Одностраничное приложение с Java EE / Wildfly: конфигурация на стороне сервера

nkeymeulen
источник
1

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

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

TimTheEnchanter
источник
1

Добавить импорт:

import { HashLocationStrategy, LocationStrategy } from '@angular/common';

А в провайдере NgModule добавьте:

providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]

В основном index.html файле приложения измените базовый href ./index.htmlс/

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

Debargho24
источник
1

Простое добавление .htaccess в root разрешило 404 при обновлении страницы в angular 4 apache2.

<IfModule mod_rewrite.c>
    RewriteEngine on

    # Don't rewrite files or directories
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]

    # Rewrite everything else to index.html
    # to allow html5 state links
    RewriteRule ^ index.html [L]
</IfModule>
a_k_v
источник
1

Я думаю, что вы получаете 404, потому что вы запрашиваете http: // localhost / route, которого нет на сервере tomcat. Поскольку Angular 2 использует маршрутизацию html 5 по умолчанию, а не использует хэши в конце URL, обновление страницы выглядит как запрос другого ресурса.

При использовании угловой маршрутизации на tomcat вам необходимо убедиться, что ваш сервер будет сопоставлять все маршруты в вашем приложении с вашим основным index.html при обновлении страницы. Есть несколько способов решить эту проблему. Что бы ни подходило вам, вы можете пойти на это.

1) Поместите приведенный ниже код в web.xml вашей папки развертывания:

<error-page>
     <error-code>404</error-code>
     <location>/index.html</location>
</error-page>

2) Вы также можете попробовать использовать HashLocationStrategy с # в URL для маршрутов:

Попробуйте использовать:

RouterModule.forRoot (маршруты, {useHash: true})

Вместо того:

RouterModule.forRoot (маршруты)

С HashLocationStrategy ваши URL будут выглядеть так:

HTTP: // локальный / # / маршрут

3) Tomcat URL Rewrite Valve: переписать URL-адреса, используя конфигурацию на уровне сервера, чтобы перенаправить на index.html, если ресурс не найден.

3.1) Внутри папки META-INF создайте файл context.xml и скопируйте нижеприведенный контекст внутри него.

<? xml version='1.0' encoding='utf-8'?>
<Context>
  <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
</Context>

3.2) Внутри WEB-INF создайте файл rewrite.config (этот файл содержит правило перезаписи URL и используется tomcat для перезаписи URL). Внутри rewrite.config скопируйте содержимое ниже:

  RewriteCond %{SERVLET_PATH} !-f
  RewriteRule ^/(.*)$ /index.html [L]
каран ханна
источник
0

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

<!doctype html>
<html>
    <head>
        <script type="text/javascript">
            window.location.href = "http://" + document.location.host;
        </script>
    </head>
</html>
don625
источник
0

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

Ответ довольно хитрый. Если вы используете простой старый сервер Apache (или IIS), вы получите проблему, потому что страницы Angular не существуют на самом деле. Они «вычисляются» из углового маршрута.

Есть несколько способов решить проблему. Одним из них является использование HashLocationStrategy, предлагаемой Angular. Но в URL добавлен четкий знак. Это в основном для совместимости с Angular 1 (я предполагаю). Дело в том, что часть после резкого не является частью URL (тогда сервер разрешает часть до знака "#"). Это может быть прекрасно.

Здесь расширенный метод (на основе трюка 404). Я предполагаю, что у вас есть «распределенная» версия вашего углового приложения ( ng build --prodесли вы используете Angular-CLI), и вы получаете доступ к страницам напрямую с вашего сервера, и PHP включен.

Если ваш веб-сайт основан на страницах (например, Wordpress), и у вас есть только одна папка, посвященная Angular (в моем примере с именем «dist»), вы можете сделать что-то странное, но, в конце концов, простое. Я предполагаю, что вы сохранили свои угловые страницы в "/ dist" (с соответствующим <BASE HREF="/dist/">). Теперь используйте перенаправление 404 и помощь PHP.

В вашей конфигурации Apache (или в .htaccessфайле вашего углового каталога приложения) вы должны добавить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 вашего угла index.html.

Принцип довольно прост: если Apache не находит страницу, в скрипт PHP делается перенаправление 404. Мы просто проверяем, находится ли страница внутри каталога угловых приложений. Если это так, мы просто загружаем index.html напрямую (без перенаправления): это необходимо для сохранения URL-адреса без изменений. Мы также изменили код HTTP с 404 на 200 (лучше для сканеров).

Что делать, если страница не существует в угловом приложении? Ну, мы используем «ловить все» углового маршрутизатора (см. Документацию углового маршрутизатора).

Этот метод работает со встроенным приложением Angular внутри основного веб-сайта (думаю, так будет и в будущем).

НОТЫ:

  • Попытка сделать то же самое с mod_redirect(путем переписывания URL-адресов) вовсе не является хорошим решением, поскольку файлы (например, ресурсы) должны быть действительно загружены, тогда это намного более рискованно, чем просто использование решения «не найдено».
  • Просто перенаправление с использованием ErrorDocument 404 /dist/index.htmlработает, но Apache все еще отвечает с кодом ошибки 404 (что плохо для сканеров).
Уильям Р
источник
0

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

У меня была такая же проблема при развертывании моего Angular App на gh-страницах. Сначала меня встретили 404 сообщениями при обновлении моих страниц на gh-страницах.

Тогда, как указал @gunter, я начал использовать, HashLocationStrategyкоторый был предоставлен в Angular 2.

Но это связано с его собственным набором проблем: #в URL это было действительно плохо, поэтому URL выглядел странно https://rahulrsingh09.github.io/AngularConcepts/#/faq.

Я начал исследовать эту проблему и наткнулся на блог. Я попытался дать ему шанс, и это сработало.

Вот что я сделал, как упоминалось в этом блоге.

Вам нужно начать с добавления файла 404.html в репозиторий gh-pages, в котором содержится пустой HTML-документ, но объем вашего документа должен превышать 512 байт (объясняется ниже). Затем поместите следующую разметку в элемент head вашей страницы 404.html:

<script>
  sessionStorage.redirect = location.href;
</script>
<meta http-equiv="refresh" content="0;URL='/REPO_NAME_HERE'"></meta>

Этот код устанавливает переменную URL-адреса попытки входа в стандартную переменную объекта sessionStorage и немедленно перенаправляет на страницу index.html вашего проекта с помощью мета-тега refresh. Если вы работаете с сайтом Github Organization, не помещайте имя репо в текст заменителя атрибута контента, просто сделайте это: content = "0; URL = '/'"

Чтобы захватить и восстановить URL-адрес, на который изначально перешел пользователь, вам нужно добавить следующий тег сценария в заголовок страницы 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

Рахул Сингх
источник
0

Я исправил это (используя бэкэнд Java / Spring), добавив обработчик, который соответствует всем определенным в моих маршрутах Angular, который отправляет index.html вместо 404. Затем он эффективно (повторно) загружает приложение и загружает правильную страницу. У меня также есть обработчик 404 для всего, что не поймано этим.

@Controller         ////don't use RestController or it will just send back the string "index.html"
public class Redirect {

    private static final Logger logger = LoggerFactory.getLogger(Redirect.class);

    @RequestMapping(value = {"comma", "sep", "list", "of", "routes"})
    public String redirectToIndex(HttpServletRequest request) {
        logger.warn("Redirect api called for URL {}. Sending index.html back instead. This will happen on a page refresh or reload when the page is on an Angular route", request.getRequestURL());
        return "/index.html";
    }
}
Ли Уиллис
источник
0

Если вы используете Apache или Nginx в качестве сервера, вам нужно создать .htaccess

<IfModule mime_module>
      AddHandler application/x-httpd-ea-php72 .php .php7 .phtml
    </IfModule>
    # php -- END cPanel-generated handler, do not edit

    <IfModule mod_rewrite.c>
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html
        # to allow html5 state links
        RewriteRule ^ index.html [L]
    </IfModule>
Мукеш Кумар Биярния
источник