vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.63k stars 26.93k forks source link

How to load properly the "Local fonts" formats? #49207

Open loick opened 1 year ago

loick commented 1 year ago

Verify canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: arm64
      Version: Darwin Kernel Version 22.4.0: Mon Mar  6 21:01:02 PST 2023; root:xnu-8796.101.5~3/RELEASE_ARM64_T8112
    Binaries:
      Node: 18.15.0
      npm: 8.15.0
      Yarn: 1.22.19
      pnpm: N/A
    Relevant packages:
      next: 13.3.4
      eslint-config-next: 13.3.4
      react: 18.2.0
      react-dom: 18.2.0

Which area(s) of Next.js are affected? (leave empty if unsure)

Font optimization (next/font)

Link to the code that reproduces this issue

/

To Reproduce

Hi everyone,

I'm using next/font on my app in order to load some local fonts I have in my public directory. I used this documentation for this: https://nextjs.org/docs/basic-features/font-optimization#local-fonts

This is the piece of code, loading the fonts:

const poppins = localFont({
  preload: true,
  display: 'swap',
  src: [
    {
      path: '../public/fonts/Poppins-Regular.woff',
      weight: 'normal',
      style: 'normal',
    },
    {
      path: '../public/fonts/Poppins-Regular.woff2',
      weight: 'normal',
      style: 'normal',
    },
    {
      path: '../public/fonts/Poppins-Italic.woff',
      weight: 'normal',
      style: 'italic',
    },
    {
      path: '../public/fonts/Poppins-Italic.woff2',
      weight: 'normal',
      style: 'italic',
    },
    {
      path: '../public/fonts/Poppins-SemiBold.woff',
      weight: 'bold',
      style: 'normal',
    },
    {
      path: '../public/fonts/Poppins-SemiBold.woff2',
      weight: 'bold',
      style: 'normal',
    },
  ],
  variable: '--font-poppins',
})

Nothing fancy, the only particularity is the font extension, as you can see I'm trying to load woff & woff2 fonts.

Since I'm using Tailwind btw, I'm adding the fonts like this in my component:

className={classNames(poppins.variable, makinac.variable)}

Describe the Bug

CleanShot 2023-05-04 at 15 10 31@2x As you can see here, with this setup, all of the fonts are loaded. The woff and the woff2.

Maybe I missed something, but do you know how I could only make the browser load the right font (woff2) and loading the other one (woff) as a fallback? When I read the doc, the fallback key only supports the system-ui fonts.

Thanks!

Expected Behavior

Only the woff2 should be loaded in the browser, not the woff version of the font.

Which browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

Vercel

joaopbnogueira commented 1 year ago

Just to bump this. Ideally the src array element should also support a set of file paths for fonts (with different) formats, instead of a single path. Something along the lines of:

src: [
    {
      paths: [
        '../../public/fonts/CeraPro/Cera-Pro-Regular.woff',
        '../../public/fonts/CeraPro/Cera-Pro-Regular.woff2'
      ],
      weight: '400',
      style: 'normal',
    },
    {
      path: '../../public/fonts/CeraPro/Cera-Pro-Medium.woff',
      weight: '500',
      style: 'normal',
    },
    {
      path: '../../public/fonts/CeraPro/Cera-Pro-Bold.woff',
      weight: '700',
      style: 'normal',
    },
  ],

It would also be nice if we could configure "preload" individually instead of for the whole group.

tylergalpin commented 1 year ago

+1-ing @joaopbnogueira feedback. I'm having the same issue where my pages may only use one or two weights per page, and not having to include all the others would be great. It's getting to a point in performance where I am debating removing all fonts from my project except one.

AliYusuf95 commented 1 year ago

+1, Also I'd suggest to have declarations per item .. since currently it's impossible to combine fonts using current api.

  src: [
    {
      path: [
        '../../public/fonts/CeraPro/Cera-Pro-Regular.woff',
        '../../public/fonts/CeraPro/Cera-Pro-Regular.woff2',
      ],
      weight: '100',
      style: 'normal',
      declarations: [
        {
          prop: 'unicode-range',
          value:
            'U+0600–U+06FF',
        },
      ],
      preload: false,
    },
    {
      path: ['../../public/fonts/CeraPro/Cera-Pro-Medium.woff'],
      weight: '100',
      style: 'normal',
      declarations: [
        {
          prop: 'unicode-range',
          value: 'U+2d, U+3d',
        },
      ],
      preload: false,
    },
    {
      paths: ['../../public/fonts/CeraPro/Cera-Pro-Bold.woff'],
      weight: '100',
      style: 'normal',
    },
]
in2erval commented 1 year ago

+1, Also I'd suggest to have declarations per item .. since currently it's impossible to combine fonts using current api.

Yes, this is something I'd really like to see added. I'm currently struggling to do proper font subsetting for local fonts, since there's no explicit documentation on next.js regarding specifying subsets for locally-loaded fonts (that have been modified via pyftsubset). Having per-src declarations would allow for this:

const font = localFont({
  src: [
    {
      path: "./fonts/my-font-latin.woff2",
      declarations: [{ prop: "unicode-range", value: "U+0000-00FF" }]
    },
    // other subsets if required to fill U+0100-2FFF
    {
      path: "./fonts/my-font-cjk.woff2",
      declarations: [{ prop: "unicode-range", value: "U+3000-FFFF" }]
    },
  ]
});

Resulting in:

@font-face {
  unicode-range: U+0000-00FF;
  font-family: '__font_028742'; /* Same font family as below */
  src: url(/_next/static/media/76abc2201fd876fb-s.p.woff2) format('woff2');
  font-display: swap;
}
@font-face {
  unicode-range: U+3000-FFFF;
  font-family: '__font_028742'; /* Same font family as above */
  src: url(/_next/static/media/1e91e29b5a5efa96-s.p.woff2) format('woff2');
  font-display: swap;
}
Alopwer commented 6 months ago

Are there any updates on this bug/feature request? I can pick this up

renanss commented 4 months ago

Looking forward for a solution. I also need to load multiple file formats for the same font.

syi0808 commented 3 months ago

guys, I implemented the draft.