Next.js — Как добавить тег внутри с буквальным значением строки атрибута onload?

#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 /