Каковы рекомендации для HTML-тега <base>?

Я никогда не видел <base> HTML-тег на самом деле раньше использовался где угодно. Есть ли подводные камни для его использования, что означает, что я должен избегать этого?

Тот факт, что я никогда не замечал его использования на современном производственном сайте (или на любом другом сайте), заставляет меня опасаться этого, хотя кажется, что у него могут быть полезные приложения для упрощения ссылок на моем сайте.


редактировать

После использования базового тега в течение нескольких недель я обнаружил несколько основных проблем с использованием базового тега, которые делают его гораздо менее желательным, чем он показался на первый взгляд. По сути, изменения в href='#topic' а также href='' под тегом base очень несовместимы с их поведением по умолчанию, и это изменение поведения по умолчанию может легко сделать сторонние библиотеки вне вашего контроля непредсказуемым образом, так как они будут логически зависеть от поведения по умолчанию. Часто изменения неуловимы и приводят к неочевидным проблемам при работе с большой кодовой базой. С тех пор я создал ответ с подробным описанием проблем, с которыми столкнулся ниже. Поэтому проверьте сами результаты ссылки, прежде чем приступить к широкому распространению <base> Это мой новый совет!

18 ответов

Решение

Разбивка эффектов базового тега:

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

Я буду использовать базовый тег: <base href="http://www.example.com/other-subdirectory/"> как мой пример в приведенных ниже случаях, и будет делать вид, что страница, на которой находится код, является http://localsite.com/original-subdirectory

Основной:

Никакие ссылки или именованные якоря или пустые ссылки не будут указывать на исходный подкаталог, если это не указано явно: базовый тег делает все ссылки по-разному, в том числе ссылки на одну и ту же страницу на URL базового тега, например:

  • <a href='#top-of-page' title='Some title'>A link to the top of the page via a named anchor</a>
    становится
    <a href='http://www.example.com/other-subdirectory/#top-of-page' title='Some title'>A link to an #named-anchor on the completely different base page</a>

  • <a href='?update=1' title='Some title'>A link to this page</a>
    становится
    <a href='http://www.example.com/other-subdirectory/?update=1' title='Some title'>A link to the base tag's page instead</a>

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

Незначительный:

Исправление IE6, требующее условных комментариев: Требует условных комментариев для ie6, чтобы избежать путаницы в иерархии dom, т.е. <base href="http://www.example.com/"><!--[if lte IE 6]></base><![endif]--> как BalusC упоминает в своем ответе выше.

Итак, в целом, основная проблема заключается в использовании хитрости, если у вас нет полного контроля над редактированием каждой ссылки, и, как я изначально опасался, это создает больше проблем, чем стоит. Теперь я должен уйти и переписать все мои использования этого!:п

Ссылки по теме тестирования на проблемы при использовании "фрагментов" / хэшей:

http://www.w3.org/People/mimasa/test/base/

http://www.w3.org/People/mimasa/test/base/results


Редактировать Иззи: Для всех вас, сталкивающихся с той же путаницы, что и я в отношении комментариев:

Я только что проверил это сам, со следующими результатами:

  • косая черта или нет, не имеет значения для приведенных здесь примеров (#anchor а также ?query будет просто добавлен к указанному <BASE>).
  • Это, однако, имеет значение для относительных ссылок: исключая косую черту, other.html а также dir/other.html начнется с DOCUMENT_ROOT с приведенным примером, /other-subdirectory будучи (правильно) обработанным как файл и таким образом опущенным.

Так что для относительных ссылок, BASE отлично работает с перемещенной страницей - в то время как якоря и ?queries потребуется, чтобы имя файла было указано явно (с BASE конечная косая черта или последний элемент, не соответствующий имени файла, в котором он используется).

Думайте об этом как <BASE> заменив полный URL-адрес самого файлане каталога, в котором он находится), и вы все поймете правильно. Предполагая, что файл, использованный в этом примере, был other-subdirectory/test.html (после того, как он переместился в новое место), правильная спецификация должна была быть:

<base href="http://www.example.com/other-subdirectory/test.html">

- и вуаля, все работает как положено: #anchor, ?query, other.html, very/other.html, /completely/other.html,

Прежде чем решить, следует ли использовать <base> Отметить или нет, вам нужно понять, как это работает, для чего он может использоваться и каковы последствия, и, наконец, перевесить преимущества / недостатки.


<base> tag в основном облегчает создание относительных ссылок на языках шаблонов, так как вам не нужно беспокоиться о текущем контексте в каждой ссылке.

Вы можете сделать, например,

