HTML <base>标签的建议是什么?

487

我以前从未见过实际使用过的HTML标签<base>。它的使用是否存在缺陷,使我应该避免使用它?

事实上,在现代生产网站(或任何网站)上,我从未注意到它的使用,这让我对它持怀疑态度,尽管它似乎可能有用于简化我的网站链接的应用。


编辑

在使用基本标记几周后,我最终发现了一些主要陷阱使用基础标记,这使得它比起初显得不那么理想。基本上,<base>下的 href='#topic'href='' 的更改与其默认行为是非常不兼容的,这种变化与默认行为的区别可能会使你无法控制的第三方库产生意料之外的极不可靠的问题, 因为它们在逻辑上依赖默认行为。这些更改通常是微妙的,并且处理大型代码库时会导致不明显的问题。因此,我在下面创建了一个详细说明我遇到的问题的答案。因此,在广泛部署<base>之前,请先自行测试链接结果,这是我的新建议!


15
通常在搜索引擎结果的缓存版本中使用它,以保持链接的可用性。 - Gumbo
15
请注意:基本标签还会影响简单锚点,所以如果您使用基本标签,以前仅是指向页面上某个位置的锚点 <a href='#anchor1'>Anchor1</a> 也将使用基本标签,覆盖默认的引用当前页面作为基本页面的行为。因此,这绝对是需要注意的问题(尽管可以通过在使用大量锚点的页面中使用另一个基本标签来修复)。 - Kzqai
1
如果您对已接受的答案不满意,为什么不取消接受并重新分配呢? - Pops
2
通常你不会查看每个主要网站的源代码。我相信使用<base>标签的人比你想象的多。 - Mathias Lykkegaard Lorenzen
2
似乎这里是最终的死灵法师,但在进行渗透测试之前,我从未听说过“base”标签,其中相对链接到CSS和JavaScript被禁止,因为黑客可以注入“base”标签将事物重定向到他们的邪恶网站。即使出于方便而使用自己的“base”标签也可能会被黑客破坏。底线:不要使用“base”标签,使用所有链接的完整路径。 - UncaAlby
显示剩余3条评论
18个回答

270

在决定是否使用<base>标签之前,您需要了解它的工作原理,可以用于什么以及其影响,并最终权衡利弊。


"

<base>标签主要是为了在模板语言中轻松创建相对链接,因为您不需要在每个链接中担心当前上下文。

例如,您可以这样做:

"
<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中出现问题。HTML中的<base>标签被规定为没有结束标签</base>,因此可以正常使用<base>而不需要结束标签。然而,IE6认为这是错误的,在这种情况下,<base>标签后面的整个内容将作为HTML DOM树中<base>元素的子元素。这可能会导致在Javascript/jQuery/CSS中出现一些看似无法解释的问题,例如在特定选择器(如html>body)中完全无法访问元素,直到您在HTML DOM检查器中发现应该有一个base(和head)在其中。

常见的IE6修复方法是使用IE条件注释来包含结束标签:

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

如果您不关心W3验证器,或者您已经在使用HTML5,则可以直接自闭它,每个网络浏览器都支持此操作:
<base href="http://example.com/en/" />

关闭<base>标签还可以立即解决IE6在WinXP SP3上使用相对URI请求<script>资源时出现无限循环的疯狂问题。
当您在<base>标签中使用相对URI(例如<base href="//example.com/somefolder/"><base href="/somefolder/">)时,可能会出现另一个IE问题。这在IE6/7/8中会失败。但这并不完全是浏览器的错;在<base>标签中使用相对URI本身就是错误的。HTML4规范指出它应该是绝对URI,因此以http://https://方案开始。这在HTML5规范中已经被删除。因此,如果您使用HTML5并仅针对HTML5兼容浏览器,则使用<base>标签中的相对URI应该没有问题。
关于使用命名/哈希片段锚点,如<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}在PHP中基本上相当于$_SERVER['REQUEST_URI'],在JSP中相当于${pageContext.request.requestURI},在JSF中相当于#{request.requestURI}。需要注意的是,像JSF这样的MVC框架有标签可以减少所有这些样板代码,并消除<base>的必要性。另请参见要链接/导航到其他JSF页面使用哪个URL


BalusC,就在我在这里写下答案的同时https://dev59.com/enI-5IYBdhLWcg3wYXL8#46539210,已经有超过10个有用的评论在这个线程下由多个作者发布了8年之久,详细介绍了<base>的信息。你知道这些评论被移动到哪个链接了吗? - Pacerier

170

基础标签的效果分析:

基础标签的效果似乎有些不直观,我建议在依赖于 <base> 前,认真了解其结果并进行个人测试!由于我是在试图使用基础标签来处理具有不同url的本地站点后才发现问题的,为此我感到非常沮丧。因此,我需要为其他人创建这些潜在陷阱的摘要。

在下面的情况中,我将使用一个基础标签:<base href="http://www.example.com/other-subdirectory/"> 作为我的示例,并假装代码所在的页面位于 http://localsite.com/original-subdirectory

主要影响:

除非明确指出,否则所有链接、命名锚点或空href都不会指向原始子目录: 基础标签让所有链接都表现不同,甚至包括同一页面上的命名锚点链接到基础标签的url,例如:

  • <a href='#top-of-page' title='Some title'>通过命名锚点链接到页面顶部的一个链接</a>
    变成了
    <a href='http://www.example.com/other-subdirectory/#top-of-page' title='Some title'>链接到完全不同的基础页面上的 # 命名锚点</a>

  • <a href='?update=1' title='Some title'>链接到此页面的一个链接</a>
    变成了
    <a href='http://www.example.com/other-subdirectory/?update=1' title='Some title'>链接到基础标签页面上的链接</a>

通过明确指定这些链接链接到的页面,您可以解决控制的链接上的这些问题,但是当您将第三方库添加到其中并依赖于标准行为时,它很容易造成混乱。

小问题:

IE6修复需要条件注释:需要针对ie6使用条件注释以避免破坏dom层次结构,例如 <base href="http://www.example.com/"><!--[if lte IE 6]></base><![endif]-->BalusC在上面的回答中提到的。

因此,总体而言,这个主要问题让使用变得棘手,除非您完全掌控每个链接的编辑,正如我最初所担心的那样,这使得它不值得麻烦。现在我必须去重新编写所有使用它的内容! :p

使用“片段”/哈希时测试问题的相关链接:

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

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


Izzy编辑:对于所有像我一样遇到相同困惑的人:

