#javascript #reactjs #next.js #server-side-rendering #head
#javascript #reactjs #next.js #рендеринг на стороне сервера #head
Вопрос:
На 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
него говорится:
Свойство ‘onload’ не существует для типа ‘DetailedHTMLProps<LinkHTMLAttributes, htmllink Element>’. Вы имели в виду «onLoad»? ts(2322)
И если я использую onLoad
вместо onload
я получаю:
Тип ‘string’ не может быть присвоен типу ‘(событие: SyntheticEvent<HTMLLINK Элемент, событие>) => void’. ts(2322)
Проблема в том, что сгенерированный на стороне сервера HTML, который я получаю, имеет:
<link href="..." rel="stylesheet" media="print" />
И только после регидратации страницы она обновляется до:
<link href="..." rel="stylesheet" media="all" onload="this.media='all'">
Я нашел эту проблему на GitHub, но это не помогает, так как я не использую шрифты Google, но Typography.com , поэтому я не могу использовать next-google-fonts
: https://github.com/vercel/next.js/issues/12984
Я подумываю о добавлении a ref
к этому link
тегу и настройке атрибута using setAttribute
, который, надеюсь, будет работать и на стороне сервера, но интересно, есть ли более простой способ сделать это.
Комментарии:
1. Что бы я сделал, так это создал компонент с именем link, который переносит Next/Link, а затем устанавливает там логику. таким образом, у вас будет Link-><a onload></a> — я думаю, что таким образом события должны работать правильно.
2. @Danziger вы нашли решение проблемы? Я столкнулся с точно такой же проблемой.
3. @RumTraubeNuss Да, вы можете увидеть, как это работает здесь: andorratechvalley.com . Я только что добавил ответ с решением. Надеюсь, это поможет (:
Ответ №1:
Итак, я в конечном итоге исправил это, используя <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;600amp;family=Karla:wght@700amp;display=swap" as="style" />
<style dangerouslySetInnerHTML={ {
__html: `</style>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;600amp;family=Karla:wght@700amp;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;600amp;family=Karla:wght@700amp;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;600amp;amp;family=Karla:wght@700amp;amp;display=swap" as="style"/>
<style></style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;600amp;family=Karla:wght@700amp;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;600amp;amp;family=Karla:wght@700amp;amp;display=swap"/></noscript>
Не очень красиво, но лучше, чем иметь <div>
внутри <head>
(который неправильно интерпретируется всеми браузерами).
Существует открытый RFC для создания RawHTML
компонента или расширения Fragment
для принятия dangerouslySetInnerHTML
, чтобы что-то подобное было возможно без взломов, но с момента его создания прошло больше года.
Кроме того, по этому поводу также ведется довольно долгое обсуждение с несколькими различными решениями (взломами), которые, похоже, работают.
Вы можете увидеть, как работает решение здесь: https://andorratechvalley.com /