<base href="${host}/${context}/${language}/">
...
<link rel="stylesheet" href="css/style.css" />
<script src="js/script.js"></script>
...
<a href="home">home</a>
<a href="faq">faq</a>
<a href="contact">contact</a>
...
<img src="img/logo.png" />

вместо

<link rel="stylesheet" href="/${context}/${language}/css/style.css" />
<script src="/${context}/${language}/js/script.js"></script>
...
<a href="/${context}/${language}/home">home</a>
<a href="/${context}/${language}/faq">faq</a>
<a href="/${context}/${language}/contact">contact</a>
...
<img src="/${context}/${language}/img/logo.png" />

Обратите внимание, что <base href> значение заканчивается косой чертой, иначе оно будет интерпретироваться относительно последнего пути.


Что касается совместимости браузера, это вызывает только проблемы в IE. <base> тег указан в HTML как не имеющий конечного тега </base>так что законно просто использовать <base> без конечного тега. Однако IE6 думает иначе, и весь контент после <base> тег в таком случае помещается как дочерний элемент <base> элемент в дереве HTML DOM. Это может вызвать на первый взгляд необъяснимые проблемы в Javascript/jQuery/CSS, то есть элементы совершенно недоступны в определенных селекторах, таких как html>bodyдо тех пор, пока вы не обнаружите в инспекторе HTML DOM, что должен быть base (а также head) между.

Обычное исправление IE6 использует условный комментарий IE для включения конечного тега:

<base href="http://example.com/en/"><!--[if lte IE 6]></base><![endif]-->

Если вас не волнует W3 Validator или вы уже используете HTML5, то вы можете просто закрыть его самостоятельно, так или иначе его поддержит каждый веб-браузер:

<base href="http://example.com/en/" />

Закрытие <base> тег также мгновенно исправляет маразм IE6 на WinXP SP3 по запросу <script> ресурсы с относительным URI в src в бесконечном цикле.

Другая потенциальная проблема IE проявится, когда вы используете относительный URI в <base> тег, такой как <base href="//example.com/somefolder/"> или же <base href="/somefolder/">, Это не удастся в IE6/7/8. Это, однако, не совсем вина браузера; используя относительные URI в <base> тэг а именно по своему неправильно. В спецификации HTML4 указано, что это должен быть абсолютный URI, поэтому, начиная с http:// или же https:// схема. Это было опущено в спецификации HTML5. Так что, если вы используете только HTML5 и целевые HTML5-совместимые браузеры, то у вас все будет хорошо, если использовать относительный URI в <base> тег.


Что касается использования именованных / хеш-фрагментов, таких как <a href="#anchor">, якоря строки запроса, такие как <a href="?foo=bar"> и фрагменты пути, как якоря <a href=";foo=bar">с <base> тег вы в основном объявляете все относительные ссылки относительно него, в том числе такого рода якорей. Ни одна из относительных ссылок больше не относится к текущему URI запроса (как это было бы без <base> тег). Это может в первую очередь сбить с толку для начинающих. Чтобы правильно построить эти якоря, вам нужно включить URI,

<a href="${uri}#anchor">hash fragment</a>
<a href="${uri}?foo=bar">query string</a>
<a href="${uri};foo=bar">path fragment</a>

где ${uri} в основном переводится как $_SERVER['REQUEST_URI'] в PHP, ${pageContext.request.requestURI} в JSP и #{request.requestURI} в JSF. Следует отметить, что фреймворки MVC, такие как JSF, имеют теги, уменьшающие весь этот шаблон и устраняющие необходимость <base>, Смотрите также, какой URL использовать для ссылки / перехода на другие страницы JSF.

Ну, подожди минутку. Я не думаю, что базовый тег заслуживает этой плохой репутации.

Хорошая особенность базового тега заключается в том, что он позволяет выполнять сложные перезаписи URL с меньшими хлопотами.

Вот пример. Вы решаете переместить http://example.com/product/category/thisproduct на http://example.com/product/thisproduct. Вы изменяете свой файл.htaccess, чтобы перезаписать первый URL-адрес вторым URL-адресом.

Установив базовый тег, вы переписываете.htaccess и все. Нет проблем. Но без базового тега все ваши относительные ссылки будут сломаны.

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

Чтобы решить, следует ли его использовать или нет, вы должны знать, что он делает и нужно ли это. Это уже частично изложено в этом ответе, которому я также способствовал. Но чтобы было легче понять и следовать, здесь есть второе объяснение. Для начала нам нужно понять:

Как ссылки обрабатываются браузером без <BASE> использовался?

Для некоторых примеров давайте предположим, что у нас есть эти URL:

