在 Next.js 项目中,我想获得一些初始 HTML,其中的内容完全相同
<head>
:
<link href="..." rel="stylesheet" media="print" onload="this.media='all'" />
我的代码中 Next.js 的
<Head>
组件内的内容是:
{ /* @ts-ignore */ }
<link href="..." rel="stylesheet" media="print" onload="this.media='all'" />
如果没有
@ts-ignore
,它会说:
类型“DetailedHTMLProps
”上不存在属性“onload”。您指的是“onLoad”吗? ts(2322)
如果我使用
onLoad
而不是 onload
我得到:
类型“string”不可分配给类型“(event: SyntheticEvent
) => void”。 ts(2322)
问题是我得到的服务器端生成的 HTML 有:
<link href="..." rel="stylesheet" media="print" />
并且只有当页面重新水合后,它才会更新为:
<link href="..." rel="stylesheet" media="all" onload="this.media='all'">
我在 GitHub 上发现了这个问题,但它没有帮助,因为我没有使用 Google Fonts,而是使用 Typography.com,所以我无法使用
next-google-fonts
:https://github.com/vercel/next .js/issues/12984
我正在考虑向该
ref
标签添加 link
并使用 setAttribute
设置属性,这希望也能在服务器端工作,但想知道是否有更简单的方法来做到这一点。
更新答案(下13-14):
Next.js 现在提供开箱即用的 Google 和本地字体优化。以下是加载 Google 字体的方法:
// 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>
)
}
原答案(下12):
所以我最终在
自定义
<style>
中使用带有
dangerouslySetInnerHTML
的
_document.js
标签修复了这个问题。总而言之,它应该看起来像这样:
<link rel="preconnect" href="https://fonts.googleapis.com" crossOrigin="anonymous" />
<link rel="preload" href="https://fonts.googleapis.com/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.com/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.com/css2?family=Inconsolata:wght@400;600&family=Karla:wght@700&display=swap" />
</noscript>
生成以下输出:
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin="anonymous"/>
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;600&family=Karla:wght@700&display=swap" as="style"/>
<style></style>
<link rel="stylesheet" href="https://fonts.googleapis.com/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.com/css2?family=Inconsolata:wght@400;600&family=Karla:wght@700&display=swap"/></noscript>
不太漂亮,但比在
<div>
中包含 <head>
更好(并非所有浏览器都能正确解释)。
有一个 open RFC 可以创建
RawHTML
组件或扩展 Fragment
来接受 dangerouslySetInnerHTML
,这样就可以在没有黑客的情况下实现类似的功能,但距离创建已经一年多了。
此外,还有对此进行了相当长的讨论,以及一些似乎有效的不同解决方案(黑客)。
您可以在此处查看解决方案:https://andorratechvalley.com/