我刚刚自己测试了一下,以下是我的结果:

  • 有无尾部斜杠对这里给出的示例(#anchor?query将简单地附加到指定的<BASE>)没有影响。
  • 但是,对于相对链接,它确实有所不同:省略尾部斜杠, other.htmldir/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?queryother.htmlvery/other.html/completely/other.html

31

等一下,我认为base标签并不应该受到这样的负面评价。

使用base标签的好处是可以更轻松地完成复杂的URL重写。

举个例子,你决定将http://example.com/product/category/thisproduct移动到http://example.com/product/thisproduct。你会修改.htaccess文件,将第一个URL重写为第二个URL。

有了base标签,进行.htaccess重写就可以了,没问题。但如果没有base标签,所有的相对链接都会失效。

URL重写通常是必要的,因为调整它们可以改善网站的结构和搜索引擎可见性。当然,你需要解决“#”和“''”问题,但base标签值得成为工具箱中的一员。


11
据我看,问题在于未来的兼容性。如果在页面上使用基础标签(base tag),所有与页面交互的其他库都会受到基础标签的影响,包括可能依赖裸露锚点标签(naked anchor tag)或哈希值(default behavior of hashs)的第三方库。请注意保持原意,并尽量让翻译通俗易懂。 - Kzqai
8
@Kzqai,非常好的观点,但有许多网站没有使用有缺陷的库。问题不在于基础href,而在于库本身,需要在那里进行修复。 - Pacerier
3
@Pacerier,我认为问题确实与基本href有关。或者更确切地说,问题是浏览器似乎不够聪明,无法简单地使其不影响以#开头的锚点href。我尝试用JavaScript来修复这个问题,但这会导致使用href='#'链接的库出现问题(例如,Bootstrap)。责怪库就像责怪它们在HTML中出现的所有其他问题一样。这是一个过时的工具,无法胜任现代的工作,就这么简单。 - Deji
2
"更轻松地进行复杂的URL重写。" - 尽管在这种情况下,“base”标签可以说是为了解决没有正确使用根相对URL(甚至绝对URL)而采取的“变通方法”。 - MrWhite
@Deji,当我写“problem”时,我的意思是“bug”。是的,base href的存在确实是一个真正的“问题”,但在上述情况下,我说bug不是由于base href引起的。(但请不要认为我支持使用base href,事实上,我的立场是当前版本的base href是无用的:https://dev59.com/enI-5IYBdhLWcg3wYXL8#46539210。现在最好的方法是将其弃用**或启用多个base hrefs**,因为只有在可以使用多个时才有用) - Pacerier
@MrWhite,干得好。@Summer,关于“相对链接会断掉”的问题,实际上只要你也用modrewrite修改所有这些相对链接,它们就不会断掉。事实上,这正是应该做的(还可以参见https://dev59.com/enI-5IYBdhLWcg3wYXL8#PYUfoYgBc1ULPQZFb5jh)。关于“但基础标签应该有一个工具箱”,不需要,只要**适当地使用modrewrite**(包括所有相对链接的页面),一切都很好。 - Pacerier

27

要决定是否使用它,您应该了解它的作用及是否需要。这在此答案中已部分概述,我也为其做出了贡献。但为了更容易理解和遵循,这里提供第二个解释。首先,我们需要了解:

没有使用 <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) 发送到浏览器,C 当然会发送 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     | Type | 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,因此它将所有链接呈现为用户调用<BASE>指定的URL。这解释了其他答案中的一些混淆:

  • 对于“完全限定绝对链接”(“类型1”),什么都不会改变
  • 对于“本地绝对链接”,如果<BASE>指定的服务器与用户最初调用的服务器不同,则目标服务器可能会发生更改
  • “相对URL”在这里变得至关重要,因此您必须特别注意如何设置<BASE>
    • 最好避免将其设置为一个目录。
      这样做,“类型3”的链接(相对目录+文件名)可能仍然有效,但它肯定会破坏那些“类型4”的链接(相对+片段);除了“情况B”(无路径或文件名)。
    • 指定完全限定文件名会在大多数情况下产生期望的结果。

例子说明最好

假设您想使用mod_rewrite来美化某些URL:

  • 真实文件:<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透明地重写为真实的URL(没有外部重新定向,因此“用户友好”的URL仍然在浏览器地址栏中,而实际的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=

关于您上一条留言...我很好奇...它是否也会改变jQuery ajax请求的解释方式。这与<SCRIPT SRC=不同。 - bkwdesign
@bkwdesign 我不使用 jQuery,不过我认为应该可以。 - Izzy
@Izzy,关于“示例” 实际上,如果你将 </some/dir/file.php?lang=en> 美化为 </en/file>,那么你也需要将 </some/dir/page2?lang=en> 和 </some/dir/script> 美化为 </en/page2> 和 </en/script>。这样,你的相对路径就会像应该的那样工作。 - Pacerier
<BASE HREF='http://www.example.com/some/dir/file.php>如何与"type 4"一起使用?它不会变成"http://www.example.com/some/dir/file.php?foo=bar"而不是"http://www.example.com/subdir/page.html?foo=bar"吗? - ANewGuyInTown
@ANewGuyInTown 是的,这就是它应该做的——就像我的示例中 http://www.example.com/some/dir/file.php 是“真正的位置”(参见“最好的例子说明”),只传递一个片段(#anchor)只能在那里解决。 - Izzy

13

Drupal最初依赖于<base>标签,但后来决定不使用该标签,原因是会与HTTP爬虫和缓存发生问题。

一般我不喜欢发布链接。但这个链接真的值得分享,因为它可以让那些想了解<base>标签的真实世界经验细节的人受益:

http://drupal.org/node/13148


该链接指向八年前的讨论,现在已经过去了将近十年。我认为如果这仍然是一个问题,应该进行更多的测试,而不是链接到一个可能不存在的问题的古老描述。 - Sami Kuhmonen
真的,但在我看来,这仍然是一个启示,让你了解需要针对基础实现进行哪些问题测试,而不仅仅是在浏览器中正确地工作锚点。 - Amr Mostafa
@AmrMostafa,不要使用base href。 - Pacerier

11

这使得网页更易于离线查看;您可以将完全限定的URL放入基本标签中,然后您的远程资源将正确加载。


@Erik,除了离线查看之外,它还适用于所有需要在另一个域上演示域页面的临时使用情况。例如,在演示jsfiddle页面时,您可以使用base href来基于您的域而不是jsfiddle的域。虽然实际上,仅为此类临时使用情况创建标签并不是一个好的设计,因此应该弃用和删除base href,即使它对于这种临时使用情况可能有用。 - Pacerier

5

它可能不太受欢迎,因为它不太知名。但既然所有主流浏览器都支持它,我不会害怕使用它。

如果您的网站使用 AJAX,您需要确保所有页面都正确设置了它,否则可能会出现无法解析的链接。

只是不要在 HTML 4.01 Strict 页面中使用 target 属性。


实际上,basetarget可能很有用,但basehref不是。事实上,它不受欢迎,因为它没有用处。请参见我的答案。 - Pacerier
现在所有的浏览器都支持base标签。 - Vitaly Zdanevich

5

使用基础元素和哈希符号“#”可以实现跳转链接,但仅适用于最新版本的Google Chrome和Firefox浏览器,不支持IE9。

如果在iframe外部使用跳转链接,同时指示框架在框架内加载跳转链接的单独页面,那么IE9会重新加载整个页面而不是跳转链接。这将导致框架内加载一个跳转链接页面的第二个副本。


3
在页面中嵌入SVG图像的情况下,当使用base标签时会出现另一个重要问题:
由于使用base标签(如上所述),您实际上失去了使用相对哈希URL的能力,例如 <a href="#foo"> 因为它们将根据基本URL而不是当前文档位置进行解析,因此不再是相对的。 因此,您需要将当前文档的路径添加到这些链接中,例如 <a href="/path/to/this/page/name.html#foo"> 因此,base标签似乎积极的一个方面(即将长URL前缀移开以获得更漂亮、更短的锚点)完全对本地哈希URL产生了反作用。
这在页面内联SVG时特别令人恼火,无论是静态SVG还是动态生成的SVG,因为在SVG中有很多这样的引用,它们将在大多数用户代理实现(至少在写作时Chrome仍然在这些情况下工作)中使用 base 标签后立即中断。
如果您正在使用模板系统或另一个处理/生成页面的工具链,我会尽量摆脱base标签,因为在我看来,它带来的问题比解决的问题更多。

无论是否使用SVG,base标签都是无用的且被认为是有害的。请参阅我的详细解释:https://dev59.com/enI-5IYBdhLWcg3wYXL8#46539210 - Pacerier

3

同时,您需要记住,如果您在非标准端口上运行 Web 服务器,则还需要在基本 href 中包括端口号:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接