478

我以前从未见过 在任何地方实际使用过的<base>HTML 标记。它的使用是否存在陷阱,这意味着我应该避免它?

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


编辑

在使用基本标签几周后,我确实发现了使用基本标签的一些主要问题,这使得它比最初出现的时候更不受欢迎。本质上,对base 标记href='#topic'及其下的更改与它们的默认行为非常不兼容,并且这种对默认行为的更改很容易使您无法控制的第三方库非常不可靠href='' 以意想不到的方式,因为它们在逻辑上将取决于默认行为。通常,这些变化是微妙的,并且在处理大型代码库时会导致不立即显而易见的问题。此后,我创建了一个答案,详细说明了我在下面遇到的问题。因此,在您承诺广泛部署 之前,请自行测试链接结果,这<base>是我的新建议!

4

18 回答 18

267

在决定是否使用<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 不这么认为,在这种情况下,标记之后的整个内容都作为元素的元素放置在 HTML DOM 树中。乍一看,这可能会导致 Javascript/jQuery/CSS 中出现无法解释的问题,即元素在特定选择器中完全无法访问,例如,直到您在 HTML DOM 检查器中发现应该有一个(和)之间。<base><base>html>bodybasehead

一个常见的 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 上的疯狂问题,即在无限循环中<script>使用相对 URI请求资源。src

当您在标签中使用相对 URI <base>(例如<base href="//example.com/somefolder/">或)时,另一个潜在的 IE 问题将显现出来<base href="/somefolder/">。这将在 IE6/7/8 中失败。然而,这并不完全是浏览器的错。在标签中使用相对 URI<base>本身就是错误的。HTML4 规范声明它应该是一个绝对 URI,因此以orhttp://方案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}基本上转换为$_SERVER['REQUEST_URI']PHP、${pageContext.request.requestURI}JSP 和#{request.requestURI}JSF。应该注意的是,像 JSF 这样的 MVC 框架有标签,减少了所有这些样板文件并消除了对<base>. 另请参阅 ao用于链接/导航到其他 JSF 页面的 URL

于 2009-12-11T18:24:24.880 回答
167

基础标签的效果细分:

基本标签似乎有一些非直观的影响,我建议在依赖之前了解结果并自己测试它们<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 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.htmlDOCUMENT_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.

于 2009-12-11T18:14:02.947 回答
30

好吧,等一下。我认为基本标签不值得这个坏名声。

基本标记的好处在于它使您能够轻松地进行复杂的 URL 重写。

这是一个例子。您决定将http://example.com/product/category/thisproduct移至http://example.com/product/thisproduct。您更改 .htaccess 文件以将第一个 URL 重写为第二个 URL。

有了基本标记,您就可以重写 .htaccess 了,就是这样。没问题。但是如果没有基本标签,您所有的相关链接都会中断。

URL 重写通常是必要的,因为调整它们可以帮助您的网站架构和搜索引擎可见性。诚然,您需要解决人们提到的“#”和“”问题。但是基本标签应该在工具包中占有一席之地。

于 2010-02-16T19:02:17.137 回答
25

要决定是否应该使用它,您应该知道它的作用以及是否需要它。这个答案已经部分概述了这一点,我也对此做出了贡献。但为了更容易理解和遵循,这里有第二个解释。首先我们需要明白:

浏览器如何处理不<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,它需要知道将它指向哪里。这对于 Link 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>. 这解释了其他几个答案中的一些混淆:

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

一个例子最好地解释它

假设您想使用以下方法“美化”某些 URL mod_rewrite

  • 真实文件:<DOCUMENT_ROOT>/some/dir/file.php?lang=en
  • 真实网址:http://www.example.com/some/dir/file.php?lang=en
  • 用户友好的网址: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=
  • …</li>
于 2014-07-09T07:30:15.290 回答
13

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

我一般不喜欢发布链接。但这确实值得分享,因为它可以使那些寻找<base>标签真实体验细节的人受益:

http://drupal.org/node/13148

于 2012-08-13T11:39:24.957 回答
11

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

于 2009-12-11T16:19:39.890 回答
5

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

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

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

于 2009-12-11T16:12:13.783 回答
5

哈希“#”目前适用于与基本元素结合的跳转链接,但仅适用于最新版本的 Google Chrome 和 Firefox,不适用于 IE9。

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

于 2012-03-16T07:53:54.297 回答
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 中可能有很多这样的引用,并且一旦使用base标签,它们就会在大多数(但不是所有)用户中中断代理实现(Chrome 至少在撰写本文时仍然适用于这些场景)。

如果您正在使用模板系统或其他处理/生成页面的工具链,我总是会尝试摆脱base标签,因为在我看来,它给表格带来的问题比它解决的要多。

于 2017-01-25T08:38:07.963 回答
3

此外,您应该记住,如果您在非标准端口上运行 Web 服务器,您还需要在基本 href 中包含端口号:

<base href="//localhost:1234" />  // from base url
<base href="../" />  // for one step above
于 2017-05-10T05:48:43.887 回答
2

One thing to keep in mind:

If you develop a webpage to be displayed within UIWebView on iOS, then you have to use BASE tag. It simply won't work otherwise. Be that JavaScript, CSS, images - none of them will work with relative links under UIWebView, unless tag BASE is specified.

I've been caught by this before, till I found out.

于 2012-10-18T15:24:44.983 回答
2

我从来没有真正看到使用它的意义。提供的优势很小,甚至可能使事情更难使用。

除非你碰巧有成百上千个链接,都指向同一个子目录。然后它可能会为您节省几个字节的带宽。

作为事后的想法,我似乎记得 IE6 中的标签存在一些问题。您可以将它们放置在正文中的任何位置,将站点的不同部分重定向到不同的位置。这在 IE7 中得到了修复,它破坏了很多网站。

于 2009-12-11T16:14:45.573 回答
2

还有一个使用 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-带有基本标签的标签/

于 2013-03-28T10:29:01.050 回答
2

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

于 2017-04-20T08:46:49.573 回答
1

基本 href 示例

说一个带有链接的典型页面:

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

.and 链接到 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,所以胜利很快就会失去,因为不是 base∙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>


结论

基本目标可能有用。)基本 href 无用,因为:

  • 页面同样是湿的,因为:
    • 默认基础 [–父文件夹] ⇌ 完美(除非不必要/罕见的例外
于 2017-10-03T07:24:15.350 回答
1

我的建议是不要<base>在管理 url 路径中使用该元素。为什么?

它只是用一个问题换另一个问题。如果没有基本元素,您可以将任何您喜欢的路径系统用于您的相对路径和链接,而不必担心它们会中断。在您将基本元素设置为“锁定”路径的那一刻,您将设计所有 url 以在该路径上工作,现在必须更改所有路径才能从基本路径工作。馊主意!

这意味着您现在必须编写更长的路径并跟踪每条路径相对于该基础的位置。更糟糕的是......当使用<base>他们建议您使用完全限定的基本路径来支持旧浏览器的元素时(“ https://www.example.com/ ”),所以现在您已经将您的域硬编码到您的页面或使您的所有链接都依赖于有效的域路径。

另一方面,当您再次从网站中删除基本路径时,您现在可以再次自由使用较短的相对路径,可以是完全限定的,使用来自根的绝对路径,或者使用真正相对于您所在的文件和文件夹。它更加灵活。最好的片段,如“#hello”,无需任何额外修复即可正常工作。同样,人们正在制造不存在的问题。

此外,上面关于您使用基本 url 来帮助您将网页文件夹迁移到新的子文件夹位置的论点在今天并不重要,因为大多数现代服务器允许您快速将任何子文件夹设置为任何域下的新应用程序根文件夹。Web 应用程序的定义或“根”现在不受文件夹或域的限制。

整个辩论似乎有点愚蠢。所以我说省略基本 url 并支持不使用它的较旧的本机服务器客户端默认路径系统。

注意:如果您遇到的问题是由于某些新的 API 系统而导致的路径控制问题,则解决方案很简单……在您的 API 中路径所有 url 和链接的方式上保持一致。不要依赖浏览器对 base 或 HTML5 的支持或像 javascript API 小子那样的新马戏团技巧。只需一致地路径所有锚标签,您将永远不会遇到问题。更重要的是,无论使用何种路径系统,您的 Web 应用程序都可以立即移植到新服务器。

旧的又是新的!基本元素显然是关于尝试为 20 年前网络世界中从未存在过的问题创建解决方案,更不用说今天了。

于 2020-03-23T06:09:00.077 回答
1

我找到了一种使用<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>

您应该在页面末尾使用

于 2016-10-19T05:14:02.927 回答
0

我将在您永远不应该设置<base href>标签的一长串原因中再添加一个论据。正如许多其他人在这里指出的那样,设置<base href>会改变 #anchor 和 ?query URL 的行为——它们附加到基本 href,而不是作为文档自己的 URL 的后备库。

您可能认为设置<base href="https://example.com/the/documents/own/url">会解决这个问题,并且一切都会正常运行。你错了。

在现实世界的网络上,?query=parameters 一直用于会话归因(如在 Google Analytics 中)和许多其他事情。其中许多参数专门供脚本客户端使用;服务器不在乎或对它们做任何事情。

假设您正在服务example.com/landing-page,页面上有一个<base href="example.com/landing-page">和 的链接#menu。然后有人通过 URL 到达那里example.com/landing-page?source=my-marketing-campaign

如果没有<base href>,当他们单击 #menu 时,浏览器将识别页面内导航并立即跳转到该部分。

但是,由于您定义的基本 hrefexample.com/landing-page缺少查询参数source=my-marketing-campaign,浏览器无法确定它是页内链接。因此,单击#menu 将触发一个的HTTP 请求,并且页面(及其所有未缓存的资产)将重新加载。最好的情况是,这是对各方时间和带宽的毫无意义的浪费。最坏的情况下,状态和数据可能会丢失。

对于静态站点,没有办法解决这个问题。如果您使用的是 CMS,您可能会想,您可以动态设置<base href>请求 URL,包括所有参数。虽然这可以解决刷新问题,但您最终会遇到缓存问题和引发噩梦的安全漏洞

底线:<base href>无论您将其设置为什么,都会给您带来麻烦。不要这样做。

如果您担心恶意脚本可能会注入自己的<base href="evil.com">标签(例如在nonce 重定向攻击中),那么 2022 年的最佳解决方案似乎是将base-uri指令添加到您的内容安全策略中。

于 2022-02-26T14:36:22.837 回答