Режим AngularJS HTML5 - Как прямые ссылки работают без изменений на сервере?
Примечание. Этот вопрос также может быть прочитан:
Как поддерживать закладок безвредных клиентских сторон mvc-фреймворков в Java.
Я перехожу к приложению angular, использующему hashtags
к html5mode
. Я успешно установил
$locationProvider.html5Mode(true);
И все ссылки с целевой страницы (index.html) работают нормально.
Проблема в том, что если частичные URL-адреса ссылаются напрямую, я получаю 404, естественно, поскольку определения конечных точек сервера не связаны с определенными на стороне клиента маршрутами.
Таким образом, без HTML5 мы получаем не-SEO дружественные hashbangs, но с ним мы не можем добавлять закладки ничего, кроме целевой страницы (страница, которая загружается angular).
Почему это работает, если сначала запрашивать целевую страницу по умолчанию (index.html), то есть htpp://mydomain.com/:
- Браузер запрашивает index.html с сервера
- Сервер возвращает index.html, а браузер загружает angular framework
- Изменения URL-адреса отправляются на клиентский маршрутизатор и загружаются соответствующие частичные /s.
Почему это не работает, если (т.е.) http://mydomain.com/foo запрашивается непосредственно из браузера:
- Браузер запрашивает mydomain/foo с сервера.
- Ресурс не существует
- Сервер возвращает 404
Что-то не хватает в этой истории, я просто не знаю, что. Вот только два ответа, которые я вижу...
- Это по дизайну. Как это работает? Пользователи должны всегда приземляться на странице начальной загрузки платформы MVC (обычно index.html), а затем перемещаться оттуда. Это не идеально, потому что состояние не может быть сохранено, и нет возможности закладки... не говоря уже об обходе.
- Серверное решение.. Работает ли это с помощью уловки на стороне сервера? Например, по всем запросам верните index.html и сразу вызовите маршрутизатор с дополнительным контекстом. Если это так, это противоречит объекту, что AngularJS полностью на стороне клиента и кажется взломанным.
Ответы
Ответ 1
Документация AngularJS действительно упоминает об этом
Сторона сервера. В этом режиме требуется переписывание URL-адресов на стороне сервера, в основном вы должны переписать все свои ссылки на точку входа приложения (например, index.html)
В этом случае одно решение на основе Java должно сказать серверу "сопоставить все URL-адреса с index.html". Это можно сделать на любом HTTP-сервере или в контейнере. Я реализовал это с помощью Java/Servet, так как я хочу, чтобы мое приложение было агностическим сервером HTTP (например, Apache или NginX, или только Tomcat/JBoss).
В web.xml:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>StaticServlet</servlet-name>
<jsp-file>/index.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>StaticServlet</servlet-name>
<url-pattern>/app</url-pattern>
</servlet-mapping>
И index.jsp выглядит просто:
<%@ include file="index.html" %>
И добавьте следующее в тег в index.html:
<base href="/app" />
Ответ 2
Я некоторое время думал об этом для своего сайта PHP. Я держу весь код на стороне сервера с маршрутом /api, чтобы сохранить его отдельно от Angular. Вот решение, которое я придумал, обновив конфигурацию apache:
RewriteEngine on
#let the php framework do its thing
RewriteRule ^(api/.*)$ index.php?url=$1 [QSA,L,NC]
#let angular do its thing
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) index.html [NC,L]
Я написал, как я это сделал, используя фреймворк Flight Framework на http://www.awnage.com/2013/10/10/taking-flight-with-angularjs/
Ответ 3
URL-адреса, на которые вы ссылаетесь, и помещаете их в адресную строку пользователя, должны ссылаться на допустимый контент на сервере, и, если это вообще возможно, они должны ссылаться на правильный контент. Конечно, вы можете просто обслуживать одну и ту же страницу для каждого URL-адреса, а клиентский код отключается и загружать реальный контент, и все работает так же, как в мире хеш-URL. Фактически, это способ наименьшего кода. Но он также квалифицируется как "взлом интернета", поэтому HTML5 и API истории предоставляют вам способ ссылки на семантически корректные URL-адреса.
В качестве небольшого примера, если вы перейдете к https://github.com/kriskowal/q, и вы нажмете "примеры", клиентский код загрузит "примеры" в браузере файлов, не выходя из страницы, а строка URL будет читать https://github.com/kriskowal/q/tree/master/examples. Если вы перейдете в https://github.com/kriskowal/q/tree/master/examples напрямую, вы получите содержимое каталога примеров, отправленное непосредственно в ваш браузер, без посредничества на стороне клиента, Да, это сложнее сделать и, возможно, невозможно в "приложении с одной страницей", но это правильно сделать в любое время, когда это возможно.