预取资源会被加载两次。

20

我希望使用html预取来预取字体文件。我遵循了这里的建议:https://css-tricks.com/prefetching-preloading-prebrowsing/

<!doctype html>
<html>
<head>
<link rel="prefetch" href="https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2">
<style>
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 400;
  src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}

html, body {
font-family: 'Open Sans';
}
</style>
</head>
<body>
Hello world
</body>
</html>

然而,在Chrome浏览器上,字体文件实际上会加载两次。我没有尝试其他浏览器。

Results

我做错了什么吗?


在我的Chrome 49 Windows Vista上,它只能加载一次。这里有一个截图 - L777
我认为它会加载两次,因为你在链接标签中加载了一次,显示为类型font/woff2,另一次在字体面src中加载,显示为类型font。我不熟悉预取,但只能使用font-face使用字体,但不需要链接标签。然而,如果我尝试仅使用链接标签而没有font-face,则会加载字体/woff2,但我无法在没有font-face规则的情况下使用字体。我认为这里的诀窍是你在链接标签和font-face规则中各加载了一次字体,但它们目前没有关联。 - frajk
@frajk 答案不是删除链接标签。在现实世界中,CSS 是一个外部样式表,其中包含 @include 另一个包含字体系列声明的样式表。如果每个样式表的文件大小都很大,则预取很重要。 - Joe Frambach
我只是指出,在font-face中同时拥有链接标签和src url是多余的,这就是两个加载来源。如果你想保留链接标签,必须有另一种方法来声明font-face的src,使用从链接标签加载的资源,而不是再次使用src url获取它。 - frajk
1个回答

19
这是 prefetch 的错误用法,请参阅资源:https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/

<link rel="prefetch"> 是一种指令,告诉浏览器预取一个资源,该资源可能会在下一个导航中使用。

...

<link rel="subresource"> 最初是为了解决当前导航问题而计划的,但在某些方面它的效果并不理想。

...

你可以使用 preload 的基本方法是提前加载迟发现的资源。[...] 一些资源隐藏在 CSS 和 JavaScript 中。


因此,在这里我们要使用 preload。但是,它几乎完全没有得到支持。

文章还对加载字体有一些特别的说明:

例如:

<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

一个值得注意的点:当获取字体时,你必须添加 crossorigin 属性,因为它们使用匿名模式 CORS 进行获取。是的,即使你的字体和页面在同一个域内也是如此。抱歉。


将所有内容组合起来,更新后可复制的代码如下:

style.css

/* 2MB of random character comment fluff */

@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 400;
  src: local('Open Sans'), local('OpenSans'), url(https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
}

html, body {
font-family: 'Open Sans';
}

index.html:

<!doctype html>
<html>
<head>
<link rel="preload" as="font" type="font/woff2" crossorigin href="https://fonts.gstatic.com/s/opensans/v13/cJZKeOuBrn4kERxqtaUH3ZBw1xU1rKptJj_0jans920.woff2">
<link rel="stylesheet" href="style.css">
</head>
<body>
Hello world
</body>
</html>

现在,它只能在Chrome的开发版Canary中工作。我指望着未来有更好的浏览器支持。

Chrome:

输入图像描述

Canary:

输入图像描述


谢谢这个提醒 - 即使在今天也值得重复,正如你引用的那样:“有一点值得再强调:在获取字体时,你必须添加 crossorigin 属性,因为它们是使用匿名模式的 CORS 进行获取的。是的,即使你的字体与页面在同一个源上。抱歉。”这让我感到惊讶,因为你会期望本地资源不需要 crossorigin 属性。 - undefined

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