对html<base>标签有什么建议?




contextpath base-tag (11)

我从来没有见过<base> HTML标签实际上在任何地方使用过。 它的使用有缺陷意味着我应该避免它?

我从来没有注意到它在现代生产网站(或任何网站)上使用的事实让我感到不快,尽管它似乎可能有用于简化我网站上链接的有用应用程序。

编辑

在使用基本标签几周后,我最终发现了一些使用基本标签的重要陷阱,使它比首次出现时更不理想。 实质上,base标记下href='#topic'href=''的更改与其默认行为非常不兼容,而且这种默认行为的更改很容易让您的控制之外的第三方库以非常不可靠的方式非常不可靠 ,因为它们在逻辑上取决于默认行为。 处理大型代码库时,这些更改通常很微妙,并且会导致不太明显的问题。 我从那以后创建了一个答案,详细说明了我所经历的问题。 因此,在您承诺广泛部署<base>之前,请自行测试链接结果,这是我的新建议!


基本标签效果的细分:

基本标签似乎有一些非直观效果,我建议您在依赖<base>之前了解结果并自行测试它们! 由于我尝试使用基本标签处理具有不同URL的本地网站后才发现它们并且仅在发现后面的问题影响之后才发现它们,令我感到沮丧的是,我不得不为其他人创建这些潜在陷阱的摘要。

我将在下面的例子中使用基本标签: <base href="http://www.example.com/other-subdirectory/">作为我的例子,并假装代码所在的页面是http://localsite.com/original-subdirectory

重大的:

没有链接或命名锚点或空白hrefs将指向原始子目录,除非明确指出:基本标记使所有链接以不同方式链接,包括与基本标记的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在上面的回答中提到了。

总的来说,主要问题使用起来很棘手,除非你对每一个链接都有完整的编辑控制权,正如我最初所担心的那样,这使得它比它的价值更麻烦。 现在我不得不重新写下它的所有用法! :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一切都按预期工作: #anchor?queryother.htmlvery/other.htmlvery/other.html /completely/other.html very/other.html


Drupal最初依赖<base>标签,后来由于HTTP爬虫和缓存问题决定不使用。

我通常不喜欢张贴链接。 但是这个真的很值得分享,因为它可以让那些寻找具有<base>标签的真实体验细节的人受益:

http://drupal.org/node/13148



使用AngularJS时,BASE标签默默打破了$ cookieStore,花了我一段时间才弄清楚为什么我的应用程序无法再写入cookie。 被警告...


在决定是否使用<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中的问题。 <base>标记在HTML中被指定为没有结束标记</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 Validator,或者您已经使用HTML5,那么您可以自行关闭它,每个webbrowser都支持它:

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

关闭<base>标记也立即修复了WinXP SP3上IE6的错误,在无限循环中用src中的相对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> 。 另请参阅ao 用于链接/导航到其他JSF页面的URL


在页面内嵌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标记,因为就我所见,它会给表格带来更多问题而不是解决问题。


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


它可能不是很受欢迎,因为它不是很出名。 因为所有主流浏览器都支持它,所以我不会害怕使用它。

如果您的网站使用AJAX,则您需要确保您的所有网页都已正确设置,否则最终可能无法解析链接。

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


我找到了一种使用<base>和基于锚的链接的方法。 您可以使用JavaScript来保持#contact链接#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>

您应该在页面的末尾使用


散列“#”目前适用于与基本元素结合的跳转链接,但只适用于Google Chrome和Firefox的最新版本NOT NOT IE9。

IE9似乎会导致页面重新加载,而不会跳到任何地方。 如果您在iframe的外部使用跳转链接,同时指示框架将跳转链接加载到框架内的单独页面上,您将取得框架内加载的跳转链接页面的第二个副本。


要决定是否应该使用它,你应该知道它的功能以及是否需要。 这个答案已经部分概括了,我也对此作出了贡献。 但为了让它更容易理解和遵循,请在此再说一次。 首先我们需要了解:

没有使用<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     | 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。 因此,它会呈现所有链接,就好像用户调用了<BASE>指定的URL一样。 这解释了其他一些答案中的一些混淆:

  • 再次,“完全合格的绝对链接”(“类型1”)没有任何变化
  • 对于本地绝对链接,目标服务器可能会更改(如果<BASE>指定的服务器与最初从用户调用的服务器不同)
  • 相对URL在这里变得至关重要,所以你必须特别注意你如何设置<BASE>
    • 最好避免将其设置为目录 。 这样做,“类型3”的链接可能会继续工作,但它肯定会打破“类型4”(除了“情况B”)之外的链接。
    • 将其设置为完全限定的文件名在大多数情况下会产生所需的结果。

一个例子最好地解释它

假设你想用mod_rewrite来“美化”一些URL:

  • 真正的文件: <DOCUMENT_ROOT>/some/dir/file.php?lang=en
  • 真实网址: http://www.example.com/some/dir/file.php?lang=enhttp://www.example.com/some/dir/file.php?lang=en lang = http://www.example.com/some/dir/file.php?lang=en
  • 用户友好的网址: http://www.example.com/en/filehttp://www.example.com/en/file

我们假设mod_rewrite用于将用户友好的URL 透明地重写为真实的URL(无需外部重定向,因此“用户友好”的URL保留在浏览器地址栏中,而真实的地址栏则加载)。 现在做什么?

  • 没有指定<BASE> :打破所有相关链接(因为它们现在基于http://www.example.com/en/file
  • <BASE HREF='http://www.example.com/some/dir> :绝对错误。 dir将被视为指定网址的文件部分,因此,所有相关链接都会被破坏。
  • <BASE HREF='http://www.example.com/some/dir/> :已经好了。 但“类型4”的相关链接仍然被打破(“情况B”除外)。
  • <BASE HREF='http://www.example.com/some/dir/file.php> :正确。 一切都应该与这一个。

最后一个音符

请记住,这适用于文档中的所有网址:

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




base-tag