React-ace: No hay soporte para la representación del lado del servidor

Creado en 23 jul. 2015  ·  15Comentarios  ·  Fuente: securingsincity/react-ace

enhancement help wanted

Comentario más útil

NextJS ofrece un gran soporte para las aplicaciones renderizadas del lado del servidor React.JS. Tienen la función dinámica en la que le permite importar solo el lado del cliente.

La implementación que utilizo.
Componente del lado del cliente

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

'

Como importar

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>
        )
    }

Todos 15 comentarios

Estaría feliz de tener un PR para esto.

Dado que sus dependencias no están creadas para la representación del lado del servidor, será bastante desafiante. Por ahora, recomendaría a los usuarios que solo usen componentes de React renderizados por el cliente si quieren usar su lib, que es lo que hice. Pero he realizado algunas modificaciones menores en mi bifurcación que deberían mejorar el rendimiento. Además, esta bifurcación no está optimizada para un PR. Si quieres, puedo prepararlo.

Me acabo de encontrar con el mismo problema. Una posible solución es tirar de la abrazadera de otra manera separada de su paquete principal. El cliente requería javascript de todos modos, así que al menos puedes renderizar el resto de la página.

por lo que he visto, Ace usa la API DOM directamente para crear el editor. ¿No sería posible usar algo como jsdom para simular un entorno de navegador en el servidor?

NextJS ofrece un gran soporte para las aplicaciones renderizadas del lado del servidor React.JS. Tienen la función dinámica en la que le permite importar solo el lado del cliente.

La implementación que utilizo.
Componente del lado del cliente

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

'

Como importar

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>
        )
    }

¿Existe algún efecto secundario de usar "siguiente / dinámico"? o está bien usar eso ...

No he visto ningún problema, noté debidamente que estoy siguiendo las pautas del marco Next, JS sobre cómo desarrollar.

Muy triste(((

Muy interesado en esto. Estamos usando Ace y nos encanta, pero aún no hemos encontrado la manera de usarlo con Gatsby.

@ saulflores95 tiene la idea correcta en mi caso, el modo y el tema también tenían que ser importados dinámicamente. Pero cuando hice eso, no creo que se estuvieran importando antes de que el componente react ace predeterminado fuera, así que no vi mi tema. Tuve que esperar la importación principal antes de importar el tema y el modo de Ace builds. Esta es la versión 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 se fusionó para 9.0.0 y debería resolver el soporte para la representación del lado del servidor. gracias a @gchallen

Al igual que un FYI, mi PR no habilita SSR completo. Simplemente evita que react-ace falle cuando se usa en el servidor. Todo lo que se procesará en el servidor estará en blanco div que Ace completará una vez que se cargue en el cliente.

He estado trabajando en un soporte más completo para SSR, lo que significa que en realidad genero un marcado en el servidor similar al que encontraría en el cliente después de que Ace cargue. Esto no es trivial, ya que Ace hace algunos cálculos de diseño bastante desagradables y complicados en la carga que necesitarán ser burlados en jsdom. Entonces, obtener algo que se parezca a lo que vería en el lado del cliente probablemente requerirá pasar algunas de esas constantes de diseño.

De todos modos, este es definitivamente un paso en la dirección correcta. Ahora que react-ace no explota SSR, debería ser posible implementar enfoques de SSR más complejos utilizando un componente contenedor.

Gracias @JohnGrisham , su solución funcionó para mí. Sin embargo, tuve que reemplazar las importaciones con requisitos

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 tiene la idea correcta en mi caso, el modo y el tema también tenían que ser importados dinámicamente. Pero cuando hice eso, no creo que se estuvieran importando antes de que el componente react ace predeterminado fuera, así que no vi mi tema. Tuve que esperar la importación principal antes de importar el tema y el modo de Ace builds. Esta es la versión 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,
  },
);

Trabajando parcialmente, falta el modo y el tema (también intenté usar require lugar de import ).

Comenzando con npm run dev (que ejecuta next dev ).

La consola Google Chrome 87 muestra este error:

No se puede inferir la ruta a ace desde el script src, use ace.config.set ('basePath', 'path') para habilitar la carga dinámica de modos y temas o con webpack use ace / webpack-resolver

También noté el código de estado 404 para estas solicitudes:

Si en cambio uso este otro enfoque:

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

Recibo el mismo error pero errores 404 ligeramente diferentes:

¿Fue útil esta página
0 / 5 - 0 calificaciones