admin管理员组

文章数量:1303335

On a Next.js project, I'd like to get some initial HTML with this exact same content inside the <head>:

<link href="..." rel="stylesheet" media="print" onload="this.media='all'" />

What I have in my code, inside Next.js's <Head> ponent, is:

{ /* @ts-ignore */ }
<link href="..." rel="stylesheet" media="print" onload="this.media='all'" />

Without the @ts-ignore it says:

Property 'onload' does not exist on type 'DetailedHTMLProps<LinkHTMLAttributes, HTMLLinkElement>'. Did you mean 'onLoad'? ts(2322)

And if I use onLoad instead of onload I get:

Type 'string' is not assignable to type '(event: SyntheticEvent<HTMLLinkElement, Event>) => void'. ts(2322)

The problem is that the server-side generated HTML that I get has:

<link href="..." rel="stylesheet" media="print" />

And only once the page has rehydrated it updates to:

<link href="..." rel="stylesheet" media="all" onload="this.media='all'">

I've found this issue on GitHub but it doesn't help as I'm not using Google Fonts but Typography, so I can't use next-google-fonts: .js/issues/12984

I'm thinking about adding a ref to that link tag and setting the attribute using setAttribute, which will hopefully work on the server-side as well, but wondering if there's a simpler way to do it.

On a Next.js project, I'd like to get some initial HTML with this exact same content inside the <head>:

<link href="..." rel="stylesheet" media="print" onload="this.media='all'" />

What I have in my code, inside Next.js's <Head> ponent, is:

{ /* @ts-ignore */ }
<link href="..." rel="stylesheet" media="print" onload="this.media='all'" />

Without the @ts-ignore it says:

Property 'onload' does not exist on type 'DetailedHTMLProps<LinkHTMLAttributes, HTMLLinkElement>'. Did you mean 'onLoad'? ts(2322)

And if I use onLoad instead of onload I get:

Type 'string' is not assignable to type '(event: SyntheticEvent<HTMLLinkElement, Event>) => void'. ts(2322)

The problem is that the server-side generated HTML that I get has:

<link href="..." rel="stylesheet" media="print" />

And only once the page has rehydrated it updates to:

<link href="..." rel="stylesheet" media="all" onload="this.media='all'">

I've found this issue on GitHub but it doesn't help as I'm not using Google Fonts but Typography., so I can't use next-google-fonts: https://github./vercel/next.js/issues/12984

I'm thinking about adding a ref to that link tag and setting the attribute using setAttribute, which will hopefully work on the server-side as well, but wondering if there's a simpler way to do it.

Share Improve this question asked Sep 29, 2020 at 14:15 DanzigerDanziger 21.2k6 gold badges58 silver badges88 bronze badges 3
  • What I'd do is create a ponent called link that wraps Next/Link then set the logic up in there. so you'd have Link-><a onload></a> - that way the events should work properly I think. – Mrk Fldig Commented Oct 4, 2020 at 9:27
  • @Danziger did you find a solution for the problem? I ran into the exact same issue. – RumTraubeNuss Commented Apr 10, 2021 at 9:05
  • @RumTraubeNuss Yes, you can see this working here: andorratechvalley.. I have just added an answer with the solution. Hope it helps (: – Danziger Commented Apr 18, 2021 at 17:57
Add a ment  | 

1 Answer 1

Reset to default 6

Updated answer (Next 13-14):

Next.js now offers Google and local fonts optimization out of the box. Here's how to load Google fonts:

// This will add the Inter font to your own deployment, serving 
// them from your domain without sending any data to Google:
import { Inter } from 'next/font/google';

// If loading a variable font, you don't need to specify the font weight
const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}

Original answer (Next 12):

So I eventually fixed this using a <style> tag with dangerouslySetInnerHTML in a custom _document.js. All together it should look like this:

<link rel="preconnect" href="https://fonts.googleapis." crossOrigin="anonymous" />

<link rel="preload" href="https://fonts.googleapis./css2?family=Inconsolata:wght@400;600&family=Karla:wght@700&display=swap" as="style" />

<style dangerouslySetInnerHTML={ {
  __html: `</style>
    <link
      rel="stylesheet"
      href="https://fonts.googleapis./css2?family=Inconsolata:wght@400;600&family=Karla:wght@700&display=swap"
      media="print"
      onload="this.media='all';"
    />
    <style>`
} }></style>

<noscript>
  <link
    rel="stylesheet"
    type="text/css"
    href="https://fonts.googleapis./css2?family=Inconsolata:wght@400;600&family=Karla:wght@700&display=swap" />
</noscript>

Which generates the following output:

<link rel="preconnect" href="https://fonts.googleapis." crossorigin="anonymous"/>

<link rel="preload" href="https://fonts.googleapis./css2?family=Inconsolata:wght@400;600&amp;family=Karla:wght@700&amp;display=swap" as="style"/>

<style></style>

<link rel="stylesheet" href="https://fonts.googleapis./css2?family=Inconsolata:wght@400;600&family=Karla:wght@700&display=swap" media="print" onload="this.media='all';" />

<style></style>

<noscript><link rel="stylesheet" type="text/css" href="https://fonts.googleapis./css2?family=Inconsolata:wght@400;600&amp;family=Karla:wght@700&amp;display=swap"/></noscript>

Not pretty, but better than having a <div> inside the <head> (which is not interpreted correctly by all browsers).

There's an open RFC to create a RawHTML ponent or extend Fragment to accept dangerouslySetInnerHTML so that something like this is possible without hacks, but it's been more than a year since it was created.

Also, there's quite a long discussion about this as well with a few different solutions (hacks) that seem to work.

You can see the solution working here: https://andorratechvalley./

本文标签: