19

I want to use html prefetch to prefetch a font file. I followed the recommendations here: 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>

However, the font file is actually loading twice on Chrome. I haven't tried other browsers.

Results

Am I doing something incorrectly?

000
  • 26,951
  • 10
  • 71
  • 101
  • On my Chrome 49 windows vista it only loads once. [**here's a screenshot of it**](https://i.gyazo.com/26f727b39b8f57c97b57d0bb58304163.png) – L777 Mar 31 '16 at 00:56
  • I think it's loading twice because you are loading it once in the link tag, which shows up as type font/woff2, and once in the font-face src, which shows up as type font. I'm not familiar with prefetch, but was only able to use the font with the font-face, but did not need the link tag. However, if I tried to use just the link tag, without the font-face, it loaded the font/woff2 but I could not use the font without the font-face rule. I think the trick here is that you are loading the font once in the link tag and once in the font-face rule, but they are currently not related – frajk Mar 31 '16 at 01:34
  • @frajk The answer is not to remove the link tag. In the real world, the css is an external stylesheet which `@include`s another stylesheet which includes the font-family declaration. If each stylesheet is of nontrivial filesize, then prefetching is important. – 000 Mar 31 '16 at 06:08
  • I was just pointing out that having the link tag and the src url in the font-face are redundant, that's where the two loads are coming from. If you want to keep the link tag, there has to be another way to declare the src of the font-face using the resources loaded from the link tag, instead of using src url, which just fetches it again. – frajk Mar 31 '16 at 12:00

1 Answers1

18

This is an incorrect usage of prefetch. See the resource: https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/

<link rel="prefetch"> is a directive that tells a browser to fetch a resource that will probably be needed for the next navigation.

...

<link rel="subresource"> was originally planned to tackle the current navigation, but it failed to do that in some spectacular ways.

...

The basic way you could use preload is to load late-discovered resources early. [...] Some of the resources are hidden in CSS and in JavaScript


So, preload is what we want to use here. But, it is not supported, hardly at all.

The article also has some words about loading fonts specifically:

Something like:

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

One point worth going over: You have to add a crossorigin attribute when fetching fonts, as they are fetched using anonymous mode CORS. Yes, even if your fonts are on the same origin as the page. Sorry.


Putting that all together, the updated reproducible code looks like:

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>

Now, it works but only in Chrome Canary. I'm counting on better browser support upcoming.

Chrome:

enter image description here

Canary:

enter image description here

000
  • 26,951
  • 10
  • 71
  • 101