React-ace: Keine Unterstützung für serverseitiges Rendern

Erstellt am 23. Juli 2015  ·  15Kommentare  ·  Quelle: securingsincity/react-ace

enhancement help wanted

Hilfreichster Kommentar

NextJS bietet hervorragende Unterstützung für serverseitig gerenderte React.JS-Anwendungen. Sie haben die dynamische Funktion, mit der Sie nur clientseitig importieren können.

Die Implementierung, die ich benutze.
Clientseitige Komponente

import brace from 'brace';
import 'brace/mode/javascript';
import 'brace/mode/c_cpp';
import 'brace/theme/twilight';
import 'brace/theme/xcode';
import AceEditor from 'react-ace';

const textEditor = (props) => (
  <div>
    <AceEditor
        mode={props.lan}
        theme={props.theme}
        onChange={props.onChange}
        name="UNIQUE_ID_OF_DIV"
        editorProps={{
            $blockScrolling: true
        }}
        fontSize={21}
        height='80vh'
        width='100%'
    />
  </div>
)

export default textEditor

`

So importieren Sie

import React, { Component } from 'react
import dynamic from 'next/dynamic'
const TextEditor = dynamic(import('../components/textEditor'), {
  ssr: false
})

 export default class Index extends Component {
    ...
    render() {
        return (
          <div>
           <TextEditor lan='javascript' theme="twilight"/>
          </div>
        )
    }

Alle 15 Kommentare

Würde mich über eine PR dafür freuen.

Da Ihre Abhängigkeiten nicht für das Rendern auf der Serverseite erstellt wurden, ist dies eine große Herausforderung. Im Moment würde ich Benutzern empfehlen, nur von einem Client gerenderte React-Komponenten zu verwenden, wenn sie Ihre Bibliothek verwenden möchten, was ich auch getan habe. Ich habe jedoch einige geringfügige Änderungen an meiner Gabel vorgenommen, die die Leistung verbessern sollten. Auch diese Gabel ist nicht für eine PR optimiert. Wenn du willst, kann ich es vorbereiten.

Ich bin gerade auf dasselbe Problem gestoßen. Eine mögliche Lösung besteht darin, die Klammer auf eine andere Weise getrennt von Ihrem Hauptbündel einzuziehen. Der Client benötigte ohnehin Javascript, sodass Sie zumindest den Rest der Seite rendern können.

Nach allem, was ich gesehen habe, verwendet Ace die DOM-API direkt, um den Editor zu erstellen. Wäre es nicht möglich, so etwas wie jsdom zu verwenden, um eine Browserumgebung auf dem Server zu simulieren?

NextJS bietet hervorragende Unterstützung für serverseitig gerenderte React.JS-Anwendungen. Sie haben die dynamische Funktion, mit der Sie nur clientseitig importieren können.

Die Implementierung, die ich benutze.
Clientseitige Komponente

import brace from 'brace';
import 'brace/mode/javascript';
import 'brace/mode/c_cpp';
import 'brace/theme/twilight';
import 'brace/theme/xcode';
import AceEditor from 'react-ace';

const textEditor = (props) => (
  <div>
    <AceEditor
        mode={props.lan}
        theme={props.theme}
        onChange={props.onChange}
        name="UNIQUE_ID_OF_DIV"
        editorProps={{
            $blockScrolling: true
        }}
        fontSize={21}
        height='80vh'
        width='100%'
    />
  </div>
)

export default textEditor

`

So importieren Sie

import React, { Component } from 'react
import dynamic from 'next/dynamic'
const TextEditor = dynamic(import('../components/textEditor'), {
  ssr: false
})

 export default class Index extends Component {
    ...
    render() {
        return (
          <div>
           <TextEditor lan='javascript' theme="twilight"/>
          </div>
        )
    }

Gibt es irgendwelche Nebenwirkungen bei der Verwendung von "next / dynamic"? oder es ist in Ordnung, das zu verwenden ..

Ich habe keine Probleme gesehen und ordnungsgemäß festgestellt, dass ich die Richtlinien des Next JS Framework zur Entwicklung befolge.

Sehr traurig(((

Sehr interessiert daran. Wir verwenden Ace und lieben es, haben aber noch keinen Weg gefunden, es mit Gatsby zu verwenden.

@ saulflores95 hat in meinem Fall die richtige Idee, dass der Modus und das Thema ebenfalls dynamisch importiert werden mussten. Aber als ich das tat, glaubte ich nicht, dass diese importiert wurden, bevor die Standard-React-Ace-Komponente war, so dass ich mein Thema nicht sah. Ich musste auf den Hauptimport warten, bevor ich das Thema und den Modus für Ass-Builds importierte. Dies ist Version 8.0.0.

const Editor = dynamic(
  async () => {
    const ace = await import('react-ace');
    import('ace-builds/src-noconflict/mode-javascript');
    import('ace-builds/src-noconflict/theme-textmate');
    return ace;
  },
  {
    // eslint-disable-next-line react/display-name
    loading: () => (
      <NoContent style={{ height: '520px' }}>
        <Spinner diameter={100} />
      </NoContent>
    ),
    ssr: false,
  },
);

841 wurde für 9.0.0 zusammengeführt und sollte die Unterstützung für serverseitiges Rendern lösen. danke an @gchallen

Genau wie zu Ihrer Information aktiviert meine PR keine vollständige SSR. Es verhindert lediglich, dass react-ace fehlschlägt, wenn es auf dem Server verwendet wird. Alles, was auf dem Server gerendert wird, ist leer div das Ace ausfüllt, sobald es auf den Client geladen wird.

Ich habe an einer umfassenderen Unterstützung für SSR gearbeitet, dh tatsächlich Markup auf dem Server generiert, ähnlich dem, was Sie nach dem Laden von Ace auf dem Client finden würden. Dies ist nicht trivial, da Ace einige ziemlich unangenehme und komplizierte Layoutberechnungen für die Last durchführt, die in jsdom verspottet werden müssen. Um also etwas zu erhalten, das so aussieht, wie es auf der Clientseite angezeigt wird, müssen wahrscheinlich einige dieser Layoutkonstanten übergeben werden.

Wie auch immer - dies ist definitiv ein Schritt in die richtige Richtung. Jetzt, da react-ace SSR nicht in die Luft sprengt, sollte es möglich sein, komplexere SSR-Ansätze mithilfe einer Wrapper-Komponente zu implementieren.

Vielen Dank an JohnGrisham , Ihre Lösung hat bei mir funktioniert. Ich musste die Importe jedoch durch Anforderungen ersetzen

const Ace = dynamic(
  async () => {
    const ace = await import('react-ace');
    require('ace-builds/src-noconflict/mode-mysql');
    require('ace-builds/src-noconflict/theme-xcode');
    return ace;
  },
{
  loading: () => (
    <>Loading...</>
  ),
  ssr: false,
})
...
<Ace mode="mysql"  theme="xcode"  />

@ saulflores95 hat in meinem Fall die richtige Idee, dass der Modus und das Thema ebenfalls dynamisch importiert werden mussten. Aber als ich das tat, glaubte ich nicht, dass diese importiert wurden, bevor die Standard-React-Ace-Komponente war, so dass ich mein Thema nicht sah. Ich musste auf den Hauptimport warten, bevor ich das Thema und den Modus für Ass-Builds importierte. Dies ist Version 8.0.0.

const Editor = dynamic(
  async () => {
    const ace = await import('react-ace');
    import('ace-builds/src-noconflict/mode-javascript');
    import('ace-builds/src-noconflict/theme-textmate');
    return ace;
  },
  {
    // eslint-disable-next-line react/display-name
    loading: () => (
      <NoContent style={{ height: '520px' }}>
        <Spinner diameter={100} />
      </NoContent>
    ),
    ssr: false,
  },
);

Teilweise funktioniert, Modus und Thema fehlen (es wurde auch versucht, require anstelle von import ).

Beginnend mit npm run dev (mit next dev ).

Die Google Chrome 87-Konsole gibt diesen Fehler aus:

Verwenden Sie ace.config.set ('basePath', 'path') nicht, um das dynamische Laden von Modi und Themen zu ermöglichen, oder verwenden Sie mit Webpack ace / webpack-resolver

Auch bemerkt 404 Statuscode für diese Anfragen:

Wenn ich stattdessen diesen anderen Ansatz verwende:

// code-editor.js
import AceEditor from 'react-ace'
import 'ace-builds/src-noconflict/mode-javascript'
import 'ace-builds/src-noconflict/theme-monokai'

const handleOnChange = () => {
  console.log('Changed!')
}

export default function CodeEditor() {
  return (
    <AceEditor
      mode="javascript"
      theme="monakai"
      onChange={handleOnChange}
      name="editor01"
    />
  )
}

// hello-world.js
import dynamic from 'next/dynamic'

const CodeEditor = dynamic(
  () => import('../../components/code-editor'),
  { ssr: false },
)

export default function HelloWorld() {
  return <CodeEditor />
}

Ich erhalte den gleichen Fehler, aber leicht unterschiedliche 404-Fehler:

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen