Open Bug 1486158 Opened 7 years ago Updated 3 years ago

Fonts using font-display always timeouts, even when they are taken from browser's cache

Categories

(Core :: Layout: Text and Fonts, defect, P3)

61 Branch
defect

Tracking

()

UNCONFIRMED

People

(Reporter: oscarcala, Unassigned)

Details

Attachments

(6 files)

User Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36 Steps to reproduce: 1) Use a definition like this: @font-face { font-family: "Myfont; src: url("/resources/fonts/Myfont-BoldItalic.eot"); src: url("/resources/fonts/Myfont-BoldItalic.eot?") format("embedded-opentype"), url("/resources/fonts/Myfont-BoldItalic.otf") format("truetype"); font-weight: bold; font-style: italic; font-display: optional; } 2) Have a html element using the font: .landing-home-page-index--title { font-family: "MyFont", Arial, sans-serif; } 3) Have the webserver sending the following response header for the font file: Response Headers HTTP/1.1 304 Not Modified x-powered-by: Express date: Sat, 25 Aug 2018 00:37:28 GMT server: Apache etag: "eb6c-56f4138f9b6c0" cache-control: max-age=31557600 connection: close Request Headers: GET /resources/fonts/Myfont-Regular.otf HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0 Accept: application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost:8080/landing/home-page/assets/0.1/styles/app.css Connection: keep-alive If-None-Match: "ede4-56f413908f900" Actual results: 4) When the page is loaded, a message is displayed in the console downloadable font: download timed out (font-family: "MyFont" style:normal weight:400 stretch:100 src index:1) source: http://localhost:8080/resources/fonts/MyFont-Regular.otf The network panel shows: In the column transferred: 58.86KB In the column Transferred: cached Timing: Waiting 326ms, everything else 0ms The font is not rendered. Expected results: The font should be rendered. No error in the console should be displayed
I wanted to test this issue but I do not have enough information. Could you please tell me more details about how to reproduce this issue? I think it will be a good idea to attach the 'HTML' file and the link from where I can download the "MyFont-Regular.otf" font. Maybe you should add the "Myfont-BoldItalic.woff" file to the src. Thanks
Flags: needinfo?(oscarcala)
Flags: needinfo?(oscarcala)
Hi Daniel. I attached a sample HTML file. Also some images. Note the fonts use font-display:optional. This is causing the font timeout. I used fonts loaded from google fonts since the issue it is still reproducible with that server. The server properly sends the cache-control header when serving the font files. However not always, all the files are cached. I have experimented with the Connection Speed Throtling control. It Seems the cache behavior changes a lot based on connection speed: * When connection speed is low, the files are not cached, they are revalidated with the server, causing the font to time out. * When connection speed is high, the files are not always cached in the first page load. Several page reloads have to occur for the file to be cached. Question: Does the firefox cache behavior change based on the connection speed? is there any documentation about this? * Some times the requests in the network panel are reported as cached. However the font times out and doesn't render. Question: if the files are already cached an served from the cache, why do they time out? *When the font is rendered, I note that the request is not even reported in the network panel. Question: Why are the request sometimes reported as cached and some other times not reported at all?
Attached image firstPageLoad.png
Attached image secondPageLoad.png
Attached image fifthPageLoad.png
The images were taken using no Throttling. When Throttling is used, depending no the selected value, the behavior is completely different. The lower the speed, the smaller the probability of the fonts being rendered even after multiple page loads.
Component: Untriaged → CSS Parsing and Computation
Product: Firefox → Core
:mayhemer
Adding :mayhemer as suggested by Patrick McManus. Thank you everyone for your help.
I took that test file and reduced it down to a single font load to test with. On my connection, the font file usually takes around 50 ms to load according to the Network devtools panel. I tried repeatedly Shift+Reloading the page, and for load times slightly more than that it looks like the font load times out and I get the default serif font. After a Shift+Reload where the font times out, but the network request completes, if I then do a normal Reload the network panel shows "Transferred: cached" but still takes up some time in the timeline. If that time is significant -- e.g. I got one where "Wait 63 ms" -- then this still causes us to time out the font load. If it's less -- one other time I got "Blocked 3 ms, Wait 35 ms, Total 38 ms" -- then the font load from the cache succeeds. For Firefox, the timeout used for font-display:optional is 100 ms, but that is a timeout from deciding to kick off the load until we are notified the load is complete, so this plausibly includes a bit more time than is displayed in the Network panel timeline, which I guess comes from the network code's own timestamps. The spec for font-display:optional at https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-display is loose enough that our behaviour is permissible, but I wonder if we should be doing something like checking if the font will come from the cache and if so, to not use that short timeout. It's not always going to be the case that loading from the cache is fast (as Race Cache With Network has shown us), but it still may be worth not giving up so quickly in this case. Jonathan, what do you think?
Component: CSS Parsing and Computation → Layout: Text and Fonts
Flags: needinfo?(jfkthame)
So it sounds like we're quite often timing out font loads from the network cache. That does seem a bit unfortunate; but if loading a resource from cache can't be guaranteed to be "pretty fast", then it's the expected behavior with font-display:optional, as that descriptor says "I don't want to keep the user waiting for this font, and I don't want to swap it in (causing a re-layout) after the page has been displayed; so if it's not available near-immediately, ignore it". Once the resource has actually been loaded successfully (even if too late to be swapped into the page), it will get cached in the user font cache such that it can be used immediately on a subsequent load, without needing to hit the network. But until that has happened, the load involves a network request, and as we don't know how long that might take (regardless of whether the resource is cached at the networking layer), the short timeout is used. It does seem unfortunate that loading the resource from network cache is often not fast enough. Does the behavior seem better if we bump the "short" timeout slightly, e.g. setting gfx.downloadable_fonts.fallback_delay_short to 200 (milliseconds) instead of the default 100? That should increase the chances of successfully loading a cached font resource; the question would be whether the longer potential blocking time before we render the text becomes too noticeable. Do we have a way to (performantly) query the networking layer to find out whether a given resource is available in cache or not? If so, we could consider allowing a slightly longer "short timeout" in this case, in the expectation that the resource is going to be successfully loaded within a fairly reasonable time -- the risk of a really slow load, or complete failure, is presumably much less than if we're having to fetch over the network. But I don't know if that's something we can determine cheaply enough to use it to adjust the timeout here. (Better would be if we could reduce the latency or general slowness of loading a resource that is already in the network layer's cache; I'm sad we frequently can't load a font resource from there within 100ms. But it may simply be that too many other things are competing for networking attention or disk i/o or whatever.)
Flags: needinfo?(jfkthame)
hi All, thanks for your comments on this topic. Yes it is very unfortunate that even when the fonts have been cached they timed out. It would be nice to have it working since font-display:optional combined with cache seems to be a very good strategy for font loading without any type of flash (FOUT/FOIT). This strategy does work pretty well in chrome and it is very consistent. I did some testing with gfx.downloadable_fonts.fallback_delay_short in 200ms, and the behavior doesn't change to much, even though it is better. It is more likely to get the fonts loaded from cache quicker (3rd page load, 4th page load). Regarding the slowness of loading a resource ... why is the browser sometimes revalidating the request even when the cache headers are correct regarding the cahce control. Headers like the ones below are not supposed to cause a revalidation request, right? or are they? age:1658395 cache-control: public, max-age=31536000 date: Wed, 29 Aug 2018 11:46:39 GMT expires: Thu, 29 Aug 2019 11:46:39 GMT last-modified: Wed, 11 Oct 2017 18:24:02 GMT But once, a condition is met, a condition that still is unclear, Firefox stops revalidating the request, it doesn't report the requests anymore in the netwrok panel, and the fonts never timeout again... Do you know what is the that condition? Is there a way that we can make it meet the condition quicker?
I believe once the fonts have been successfully loaded, they end up in our internal webfont cache (i.e. a cache of font resources that have been validated and instantiated on the platform; distinct from the network-level http cache); then the preloaded font can be used from the cache when reloading the page, without making a network request at all. Offhand I'm not sure what's the best way forward here...
Priority: -- → P3
(In reply to Jonathan Kew (:jfkthame) from comment #11) > Do we have a way to (performantly) query the networking layer to find out > whether a given resource is available in cache or not? If so, we could > consider allowing a slightly longer "short timeout" in this case, in the > expectation that the resource is going to be successfully loaded within a > fairly reasonable time -- the risk of a really slow load, or complete > failure, is presumably much less than if we're having to fetch over the > network. But I don't know if that's something we can determine cheaply > enough to use it to adjust the timeout here. I don't know the answer to this whether there is a way to query the network layer like this, but if so, I would be in favour of trying this approach.
Honza, is there a way to query whether a given channel will be getting its content from the network cache, maybe just before or after opening the channel? For a small file, should it be faster to do such a query than the actual load of the data, or should it be much the same?
Flags: needinfo?(honzab.moz)
I don't think the question "is a channel getting the content from the cache" is the right question for solving this "bug". The reason for the delay is the necessary server validation round trip. If it takes 300ms on localhost, then the server validation has a performance issue. If it takes 300ms from a remote server, then it may be because of a network with long rtt or again server has a perf issue. Reading some of the comments it's apparent that most of you don't know how caching works according how you navigate or reload the page. When you reload a page with only F5 (NOT Ctrl-F5!) we still do revalidation of all resources on the page. The font response has an ETag, so we do a conditional request and the server responds with 304, we then server from the cache. If you navigate to the page (link click, bookmark click, going directly), then the resource, according the info provided - specifically max-age, should come from the cache w/o a round trip to the server and likely make it in 200ms. If we are going to do a round trip or not is known asynchronously after opening the channel and there is no API to inform the consumer about it and we don't plan to provide it, as I believe it's not a good design. If the font content is not changing then it may be possible to use `Cache-control: immutable` response header that will bypass revalidation on F5.
Flags: needinfo?(honzab.moz)

Hi everybody, I'm getting back to this issue.

After some months, the behavior continues the same in our implementation. I would like to know if there is a way to help to resolve this. I think the reproduction steps are not far from the general use case, so I'm wondering if there is something specific I'm doing that makes this work out of the expectations. Or, if definetelly there is a defect in the behavior and this can be considered a compliance issue that may be we can report in canisue.com.

Would this be something in my localhost server? Let say it is. But this doesn't work anyways in our production environments and we have such a good infrastructure that serves more than 8M pageviews per day with very low latency, CDN (akamai), 64+ servers, loadbalancing and other optimizations in the middle. So, if it doesn't work in a production environment like this, would this work for other people that might have less infrastructure?

If you navigate to the page (link click, bookmark click, going directly), then the resource, according the info provided - specifically max-age, should come from the cache w/o a round trip to the server and likely make it in 200ms.

Specifically this is not happening.

I will try Cache-control: immutable, this week, but I'm wondering if I'm the only one seeing this issue, or how do people in general handle font-display:optional in recent versions of firefox (This works according to the expectations in Chrome).

but I'm wondering if I'm the only one seeing this issue

You're not the only one, it's an issue on https://warwick.ac.uk/study too (see element div.text) too. We've discussed the idea of a Link header to try and preload the fonts but not tried it.

Did you get anywhere with Cache-control: immutable, Oscar?

Oh, and I can reproduce this in 70.0a1 (2019-08-29) (64-bit) nightly - it should probably be set to NEW, no?

Hi,

I found this bug whilst working on some web font issues reported on a couple of our websites under Firefox after we switched to font-display: optional.

After quite a bit of tinkering here is what we have found has improved the situation for us:

  • Ensuring that immutable is added to the Cache-Control header of your font. We were setting this against our S3 bucket but our CDN was removing it, so it is worth double checking.
  • Ensuring that there is a <link rel="preload"/> for every font that could be used on the page. For us this meant preloading all variants of our font as our fonts are loaded centrally and used by many sub-sites that we have limited control over.

An example of one of our font preloads:

<link rel="preload" href="https://nav.files.bbci.co.uk/orbit/ece9cb048f668bbc4cc6214737a6cdb6/font/BBCReithSans_W_Rg.woff2" as="font" type="font/woff2" crossorigin="">

I found this SmashingMagazine article useful for understanding what rel=preload is and roughly how it works https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/.

The above steps have made web fonts on Firefox work quite well for websites that use a small number of web fonts. Unfortunately sites that use quite a few variants of our font are still encountering issues; see https://www.bbc.com/culture/article/20201112-the-eye-of-providence-the-symbol-with-a-secret-meaning as an example.

For me and my colleagues the header font loads like so:

But it should look like so:

Many other fonts on this page do load correctly, but the header font consistently has issues. I would greatly appreciate any advice folks have to see how we can improve this situation.

Attached image incorrect font.png
Attached image correct font.png

Apologies I incorrectly uploaded images in my previous comment. I have attached the correct and incorrect font images to this issue.

Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: