web-dev-qa-db-ja.com

反応と玉の組み合わせ

私は、Express + Reactを使用した同形JavaScriptアプリに取り組んでいます。静的コンテンツ用のサーバー側テンプレートにjadeを使用し始めましたが、2つを組み合わせるとすぐに扱いにくくなります。次のような結果になりました。

エクスプレスルートの場合:

_router.get("/", function(req, res) {
  var webpackStats = require('../../config/webpack-stats.json');
  var reactHtml = React.renderToString(HiwApp({}));
  var slideshowHtml = React.renderToString(slideshowApp({}));
  var config = {
    webpackStats: webpackStats,
    reactOutput: reactHtml,
    slideshowHtml: slideshowHtml
  };
  res.render("how_it_works/howitworks", config);
});
_

Jで:

_body
  .company-logo.center
  #react-main-mount
    != reactOutput
  include ./content_block_1.jade

  include ./content_block_2.jade

  #slideshow-main-mount
    != slideshowHtml
_

これは非常に脆弱です。jsx、jadeテンプレート、さらにjsxが必要な場合は、順序が正しいことを確認する必要があります。

私のアイデアは、jsxでallを実行することです。この種のことにはReact.renderToStaticMarkupがあることは知っていますが、動的ページと静的ページを混在させる問題は解決しません。

大きな質問:jsx(すべてのコンポーネントを含むlayout.jsxなど)でこれをすべて行うことにした場合、React.renderToString(App({});を呼び出すと、これは大きなパフォーマンスヒットになりますか?もしそうなら、静的ブロックと動的ブロックを簡単に組み合わせるより良い方法はありますか?

23
johnnyutah

これはトピックから少し外れているかもしれませんが、jadeテンプレートにこだわっています。

基本的に、必要に応じて、サイトのエリアに非反応+フラックスアーキテクチャを使用する柔軟性が必要でした。私たちのサイトは基本的にいくつかの小さなSPアプリ:サイト、ユーザーアカウント、チーム、管理者で構成されています。

なぜこれを行ったのですか?

  • サイトのすべてのセクションにアクセスしていないユーザーのファイルサイズとオーバーヘッドが小さくなります。

  • Reactの「オプトアウト」オプションと、必要に応じてフラックス。

  • よりシンプルなサーバー側認証。

6
AndrewMcLagan

成功した方法は、React.renderToStaticMarkup()を使用してサーバー上でJSX Shellテンプレート(Html.jsx)をレンダリングし、それを意味するすべてのサーバー側高速ルート要求への応答として送信することでした。ブラウザにHTMLを配信します。 Html.jsxは、htmlヘッド情報とGAスクリプトなど)を含む単なるシェルです。レイアウトを含めないでください。

// Html.jsx
render(){
  return (
    <html>
      <head>
        // etc.
      </head>
      <body>
        <div
          id="app"
          dangerouslySetInnerHTML={{__html: this.props.markup}}>
        </div>
      </body>
      <script dangerouslySetInnerHTML={{__html: this.props.state}</script>
      <script>
        // GA Scripts etc.
      </script>
    </html>
  )
}

アプリをハイドレートするときにサーバー上でdangerouslySetInnerHTMLを使用することもまったく問題ないことを忘れないでください。

動的なレイアウトは、同型コンポーネントを使用して、状態/小道具の構成に基づいてコンポーネントの階層を介して行う必要があります。 React Router)を使用している場合、ルーターは、提供するルートに基づいてビューハンドラーをレンダリングするため、自分で管理する必要はありません。

この手法を使用する理由は、同型で状態に応答する「アプリ」を、単に配信メカニズムであり、事実上ボイラープレートであるサーバー側テンプレートシェルからアーキテクチャ的に分離するためです。アプリ内のすべてのエクスプレスコンポーネント間でHtml.jsxテンプレートを保持し、他の同形のReactコンポーネントと混合させないようにします。

React/isomorphicアーキテクチャを解決するために見つけた最も役立つリソースの1つは、 https://github.com/yahoo/flux-examples/tree/master/react-router で、これを盗みましたからのテクニック。

将来的に当社の製品を使用するクライアントの開発者向けのテンプレートエンジンとしてハンドルバーを統合するというアイデアを検討しましたが、JSXで独自のDSLを記述し、HTMLのようなDSLをJSXに解析するためにいくつかの単純な解析ルーチンを使用する方が複雑ではないと判断しましたテンプレートの先頭にexport default(ES6モジュールの構文)などを追加してから、テンプレートをレンダリングコンポーネントにインポートします。

もちろん、この考え方に従って、ヒスイコンパイラを使用してテンプレートを吐き出し、別のヒスイファイルが不可欠だと思う場合は、その周囲にモジュール構文を追加することもできます。怒りで探ったことはありませんが、このプロジェクトにも気付きました: https://github.com/jadejs/react-jade

2
rickard