React-ace: サーバー側のレンダリングはサポートされていません

作成日 2015年07月23日  ·  15コメント  ·  ソース: securingsincity/react-ace

enhancement help wanted

最も参考になるコメント

NextJSは、React.JSサーバーサイドレンダリングアプリケーションを強力にサポートします。 クライアント側のみをインポートできる動的機能があります。

私が使用する実装。
クライアント側コンポーネント

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

`

インポートする方法

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

全てのコメント15件

このためのPRがあれば幸いです。

依存関係はサーバーサイドレンダリング用に構築されていないため、かなり難しいでしょう。 今のところ、私が行ったことであるlibを使用したい場合は、クライアントがレンダリングしたReactコンポーネントを使用することをお勧めします。 しかし、パフォーマンスを向上させるために、フォークにいくつかの小さな変更を加えました。 また、このフォークはPR用に最適化されていません。 よろしければご用意させていただきます。

私はちょうどこれと同じ問題に遭遇しました。 考えられる解決策の1つは、メインバンドルとは別の方法でブレースを引き込むことです。 とにかくクライアントはJavaScriptを必要としていたので、少なくともページの残りの部分をレンダリングすることができます。

私が見たところ、AceはDOMAPIを直接使用してエディターを作成しています。 jsdomのようなものを使用して、サーバー上のブラウザー環境をシミュレートすることは可能ではないでしょうか。

NextJSは、React.JSサーバーサイドレンダリングアプリケーションを強力にサポートします。 クライアント側のみをインポートできる動的機能があります。

私が使用する実装。
クライアント側コンポーネント

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

`

インポートする方法

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

「next / dynamic」を使用することによる副作用はありますか? またはそれを使用しても問題ありません。

私は問題を見ていませんが、開発方法についてNext、JSフレームワークのガイドラインに従っていることを正しく指摘しました。

とても悲しい(((

これに非常に興味があります。 私たちはエースを使用していて気に入っていますが、ギャツビーで使用する方法はまだ見つかりません。

@ saulflores95は私の場合、モードとテーマも動的にインポートする必要があるという正しい考えを持っています。 しかし、それを行ったとき、デフォルトの反応エースコンポーネントがインポートされる前にそれらがインポートされていたとは思わないので、テーマが表示されませんでした。 エースビルドのテーマとモードをインポートする前に、メインのインポートを待たなければなりませんでした。 これはバージョン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は9.0.0にマージされ、サーバー側レンダリングのサポートを解決するはずです。 @gchallenに感謝します

参考までに、私のPRでは完全なSSRが有効になっていません。 サーバーで使用したときにreact-aceが失敗するのを防ぐだけです。 サーバーにレンダリングされるものはすべて空白のdivあり、クライアントにロードされるとAceが入力します。

私はSSRのより完全なサポートに取り組んできました。つまり、Aceのロード後にクライアントで見られるものと同様に、サーバー上で実際にマークアップを生成します。 Aceは、jsdomでモックアウトする必要がある負荷に対して、かなり厄介で複雑なレイアウト計算を行うため、これは重要です。 したがって、クライアント側に表示されるもののように見えるものを取得するには、おそらくこれらのレイアウト定数のいくつかを渡す必要があります。

とにかく、これは間違いなく正しい方向への一歩です。 react-aceがSSRを爆破しないようになったので、ラッパーコンポーネントを使用してより複雑なSSRアプローチを実装できるはずです。

@JohnGrishamに感謝します、あなたの解決策は私のために働きました。 ただし、インポートをrequireに置き換える必要がありました

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は私の場合、モードとテーマも動的にインポートする必要があるという正しい考えを持っています。 しかし、それを行ったとき、デフォルトの反応エースコンポーネントがインポートされる前にそれらがインポートされていたとは思わないので、テーマが表示されませんでした。 エースビルドのテーマとモードをインポートする前に、メインのインポートを待たなければなりませんでした。 これはバージョン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,
  },
);

部分的に協力し、モードと不足しているテーマは、(また、使用してみましたrequireの代わりにimport )。

npm run devnext dev )から始まります。

Google Chrome87コンソールは次のエラーを出力します。

スクリプトsrcからaceへのパスを推測できない場合は、ace.config.set( 'basePath'、 'path')を使用してモードとテーマの動的ロードを有効にするか、webpackでace / webpack-resolverを使用してください

このリクエストの404ステータスコードにも気づきました:

代わりに、この他のアプローチを使用する場合:

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

同じエラーが発生しますが、404エラーがわずかに異なります。

このページは役に立ちましたか?
0 / 5 - 0 評価