A) http://www.example.com/index.html
B) http://www.example.com/
C) http://www.example.com/page.html
D) http://www.example.com/subdir/page.html

A + B оба результата в одном и том же файле (index.htmlотправлять в браузер, С конечно отправляет page.htmlи D отправляет /subdir/page.html,

Предположим далее, что обе страницы содержат набор ссылок:

1) полностью определенные абсолютные ссылки (http://www...)
2) локальные абсолютные ссылки (/some/dir/page.html)
3) относительные ссылки, включая имена файлов (dir/page.html), а также
4) относительные ссылки только с "сегментами" (#anchor, ?foo=bar).

Браузер получает страницу и отображает HTML. Если он находит какой-то URL, ему нужно знать, куда его указать. Это всегда понятно для ссылки 1), которая принимается как есть. Все остальные зависят от URL отображаемой страницы:

URL     | Link | Result
--------+------+--------------------------
A,B,C,D |    2 | http://www.example.com/some/dir/page.html
A,B,C   |    3 | http://www.example.com/dir/page.html
D       |    3 | http://www.example.com/subdir/dir/page.html
A       |    4 | http://www.example.com/index.html#anchor
B       |    4 | http://www.example.com/#anchor
C       |    4 | http://www.example.com/page.html#anchor
D       |    4 | http://www.example.com/subdir/page.html#anchor

Теперь, что меняется с <BASE> использовался?

<BASE> должен заменить URL, как он выглядит в браузере. Таким образом, он отображает все ссылки, как если бы пользователь вызвал URL, указанный в <BASE>, Что объясняет некоторую путаницу в нескольких других ответах:

  • опять же, ничего не меняется для "полностью определенных абсолютных ссылок" ("тип 1")
  • для локальных абсолютных ссылок целевой сервер может измениться (если тот, который указан в <BASE> отличается от того, который вызывается изначально от пользователя)
  • относительные URL-адреса становятся критическими, поэтому вы должны быть особенно внимательны <BASE>:
    • лучше не устанавливать его в каталог. При этом ссылки типа "3" могут продолжать работать, но это, безусловно, нарушает ссылки типа 4 (за исключением случая В).
    • установка полного имени файла дает, в большинстве случаев, желаемые результаты.

Пример объясняет это лучше всего

Скажем, вы хотите "предварительно" оптимизировать "какой-либо URL, mod_rewrite:

  • реальный файл: <DOCUMENT_ROOT>/some/dir/file.php?lang=en
  • реальный URL: http://www.example.com/some/dir/file.php?lang=en
  • удобный URL: http://www.example.com/en/file

Давайте предположим mod_rewrite используется для прозрачного переписывания удобного для пользователя URL-адреса в реальный (без внешнего перенаправления, поэтому "удобный для пользователя" остается в адресной строке браузера, пока загружается реальный). Что делать сейчас?

  • нет <BASE> указано: ломает все относительные ссылки (так как они будут основаны на http://www.example.com/en/file сейчас)
  • <BASE HREF='http://www.example.com/some/dir>Абсолютно неправильно. dir будет считаться файловой частью указанного URL, поэтому все относительные ссылки не работают.
  • <BASE HREF='http://www.example.com/some/dir/>Уже лучше. Но относительные ссылки типа 4 все еще не работают (за исключением случая B).
  • <BASE HREF='http://www.example.com/some/dir/file.php>: Именно так. Все должно работать с этим.

Последнее примечание

Имейте в виду, что это относится ко всем URL в вашем документе:

  • <A HREF=
  • <IMG SRC=
  • <SCRIPT SRC=
  • ...

Drupal изначально опирался на <base> тег, а затем принял решение не использовать из-за проблем с HTTP-сканерами и кешами.

Я вообще не люблю размещать ссылки. Но этим действительно стоит поделиться, так как он может помочь тем, кто ищет детали реального опыта с <base> тег:

http://drupal.org/node/13148

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

Хеш "#" в настоящее время работает для ссылок перехода в сочетании с базовым элементом, но только в последних версиях Google Chrome и Firefox, а не IE9.

IE9, кажется, заставляет страницу быть перезагруженной, никуда не переходя. Если вы используете переходные ссылки на внешней стороне iframe, при этом направляя фрейм для загрузки переходных ссылок на отдельной странице внутри фрейма, вместо этого вы получите вторую копию страницы переходных ссылок, загруженную внутри фрейма.

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

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

Просто не используйте target атрибут в HTML 4.01 Строгая страница.

В случае изображений SVG, встроенных в страницу, есть еще одна важная проблема, которая возникает, когда base тег используется:

Так как с base тег (как уже отмечалось выше) вы фактически теряете возможность использовать относительные URL-адреса хеша, как в

<a href="#foo">

потому что они будут сопоставлены с базовым URL, а не с местоположением текущего документа, и, следовательно, больше не будут относительными. Таким образом, вам нужно будет добавить путь к текущему документу к таким ссылкам, как в

<a href="/path/to/this/page/name.html#foo">

Так что один из, казалось бы, положительных аспектов base тэг (то есть, чтобы переместить длинные префиксы URL-адресов от тега привязки и получить более хорошие, более короткие якоря) полностью отрицательно сказывается на локальных хеш-URL.

Это особенно раздражает, когда вы вставляете SVG на вашу страницу, будь то статический SVG или динамически генерируемый SVG, потому что в SVG может быть много таких ссылок, и они все сломаются, как только base тег используется в большинстве, но не во всех реализациях пользовательских агентов (по крайней мере, Chrome все еще работает в этих сценариях на момент написания).

Если вы используете систему шаблонов или другую цепочку инструментов, которая обрабатывает / генерирует ваши страницы, я всегда буду пытаться избавиться от base тег, потому что, как я вижу, это приносит больше проблем, чем решает.

Работая с AngularJS, тег BASE молча сломал $cookieStore, и мне потребовалось некоторое время, чтобы понять, почему мое приложение больше не может писать куки. Имейте в виду...

Кроме того, вы должны помнить, что если вы запускаете веб-сервер с нестандартным портом, вам нужно также указать номер порта в base href:

<base href="//localhost:1234" />  // from base url
<base href="../" />  // for one step above

Имейте в виду одну вещь:

Если вы разрабатываете веб-страницу для отображения в UIWebView на iOS, то вам нужно использовать тег BASE. Это просто не будет работать иначе. Будь то JavaScript, CSS, изображения - ни одно из них не будет работать с относительными ссылками в UIWebView, если не указан тег BASE.

Я был пойман этим раньше, пока не узнал.

Также есть сайт, на котором используется базовый тег, и возникла описанная проблема. (после обновления jquery), смог исправить это, имея URL-адреса табуляции следующим образом:

<li><a href="{$smarty.server.REQUEST_URI}#tab_1"></li>

это делает их "местными"

ссылки, которые я использовал:

http://bugs.jqueryui.com/ticket/7822 http://htmlhelp.com/reference/html40/head/base.html http://tjvantoll.com/2013/02/17/using-jquery-ui-tabs-with-the-base-tag/

Я никогда не видел смысла в его использовании. Предоставляет очень мало преимуществ и может даже усложнить использование.

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

В качестве запоздалой мысли я, кажется, вспоминаю, что была некоторая проблема с тегом в IE6 Вы можете разместить их в любом месте тела, перенаправляя разные части сайта в разные места. Это было исправлено в IE7, который сломал много сайтов.

Пример базы href

Скажите типичную страницу со ссылками:

<a href=home>home</a> <a href=faq>faq</a> <a href=etc>etc</a>

.и ссылки на папку diff:

..<a href=../p2/home>Portal2home</a> <a href=../p2/faq>p2faq</a> <a href=../p2/etc>p2etc</a>..

С помощью base href мы можем избежать повторения базовой папки:

<base href=../p2/>
<a href=home>Portal2-Home</a> <a href=faq>P2FAQ</a> <a href=contact>P2Contact</a>

Так что это выигрыш... все же страницы слишком часто содержат URL для различий баз И текущая сеть поддерживает только один базовый href на страницу, поэтому выигрыш быстро теряется в качестве баз, которые не повторяет база - hrefed, например:

<a href=../p1/home>home</a> <a href=../p1/faq>faq</a> <a href=../p1/etc>etc</a>
<!--.. <../p1/> basepath is repeated -->

<base href=../p2>
<a href=home>Portal2-Home</a> <a href=faq>P2FAQ</a> <a href=contact>P2Contact</a>


Заключение

( Base target может быть полезен.) Base href бесполезен, так как:

  • страница одинаково влажная, так как:
    • база по умолчанию [папка-родитель] ⇌ идеально (за исключением ненужных / редких исключений 𝒞1 и 𝒞2).
    • текущий веб ⇌ несколько базовых ссылок не поддерживаются.

связанные с

Я рекомендую НЕ использовать<base>элемент управления путями URL. Почему?

Он просто меняет одну проблему на другую. Без базового элемента вы можете использовать любую систему путей для относительных путей и ссылок, не опасаясь, что они сломаются. В ту минуту, когда вы устанавливаете базовый элемент на путь, вы "заблокированы", чтобы проектировать все ваши URL-адреса, чтобы работать с этим путем, и теперь вам придется изменить ВСЕ пути, чтобы они работали с базового пути. Плохая идея!

Это означает, что теперь вы должны писать БОЛЬШИЕ пути И отслеживать, где каждый путь относительно этой базы. Хуже..... при использовании<base>они рекомендуют вам использовать полностью квалифицированный базовый путь для поддержки старых браузеров ("https://www.example.com/"), поэтому теперь вы жестко прописали свой домен на своей странице или сделали все свои ссылки зависимыми от действительный путь к домену.

С другой стороны, как только вы снова удалите базовый путь со своего веб-сайта, вы снова можете использовать более короткие относительные пути, которые могут быть полностью квалифицированы, использовать абсолютные пути от корня или использовать пути, которые действительно относятся к файл и папка, в которых вы находитесь. Это гораздо более гибко. А лучше всего корректно работают фрагменты типа "#hello" без дополнительных исправлений. Опять же, люди создают проблемы, которых не существует.

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

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

Примечание. Если проблема заключается в управлении путями из-за какой-то новой системы API, решение простое... будьте последовательны в том, как вы путешествуете по всем своим URL-адресам и ссылкам в своем API. Не полагайтесь на поддержку браузером базовых трюков, HTML5 или более новых цирковых трюков, как это делают ребята из API JavaScript. Просто последовательно размещайте все свои якорные теги, и у вас никогда не будет проблем. Более того, ваше веб-приложение мгновенно переносится на новые серверы независимо от используемых систем путей.

Что старое, то снова новое! Базовый элемент явно связан с попыткой создать решение проблемы, которой никогда не существовало в веб-мире 20 лет назад, а тем более сегодня.

Я нашел способ использовать <base> и ссылки на основе якоря. Вы можете использовать JavaScript, чтобы сохранить ссылки как #contact работает как надо. Я использовал его на некоторых страницах параллакса, и он работает для меня.

<base href="http://www.mywebsite.com/templates/"><!--[if lte IE 6]></base><![endif]-->

...content...

<script>
var link='',pathname = window.location.href;
$('a').each(function(){
    link = $(this).attr('href');
    if(link[0]=="#"){
        $(this).attr('href', pathname + link);
    }
});
</script>

Вы должны использовать в конце страницы

Я добавлю еще один аргумент в длинный список причин, почему вы никогда не должны устанавливать тег. Как уже отмечалось здесь, настройка изменяет поведение URL-адресов #anchor и ?query — они прикрепляются к базовому адресу href, а не к резервной базе, которая является собственным URL-адресом документа.

Вы можете подумать, что настройка <base href="https://example.com/the/documents/own/url">бы решить это, и все будет вести себя нормально. Вы ошибаетесь.

В реальной сети ?query=parameters постоянно используется для атрибуции сеансов (как в Google Analytics) и многих других вещей. Многие из этих параметров предназначены исключительно для использования сценариями на стороне клиента; серверу все равно и он ничего с ними не делает.

Допустим, вы служите, с <base href="example.com/landing-page">, а на странице ссылка на #menu. Затем кто-то приходит туда через URL example.com/landing-page?source=my-marketing-campaign.

Без , когда они нажимают #menu, браузер распознает внутристраничную навигацию и мгновенно переходит к этому разделу.

Но, поскольку ваш определенный базовый адрес href example.com/landing-pageотсутствует параметр запроса source=my-marketing-campaign, браузер не может быть уверен , что это ссылка на странице. Таким образом, нажатие #menu вызовет новый HTTP-запрос, и страница (и все ее некэшированные ресурсы) перезагрузится. В лучшем случае это бессмысленная трата времени и трафика со всех сторон. В худшем случае состояние и данные могут быть потеряны.

Для статического сайта это невозможно. Если вы используете CMS, вы можете на мгновение подумать, что вы можете динамически установить URL-адрес запроса, включая все параметры. Хотя это решило бы проблему с обновлением, в конечном итоге вы столкнулись бы с проблемами кэширования и вызывающей кошмар уязвимостью системы безопасности .

Нижняя линия: <base href>вызовет у вас проблемы, независимо от того, что вы установите. Не делай этого.

Если вас беспокоит возможность того, что вредоносный скрипт внедрит свой собственный <base href="evil.com">tag (например, при атаке с перенацеливанием одноразового номера ), лучшим решением в 2022 году кажется добавление директивы base-uri в вашу политику безопасности контента.

Другие вопросы по тегам