Heim > Web-Frontend > CSS-Tutorial > Verantwortungsbewusstes Abschluss in Next.js

Verantwortungsbewusstes Abschluss in Next.js

Joseph Gordon-Levitt
Freigeben: 2025-03-21 10:57:11
Original
822 Leute haben es durchsucht

Verantwortungsbewusstes Abschluss in Next.js

Markdown ist in der Tat ein großartiges Format. Es ist nah genug an einfachem Text, dass jeder schnell lernen kann, und es ist gut strukturiert genug, um analysiert und schließlich in das gewünschte Format umgewandelt zu werden.

Allerdings: Analyse, Verarbeitung, Verbesserung und Konvertieren erfordert Code. Die Bereitstellung all dieser Code im Client hat einen Preis. Es ist an sich nicht riesig, aber es ist immer noch ein paar Dutzend KB Code, die nur zur Behandlung von Markdown und keinem anderen Zweck verwendet werden.

In diesem Artikel werde ich erklären, wie ich in einer nächsten.js -Anwendung mit dem Unified/Bemerkung -Ökosystem aus dem Kunden ferngehalten werden kann (ich weiß wirklich nicht, welchen Namen zu verwirrend ist).

Hauptideen

Die Idee ist, nur die Markdown -Funktion in der getStaticProps -Funktion in Next.js zu verwenden, um dies während des Erstellungsprozesses zu tun (wenn Sie den inkrementellen Build von Vercel verwenden, wird dies in der nächsten serverlosen Funktion durchgeführt), wird jedoch keineswegs auf der Client -Seite verwendet. Ich denke, getServerSideProps ist auch in Ordnung, aber ich denke, getStaticProps ist eher ein häufiger Anwendungsfall.

Dies gibt einen AST zurück, der durch Parsen und Verarbeitung von Markdown -Inhalten ( abstrakter Syntaxbaum , dh ein großes verschachteltes Objekt, das unseren Inhalt beschreibt) erzeugt wird, und der Kunde ist nur dafür verantwortlich, den AST in eine React -Komponente zu verwandeln.

Ich denke, wir können sogar als HTML direkt in getStaticProps Markdown machen und es zurückgeben, um es mit dangerouslySetInnerHtml zu rendern, aber wir sind nicht so Menschen. Sicherheit ist wichtig. Auch die Flexibilität, den Markdown so zu machen, wie wir es mit unseren eigenen Komponenten gewünscht haben, anstatt es als reines HTML zu machen. Ernsthaft, Freunde, tu das nicht. ?

 Export const GetstaticProps = async () => {
  // Erhalten Sie Markdown -Inhalte von irgendwoher, z. B. CMS oder so. In diesem Artikel ist dies nicht wichtig. Es kann auch aus der Datei gelesen werden.
  const markdown = Warten Sie GetmarkdownContentFromomewhere ()
  const ast = parSemarkdown (Markdown)

  return {props: {ast}}
}

const page = props => {
  // Dies umfasst normalerweise Ihr Layout und so weiter, aber es wird hier zum Einfachheit halber weggelassen.
  Zurückkehren<markdownrenderer ast="{props.ast}"></markdownrenderer>
}

Standardseite exportieren
Nach dem Login kopieren

Markdown analysieren

Wir werden das Unified/Bemerkung -Ökosystem verwenden. Wir müssen einheitlich und bemerkenswertig installieren, das war's. Es ist relativ einfach, den Markdown selbst zu analysieren:

 Import {Unified} aus 'Unified'
Importierendurchdringung aus "Bemerkung-Parse"

const parSemarkdown = content => Unified (). Verwendung (RemindParse) .Parse (Inhalt)

Exportieren Sie den Standard -Parsemarkdown
Nach dem Login kopieren

Was mich lange gebraucht habe, um zu verstehen, ist, warum meine zusätzlichen Plugins wie Bemerkung-Prism oder Bemerkung nicht so funktionieren. Dies liegt daran, dass die Unified .parse(..) -Methode AST mit dem Plugin nicht verarbeitet. Wie der Name schon sagt, analysiert es nur den Markdown -String -Inhalt in einen Baum.

Wenn wir möchten, dass Unified unsere Plugins anwendet, müssen wir Unified einheitlich machen, was sie als "Auslauf" -Phase bezeichnen. Normalerweise erfolgt dies mit .process(..) anstelle .parse(..) -Methode. Leider analysiert .process(..) nicht nur Markdown und wendet Plugins an, sondern auch in ein anderes Format (z. Und das wollen wir nicht, weil wir das AST behalten wollen, sondern nachdem es vom Plugin verarbeitet wurde.

 <code>| ........................ process ........................... | | .......... parse ... | ... run ... | ... stringify ..........| -------- ----------输入->- | 解析器| ->- 语法树->- | 编译器| ->- 输出-------- | ---------- X | -------------- | 变换器| --------------</code>
Nach dem Login kopieren

Daher müssen wir nur die Analyse- und Ausführenphasen ausführen, aber nicht die Stringungsphase. Unified bietet keine Methode zur Ausführung von zwei dieser drei Stufen, bietet jedoch eine separate Methode für jede Phase, damit wir es manuell tun können:

 Import {Unified} aus 'Unified'
Importierendurchdringung aus "Bemerkung-Parse"
Import BemerkungPrismus aus "Bemerkung-Prismus"

const parSemarkdown = content => {
  const Engine = Unified (). Verwendung (Remarkse).
  const ast = Engine.Parse (Inhalt)

  // Unified's * Process * enthält drei verschiedene Phasen: Parsen, Ausführen und Stringung. Wir wollen die String -Phase nicht durchgehen, weil wir AST behalten wollen, damit wir nicht ".Process (..)` nennen können. Das Aufrufen von ".Parse (..)` reicht jedoch nicht aus, da das Plugin (und daher Prisma) während der Laufphase ausgeführt wird. Daher müssen wir die Laufphase manuell anrufen (zum Einfachheit halber synchron).
  // Siehe: https://github.com/unifiedjs/unified#description
  Return Engine.Runsync (AST)
}
Nach dem Login kopieren

Sehen! Wir haben den Markdown in einen Syntaxbaum analysiert. Wir führen dann unser Plugin auf diesem Baum aus (er wird so leicht synchron, aber Sie können es asynchron mit .run(..) tun). Wir haben unseren Baum jedoch nicht in andere Syntaxen wie HTML oder JSX umgewandelt. Wir können es selbst im Rendering tun.

Markdown machen

Jetzt, wo wir unseren coolen Baum bereit haben, können wir ihn nach Absicht machen. Lassen Sie uns eine MarkdownRenderer -Komponente erstellen, die den Baum als ast -Eigenschaft nimmt und ihn mit der React -Komponente macht.

 const getComponent = node => {
  Switch (node.type) {
    Fall 'Wurzel':
      return ({Kinder}) =>  {Kinder} >

    Fall 'Absatz':
      return ({Kinder}) =><p> {Kinder}</p>

    Fall "Betonung":
      return ({Kinder}) => <em>{Kinder}</em>

    Fall 'Überschrift':
      return ({Kinder, Tiefe = 2}) => {
        const hading = `H $ {Tiefe}`
        Zurückkehren<heading> {Kinder}</heading>
      }

    Fall 'Text':
      return ({value}) =>  {value} >

    / * Gehen Sie hier alle Typen um ... *///

    Standard:
      console.log ('unverarbeiteter Knotentyp', Knoten)
      return ({Kinder}) =>  {Kinder} >
  }
}

const node = ({node}) => {
  const component = getComponent (Knoten)
  const {Kinder} = Knoten

  Kinder zurückgeben?
    <component>
      {Kinder.Map ((Kind, Index) => (
        <node key="{index}" node="{child}"></node>
      ))}
    </component>
  ): (
    <component></component>
  )
}

const markdownrenderer = ({ast}) =><node node="{ast}"></node>

Exportieren Sie Standard -React.Memo (Markdownrenderer)
Nach dem Login kopieren

Der größte Teil der Logik unseres Renderers befindet sich in Node . Es findet heraus, was auf type des AST -Knotens rendern zu werden (dies ist unsere getComponent -Methode, die mit jedem Knotentyp befasst) und dann es dann rendert. Wenn der Knoten Kinder hat, tritt er rekursiv in den Kinderknoten ein.

Reinigen Sie den Baum

Abhängig vom von uns verwendeten Bemerkung -Plugin können wir auf die folgenden Probleme stoßen, wenn wir versuchen, die Seite zu rendern:

Fehler: Ein Fehler beim Serialisieren .Content [0] .Content.Children [3] .Data.hchildren [0] .Data.hchildren [0] .Data.hchildren [0] .data.hchildren [0] .data.hname (von getstaticProps in '/'). Ursache: undefined kann nicht mit JSON serialisiert werden. Bitte verwenden Sie NULL oder lassen Sie diesen Wert weg.

Dies geschieht, weil unser AST Schlüssel mit undefinierten Werten enthält, was nicht sicher mit JSON serialisiert werden kann. Als nächstes gibt wir eine Lösung: Wir können den Wert insgesamt weglassen oder ihn durch Null ersetzen, wenn wir ihn mehr oder weniger benötigen.

Wir werden jedoch nicht jeden Pfad manuell reparieren, daher müssen wir das rekursiv über das ASTRAVES durchqueren und aufräumen. Ich habe festgestellt, dass dies bei der Verwendung von Bemerkung-Prismus (ein Plugin, das die Codeblocksyntax-Hervorhebung ermöglicht) geschieht. Das Plugin fügt dem Knoten ein [data] Objekt hinzu.

Was wir tun können, ist, diese Knoten zu beseitigen, bevor wir AST zurückgeben:

 const cleanNode = node => {
  if (node.value === undefiniert) Knoten löschen.Value
  if (node.tagname === undefiniert) Knoten löschen.tagname
  if (node.data) {
    löschen node.data.hname
    löschen node.data.hchildren
    löschen node.data.hproperties
  }

  if (node.children) node.children.foreach (CleanNode)

  Return Node
}

const parSemarkdown = content => {
  const Engine = Unified (). Verwendung (Remarkse).
  const ast = Engine.Parse (Inhalt)
  const processedast = motor.runsync (AST)

  CleanNode (Processedast)

  Processedast zurückgeben
}
Nach dem Login kopieren

Das Letzte, was wir tun können, ist, das position zu löschen, das auf jedem Knoten vorhanden ist, der die ursprüngliche Position in der Markdown -Zeichenfolge enthält. Es ist kein großes Objekt (es hat nur zwei Schlüssel), aber es sammelt sich schnell an, wenn der Baum größer wird.

 const cleanNode = node => {
  Node löschen.position
  // ... andere Reinigungslogik}
Nach dem Login kopieren

Zusammenfassen

Das war's! Wir haben es geschafft, die Markdown -Verarbeitung auf Erstellen/Server -Seitencode zu begrenzen, sodass wir keine unnötigen Markdown -Runtimes an den Browser senden, was die Kosten unnötig erhöht. Wir übergeben den Datenbaum an den Client, und wir können ihn über ihn iterieren und in jede gewünschte React -Komponente umwandeln.

Hoffe das hilft. :)

Das obige ist der detaillierte Inhalt vonVerantwortungsbewusstes Abschluss in Next.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage