Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Option to prevent "base64 encode inlining" #155

Open
the-hotmann opened this issue Jan 6, 2022 · 15 comments
Open

[Feature Request] Option to prevent "base64 encode inlining" #155

the-hotmann opened this issue Jan 6, 2022 · 15 comments

Comments

@the-hotmann
Copy link

the-hotmann commented Jan 6, 2022

I have tested subfont and actually like it. Had to create some scripted workarounds for some things.

The first one I would like to talk about here.

When --formats='woff2' is given as input parameter subfont inlines the woff2 font base64 encoded into the CSS since this generating a general smaller file.

I ATM work around this by adding --formats='woff2,woff'. As this creates multiple outputformats, they will not be inlined. Thats a dirty workaround - but it works.

I would like to be able to achive the same without having to create the overhead of exporting yet another fontformat (which in this case is not needed).

I really dont like this. A option to prevent that would be awesome. Something like "--no-base64"

@the-hotmann the-hotmann changed the title [Feature Request] Option to prevent "base64 string inlining" [Feature Request] Option to prevent "base64 encode inlining" Jan 6, 2022
@papandreou
Copy link
Collaborator

We used to have that feature, but removed it for 6.0.0: a85fc9c?diff=unified&w=1 🙈

... So we can theoretically put it back. However, you're not saying why it's bad? Do you have a case where it's slower than not inlining the font?

@the-hotmann
Copy link
Author

the-hotmann commented Jan 6, 2022

Well, first, I don't like my code changed anywhere unless I define so. Therefore, I would really appreciate having an option. For those who want base64encodes can go for, the ones which don't, don't have to.

But yes I would like to load my fonts on a separate file since I Early hint them but not the whole CSS file, or not always. It depends on the site. If it's inlined it takes this option from me. Also, every string/file is bigger when base64encoded. And I, in my case do not safe any data by encoding it. But others might do and therefore I can understand it if people want to use it.

Also, this goes against the (eventually) need of modular use. Since I just want to optimize my font file, but nothing else, I would appreciate this function.

@papandreou
Copy link
Collaborator

First off, subfont is deliberately an opinionated tool. Catering to every taste and preference would add too much complexity. Performance is the top goal, so if there's a case where it's reproducibly slower to inline the font, we'll take a look.

Wrt. the hinting, could you share an example of what your HTML and CSS looks like?

@the-hotmann
Copy link
Author

Performance is the top goal, so if there's a case where it's reproducibly slower to inline the font, we'll take a look.

What performance are you talking about?

  1. Backend performance (how fast it's optimized)
  2. Frontend performance (how fast the page loads)

Backend performance:

Like I said, I have this workaround which just created twice as much exportdata and therefore takes longer to export and creates overhead. I can use this, no problem. So yes, instead of using this hacky workaround the backend performance would definitely be better when this option would be given.

Frontend performance:

How big the site overall is, isnt all. Its also about how good can you speed up the page? Since fonts should be loaded before CSS to prevent FOUT, FOIT & FOFT, when set the correct font-display. Therefore I like to change the loadingorder to:

  1. HTML
  2. FONTS
  3. CSS

this prevents nearly all bad font behaviour. Maybe the code of the website is loaded slower, but the website (text) therefore just needs to be rendered once, not twice (as soon as the font is available).
To have control over this the font needs to be loaded over a link/seperat request and not inline.

I wouldn't mind to much if you don't realize this as like I said I have the workaround of rendering WOFF2 and additionally (not needed and therefore 100% overhead) WOFF even if I later do not use this at all.

@the-hotmann
Copy link
Author

For the actual website I will drop you a email. Thanks.

@papandreou
Copy link
Collaborator

What performance are you talking about?

  1. Backend performance (how fast it's optimized)
  2. Frontend performance (how fast the page loads)

Frontend performance. All of subfont's tradeoffs have pointed in the direction of sacrificing build time for page load improvements.

For the actual website I will drop you a email. Thanks.

Thanks for the link to your website! As I understand it, your website contains some existing <link rel=preload type=font/woff2 as=font href=...> hints pointing at some of your fonts, with the purpose of prioritizing the most important ones.

When subfont --formats=woff2 processes your page, it will inject the subset fonts as base64 inside the subfont stylesheet, and strip your original preload tags. This is bad because it undoes your explicit choice of preloading only some of the fonts. Instead you would like those important fonts to still be prioritized.

(For the record, subfont --formats=woff,woff2 also strips the <link rel=preload as=font href=...> tags pointing at your original fonts).

I think it's a fair use case. I wonder if there's a way to make subfont DTRT by default instead of jumping to adding a switch.

Maybe the presence of existing preload tags pointing at some of the original fonts could affect what gets output. Eg. if you preload one out of five fonts, it's a signal that subfont shouldn't base64 inline the other ones?

@the-hotmann
Copy link
Author

the-hotmann commented Jan 10, 2022

Thanks for the link to your website! As I understand it, your website contains some existing <link rel=preload type=font/woff2 as=font href=...> hints pointing at some of your fonts, with the purpose of prioritizing the most important ones.

Exactly. But keep in mind that I was talking about the link header preload which is getting used for Early Hinting and also for (before it was discontinued) HTTP/2 Pushing. So it beeing in the HTML is not the earliest preload, but beeing in the link header.

(For the record, subfont --formats=woff,woff2 also strips the <link rel=preload as=font href=...> tags pointing at your original fonts).

Thats true, but I did not implement it with subfont. I have implemented it via my SSG which adds it to the .htaccess.

I think it's a fair use case. I wonder if there's a way to make subfont DTRT by default instead of jumping to adding a switch.

Since the <link rel=preload type=font/woff2 as=font href=...> is not required and is not always given, it would be hard for subfont to know what headers are set, untill it actually calls the site in a way which is going through the webserver.

Maybe the presence of existing preload tags pointing at some of the original fonts could affect what gets output. Eg. if you preload one out of five fonts, it's a signal that subfont shouldn't base64 inline the other ones?

Thats makes sense, but like I said, the <link rel=preload type=font/woff2 as=font href=...> maybe is not given, and still I could be preloading fonts (via link header), which then is nearly impossible for subfont to know.

There is a difference between head link and header link.

  1. head link is in the head of the HTML and easy to detect for subfont.
  2. header link is in the header of the response from a request, served by a webserver and hard to detect for subfont.
    The second way (header link) is the best way to preload things as invoked as soon as possible (since HTTP/2 Push)

@papandreou
Copy link
Collaborator

Ah, I had missed that you were also using the Link header, mirroring the <link rel=preload ...> tags. Yes, that complicates the idea of magically doing the right thing, as you say.

I see how this ties in with #156 and the desire to have subfont perform a direct replacement of your existing fonts with the subset ones, as that would preserve the path and thus not break your existing Link headers.

That's not exactly how subfont operates, though. In the default mode (without --no-fallbacks) it keeps your original fonts and adds the subset fonts separately (and references the subset fonts with a higher priority in font-family / font declarations). On top of that the subset fonts have a content hash added to their file name to allow a far-future Cache-Control.

In other words doing the direct replacement would be a bit tricky without --no-fallbacks as both the original and subset fonts are still around. I suppose we could rename the original one so it's out of the way, but that could also turn out to be a bit confusing, and it would break some caching schemes.

I think it'll be difficult to get this to work the way you want without at least one mode switch.

@papandreou
Copy link
Collaborator

papandreou commented Jan 12, 2022

@MartinHotmann, what's your caching strategy btw.? If we made subfont write out the subset fonts at the same location as the original fonts (so the Link headers match up), wouldn't it then be difficult to set a far-future Cache-Control on that font? I mean if the contents of the file can be different depending on whether subfont ran (and if it did the set of characters that were traced on the website), it would be hard to guarantee that the url of the font asset changes when its content does?

@the-hotmann
Copy link
Author

the-hotmann commented Jan 12, 2022

Caching strategy is: after successfully overwriting the fonts I use cloudflare-cli (alternatively a native API request) to purge Cloudflares Edge Cache. Since I use a SSG (Static Site Generator) thats good enough. Even if someone calls the page while generating the visitor would get a font which contains the required charset and more. After this, the Edge Cache gets wipes anyway after successfully overwritten. So at no time this produces a not working page.

wouldn't it then be difficult to set a far-future Cache-Control on that font?

Actually I don't see a problem there. Even if you set a far-future (1 years I guess) TTL you can change/overwrite this by changing a link, without changing the URL (which is possible by adding a querystring). This is the native way is telling the client, that something changed at this URL.

@papandreou
Copy link
Collaborator

Okay, thanks. Well yeah, adding a cache buster to the query string also does the job, although I prefer to include a content hash in the file name itself. That means that I don't ever have to purge anything.

@papandreou
Copy link
Collaborator

subfont doing that by default is an attempt to make it play nice with all caching strategies, even when the tool gets applied as the very last step in a build pipeline 😇

@the-hotmann
Copy link
Author

I prefer to include a content hash in the file name itself.

Thats true, this works flawlessly aswell. I considert implementing this.

Just discovered a weird behaviour. the fallback-*.css for me does just contain a unicode-range for one font, but not for another, because it maybe did not get altered, but even if not altered and not the full font, the unicode-range should be set.

port19x added a commit to port19x/port19.xyz that referenced this issue May 7, 2023
Needed a workaround to make subfont do what I want:
Munter/subfont#155
port19x added a commit to port19x/port19.xyz that referenced this issue Nov 29, 2023
@port19x
Copy link

port19x commented Nov 29, 2023

I feel like you're overlooking something obvious in the performance discussion: not everything is on the web.
Making a quick html file with all necessary glyphs and then running it and a target font through the program is universally applicable.

So that's relevant for GUI applications, games, powerusers who want to just modify their own fonts, android devs (?)

I'm reaching a bit, but point stands.
With a name as generic as "subfont" you ought to support the generic usecase imho.

@papandreou
Copy link
Collaborator

Making a quick html file with all necessary glyphs and then running it and a target font through the program is universally applicable.

That sounds like a convoluted way of using subfont instead of a more minimalistic tool that only does the subsetting, such as https://github.com/papandreou/subset-font

With a name as generic as "subfont" you ought to support the generic usecase imho.

To be honest, that's not a very good argument.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants