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

Support for automatic link rel="preload" elements for fonts #24

Closed
codeflorist opened this issue Mar 1, 2024 · 16 comments · Fixed by #136
Closed

Support for automatic link rel="preload" elements for fonts #24

codeflorist opened this issue Mar 1, 2024 · 16 comments · Fixed by #136
Labels
enhancement New feature or request

Comments

@codeflorist
Copy link

SEO- and performance-wise it makes sense to add a <link rel="preload" head-tag for the fonts used by the site.

Since font-file-names and -locations can change (e.g. because of version/hashes), it would be great, if nuxt/fonts does that automatically. Ideally it could be enabled by family, like e.g.:

{ name: 'My Font Family', provider: 'google', preload: true },
@danielroe
Copy link
Member

Adding preload by default can result in over-download fonts in a blocking way as a font may not be used on the page.

This shouldn't be needed if the font face rule + font-family are inlined in the HTML.

Do you have an example where preloading the fonts with Nuxt Fonts makes a positive difference in performance? Would you suggest that setting preload: true would result in just preloading woff2 files, for example? For all weights?

@codeflorist
Copy link
Author

codeflorist commented Mar 3, 2024

I guess the optimal solution would be an automatic one, that dynamically creates the preload-tags for fonts, that are actually used on the current page. They must of course be in the initial HTML - so pre-generated on server.

Otherwise i would definitely make it optional - at least by family, even better by weight/style-variant.

But i guess it's safe to say, that in 95% of all projects you have 1 or 2 fonts pretty much used on every page (a normal body font and sometimes an additional display font for headers. )

Regarding the font-format, i'd only use woff2 (or make it configurable), as that's the de-facto standard now (can i use reports 97,33% support worldwide). And according to this article...

specifying preloading for multiple types of the same resource is discouraged. Instead, the best practice is to specify preloading only for the type the majority of your users are likely to actually use.

As for the actual performance advantage, i don't have any numbers. But it is recommended by google - see here). It reduces flash of unstyled text (FOUT) - a relevant metric for Google's Page Speed score (specifically FCP and LCP). Thus it should be also relevant for SEO. Here is what Page Speed has to say about it:

Consider using <link rel=preload> to prioritise fetching resources that are currently requested later in page load. Learn how to preload key requests

This shouldn't be needed if the font face rule + font-family are inlined in the HTML.

I haven't heard that before, but i guess it could be the case. But maybe preload has additional advantages, like being parsed first or getting handled with priority by the browser. But as Google recommends it, i'm sure it has at least advantages for their speed (and thus SEO) metric.

@danielroe
Copy link
Member

danielroe commented Mar 11, 2024

I've released v0.2.0 with support for font preloading (you'll need to enable with fonts.experimental.addPreloadLinks). I'd appreciate any feedback or performance measurements you or others are able to do. 🙏

@codeflorist
Copy link
Author

Hey Daniel,

Many thanks for the fast implementation!

Unfortunately i cannot get this to work. I have this in my nuxt config:

	fonts: {
		experimental: {
			addPreloadLinks: true
		}
	},

But no preload-link is showing up either in dev, build or generate.

@danielroe
Copy link
Member

@codeflorist Could you provide a reproduction? 🙏

@codeflorist
Copy link
Author

@mklueh
Copy link

mklueh commented Mar 21, 2024

I'm facing a similar issue using UnoCSS and this plugin (I guess).

unocss.config.ts

  presetWebFonts({

      //provider: 'google',

      fonts: {

        sans: "Roboto",

        serif: "Rubik",

        mono: ["Fira Code", "Fira Mono:400,700"]
      }
    })

nuxt.config.ts

  fonts: {
    experimental: {
      addPreloadLinks: true
    }
  }

And when I visit the site, I see fonts getting downloaded from static

image

Maybe I got addPreloadLinks wrong. Is something else needed to store fonts locally during build instead?

@danielroe
Copy link
Member

With this module you do not need the unocss web font preset.

@mklueh
Copy link

mklueh commented Mar 21, 2024

Good to know, and I also was not on the latest version

@agracia-foticos
Copy link

please fix addPreloadLinks, the preload link tag not appears!

@danielroe
Copy link
Member

@agracia-foticos Please open an issue with a reproduction 🙏

@agracia-foticos
Copy link

agracia-foticos commented Apr 17, 2024

@danielroe https://stackblitz.com/edit/nuxt-starter-et4gzh here you are

There isn't any link rel="preload" with Signika hashed name Font

@danielroe
Copy link
Member

danielroe commented Apr 17, 2024

@agracia-foticos Preload links are not inserted in dev mode. (improved docs just now here)

@agracia-foticos
Copy link

@agracia-foticos Preload links are not inserted in dev mode. (improved docs just now here)

Compiling in PROdution mode i dont see <link rel="preload" with each font

@danielroe
Copy link
Member

@agracia-foticos Cloning your reproduction and running build, this was the output:

...
<style>
@font-face{font-family:Signika;src:local("Signika Variable"),url(/_fonts/vEFO2_JTCgwQ5ejvMV0Ox_Kg1UwJ0tKfX6bOjM7-f7e0Mls-xQWzOkeLSd.woff2) format(woff2);font-display:swap;unicode-range:U+0102-0103,U+0110-0111,U+0128-0129,U+0168-0169,U+01A0-01A1,U+01AF-01B0,U+0300-0301,U+0303-0304,U+0308-0309,U+0323,U+0329,U+1EA0-1EF9,U+20AB;font-weight:300 700;font-style:normal}
/** removed more font faces here */
#element{font-family:Signika, "Signika Fallback: Arial"}</style>
<link rel="stylesheet" href="/_nuxt/entry.DFgiMwVT.css">
<link rel="modulepreload" as="script" crossorigin href="/_nuxt/CYhS_UQ5.js">
<link rel="preload" as="font" crossorigin href="/_fonts/vEFO2_JTCgwQ5ejvMV0Ox_Kg1UwJ0tKfX6bOjM7-f7e0Mls-xQWzOkeLSd.woff2">
<link rel="prefetch" as="script" crossorigin href="/_nuxt/rEEB8dd5.js">
<link rel="prefetch" as="script" crossorigin href="/_nuxt/7Il5epJC.js">
...

If you want to continue to discuss, please open a new issue. 🙏 This issue is to track automatic support for preload links, which is a future enhancement.

@codeflorist
Copy link
Author

@danielroe

It seems the preload-tag is not generated for fonts, that are defined in tailwind.config.ts.

I define my font in tailwind-config like this:

	theme: {
		fontFamily: {
			body: ['"Felipa"', ...defaultTheme.fontFamily.sans],
		},
	},

And then set this css inside assets/css/tailwind.css:

  html {
    @apply font-body;
  }

Basically, nuxt/fonts is correctly picking up and downloading this font with everything seemingly working correctly, but it does not create the preload-tag.

Here is a stackblitz:
https://stackblitz.com/edit/nuxt-starter-xrzkqs?file=app.vue

If you add this to app.vue, the preload-tag gets added correctly:

<style scoped>
div {
  font-family: Felipa, serif;
}
</style>

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

Successfully merging a pull request may close this issue.

4 participants