Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No support for server-side rendering #27

Open
mathew-kurian opened this issue Jul 23, 2015 · 22 comments
Open

No support for server-side rendering #27

mathew-kurian opened this issue Jul 23, 2015 · 22 comments

Comments

@mathew-kurian
Copy link

No description provided.

@securingsincity
Copy link
Owner

Would be happy to have a PR for this.

@mathew-kurian
Copy link
Author

Since your dependencies are not built for serverside rendering, it will be pretty challenging. For now, I would recommend users should just use a client-rendered React components if they want to use your lib which is what I did. But, I have made some minor modifications in my fork which should improve performance. Also, this fork is not optimized for a PR. If you want, I can prepare it.

@psayre23
Copy link

I just ran into this same issue. One possible solution is to pull in brace in another way separate from you main bundle. The client required javascript anyway, so at least you can render the rest of the page.

@gabipurcaru
Copy link

gabipurcaru commented Dec 17, 2015

from what I've seen, Ace uses the DOM api directly to create the editor. Wouldn't it be possible to use something like jsdom to simulate a browser environment on the server?

@saulflores95
Copy link

saulflores95 commented May 29, 2018

NextJS offers great support for React.JS server-side rendered applications. They have the dynamic function where it allows you to import client side only.

The implementation that I use.
Client Side Component

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

`

How to import

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

@prtvora99
Copy link

prtvora99 commented Jul 24, 2018

is there any side effect of using "next/dynamic" ? or it's fine to use that..

@saulflores95
Copy link

I have not seen any issues, duly noted that I am following the Next,JS framework guidelines on how to develop.

@Fi1osof
Copy link

Fi1osof commented Dec 9, 2018

Very sad(((

@x5engine
Copy link

@ezeev
Copy link

ezeev commented Apr 8, 2019

Very interested in this. We are using Ace and love it but haven't found a way to use it with Gatsby yet.

@JohnGrisham
Copy link

@saulflores95 has the right idea in my case the mode and theme had to be dynamically imported as well. But when I did that I don't think those were being imported before the default react ace component was so I didn't see my theme. I had to await the main import before I imported the ace builds theme and mode. This is 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,
  },
);

@securingsincity
Copy link
Owner

#841 was merged for 9.0.0 and should solve support for server-side rendering. thanks to @gchallen

@gchallen
Copy link
Contributor

gchallen commented May 23, 2020

Just as an FYI, my PR does not enable full SSR. It just prevents react-ace from failing when used on the server. All that will be rendered on the server is blank div which Ace will fill in once it is loaded on the client.

I've been working on more complete support for SSR, meaning actually generating markup on the server similar to what you would find on the client after Ace loads. This is non-trivial, since Ace does some fairly nasty and convoluted layout calculations on load that will need to be mocked out in jsdom. So getting something that looks like what you'd see client side will probably require passing some of those layout constants.

Anyway—this is definitely a step in the right direction. Now that react-ace doesn't blow up SSR, it should be possible to implement more complex SSR approaches using a wrapper component.

@pythonruss
Copy link

Thank you @JohnGrisham, your solution worked for me. I did have to replace the imports with requires however

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

@oncet
Copy link

oncet commented Jan 3, 2021

@saulflores95 has the right idea in my case the mode and theme had to be dynamically imported as well. But when I did that I don't think those were being imported before the default react ace component was so I didn't see my theme. I had to await the main import before I imported the ace builds theme and mode. This is 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,
  },
);

Working partially, mode and theme missing (also tried using require instead of import).

  • Windows 10 with WSL2
  • node@12.16.2 (and npm@6.14.4)
  • next@10.0.4
  • reace-ace@9.2.1
  • ace-builds@1.4.12

Starting with npm run dev (which runs next dev).

Google Chrome 87 console outputs this error:

Unable to infer path to ace from script src, use ace.config.set('basePath', 'path') to enable dynamic loading of modes and themes or with webpack use ace/webpack-resolver

Also noticed 404 status code for this requests:

If instead I use this other approach:

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

I get the same error but slightly different 404 errors:

@nopol10
Copy link

nopol10 commented Jul 24, 2021

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

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

export default function HelloWorld() {
return
}


I get the same error but slightly different 404 errors:

* http://localhost:3000/courses/theme-monakai.js
* http://localhost:3000/courses/worker-javascript.js (this one is new)

Was able to prevent that by setting the useWorker option to false

<CodeEditor
   ...
  setOptions={{
    useWorker: false,
  }}
/>

@cc7gs
Copy link

cc7gs commented Aug 26, 2021

hi~,i'm use next and react-ace create playground

@radikris
Copy link

Hi guys!

I deployed my app on vercel, and my dynamic component, (dynamic Ace Code Editor) not showing up, although on my localhost it is working great, but on the deployed site it is rendered empty. Anyone experienced this strange behaviour, and found a solution for it?
image

(I have followed @saulflores95 idea, with next/dynamic)

@danr-za
Copy link

danr-za commented Mar 28, 2022

same as @radikris, production build is not rendering it.

@saulflores95
Copy link

@radikris did you add the ssr:false key?

@nealchen-cn
Copy link

same as @radikris , any updates on the production build not rendering?

fisprak added a commit to swim-io/swim that referenced this issue Aug 17, 2022
It worked and then stopped. Doesn't build because [react-ace (used by
elastic UI) can't doesn't support server-side rendering][1]

[1]: securingsincity/react-ace#27 (comment)
@FilipPyrek
Copy link

FilipPyrek commented Aug 20, 2022

@saulflores95 has the right idea in my case the mode and theme had to be dynamically imported as well. But when I did that I don't think those were being imported before the default react ace component was so I didn't see my theme. I had to await the main import before I imported the ace builds theme and mode. This is 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,
  },
);

Worked for me 👍 but had to add await to all imports otherwise I was getting aforementioned errors like

Unable to infer path to ace from script src, use ace.config.set('basePath', 'path') to enable dynamic loading of modes and themes or with webpack use ace/webpack-resolver

GET http://localhost:3000/widget/mode-javascript.js net::ERR_ABORTED 404 (Not Found)

GET http://localhost:3000/widget/theme-textmate.js net::ERR_ABORTED 404 (Not Found)

async () => {
  const ace = await import('react-ace');
  await import('ace-builds/src-noconflict/mode-javascript');
  await import('ace-builds/src-noconflict/theme-textmate');
  return ace;
},

Also important step, as mentioned above, is to set useWorker: false

<Editor
   ...
  setOptions={{
    useWorker: false,
  }}
/>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests