マルチページアプリでのReactの使用


122

私はReactをいじくり回してきましたが、これまでのところとても気に入っています。NodeJSでアプリを構築していますが、アプリケーション全体のインタラクティブコンポーネントの一部にReactを使用したいと考えています。シングルページアプリにしたくありません。

以下の質問に答えるウェブをまだ見つけていません。

Reactコンポーネントを複数ページのアプリに分割またはバンドルするにはどうすればよいですか?

アプリの一部のセクションでコンポーネントをロードできない場合でも、現在すべてのコンポーネントが1つのファイルに含まれています。

これまでのところ、ReactがレンダリングするコンテナーのIDを検索することにより、条件ステートメントを使用してコンポーネントをレンダリングしようとしています。Reactのベストプラクティスが何であるかは100%わかりません。こんな感じです。

if(document.getElementById('a-compenent-in-page-1')) {
    React.render(
        <AnimalBox url="/api/birds" />,
        document.getElementById('a-compenent-in-page-1')
    );
}

if(document.getElementById('a-compenent-in-page-2')) {
    React.render(
        <AnimalBox url="/api/cats" />,
        document.getElementById('a-compenent-in-page-2')
    );
}

if(document.getElementById('a-compenent-in-page-3')) {
    React.render(
        <AnimalSearchBox url="/api/search/:term" />,
        document.getElementById('a-compenent-in-page-3')
    );
}

まだドキュメントを読んでいて、マルチページアプリに必要なものがまだ見つかりません。

前もって感謝します。


requirejsプラグインを使用してみてください。
amit_183 2015

2
ReactJsが非常に大きなJSライブラリであり、ページごとに初期化する必要があることを気にしない場合(単一ページのアプリを構築していないと言ったように)、それが問題であることはわかりませんすべてのコンポーネントを1つのファイルに結合しました。クライアントにキャッシュされます。ページが読み込まれたら、ブロックrender内の正しいコンポーネントにしてくださいscript
WiredPrairie 2015

私は同じ問題を抱えています:異なるページに他の大きなライブラリをロードするアプリがあり、念のために4つの大きなライブラリではなく、訪問者のニーズに応じて1つのライブラリ+ reactをロードしたいのです。
AJFarkas

回答:


83

現在、私は同様のことをしています。

アプリケーションは完全なReactアプリではありません。私はautarkであるCommentBoxのような動的なものにReactを使用しています。そして、特別なパラメータで任意のポイントに含めることができます。

ただし、すべてのサブアプリが読み込まれ、1つのファイルに含まれているall.jsため、ブラウザでページ間でキャッシュできます。

アプリをSSRテンプレートに含める必要がある場合は、クラス「__react-root」と特別なID(レンダリングされるReactアプリの名前)を持つDIVを含める必要があります。

ロジックは本当にシンプルです:

import CommentBox from './apps/CommentBox';
import OtherApp from './apps/OtherApp';

const APPS = {
  CommentBox,
  OtherApp
};

function renderAppInElement(el) {
  var App = APPS[el.id];
  if (!App) return;

  // get props from elements data attribute, like the post_id
  const props = Object.assign({}, el.dataset);

  ReactDOM.render(<App {...props} />, el);
}

document
  .querySelectorAll('.__react-root')
  .forEach(renderAppInElement)

<div>Some Article</div>
<div id="CommentBox" data-post_id="10" class="__react-root"></div>

<script src="/all.js"></script>

編集する

webpackはコード分割とLazyLoadingを完全にサポートしているため、1つのバンドルにすべてのアプリをロードする必要はなく、それらを分割してオンデマンドでロードする必要がある例を含めることは理にかなっていると思いました。

import React from 'react';
import ReactDOM from 'react-dom';

const apps = {
  'One': () => import('./One'),
  'Two': () => import('./Two'),
}

const renderAppInElement = (el) => {
  if (apps[el.id])  {
    apps[el.id]().then((App) => {
      ReactDOM.render(<App {...el.dataset} />, el);
    });
  }
}

1
見栄えがいい、npm create-react-appを使用しているときに誰かがこれを実行していますか?私はこれがうまくいくとは思いません...私は今1つのアプリで実行していて、それがどのように機能するかを確認できますが、私のビルドは正しく機能する製品ビルドを作成しません。
スプローズ2017

@Sproseはcreate-react-appでも動作するはずですが、何か不足していますか?たぶん、githubで小さな例を共有できないかもしれませんが、そうしない理由はわかりません
webdeb

1
@Sproseは遅い答えを求めていますが、私はあなたが完全に異なる何かを試みていると思います、このアプローチが解決しようとするもの。IMO create react appは、作成するための簡単なツールを提供しますbundle.js。したがって、私の答えの目的は、同じものbundle.jsを使用して複数のSSRサイトで使用し、さまざまなReactアプリケーションを1つのページにロードすることです。申し訳ありませんが、私の答えがあなたのニーズに合わない場合は、新しい投稿を作成して、あなたがやろうとしていることを説明してください。私がお手伝いします。
webdeb

1
@SorcererApprentice craはwebpackを使用します。取り出してから基本をチェックアウトする必要がありますwebpack.js.org/guides/getting-started/#creating-a-bundle
webdeb

1
@SorcererApprentice基本的に誰かがこのページにwebpack設定を投稿しました:stackoverflow.com/a/41857199/5004923
webdeb

52

アプリケーションのいくつかのエントリポイントをwebpack.config.jsファイルで提供できます。

var config = {
  entry: {
    home: path.resolve(__dirname, './src/main'),
    page1: path.resolve(__dirname, './src/page1'),
    page2: path.resolve(__dirname, './src/page2'),
    vendors: ['react']
  },
 output: {
    path: path.join(__dirname, 'js'),
    filename: '[name].bundle.js',
    chunkFilename: '[id].chunk.js'
  },
}

次に、srcフォルダーに3つの異なるhtmlファイルとそれぞれのjsファイル(page1の例)を含めることができます。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Page 1</title>
</head>
<body>
  <div id="app"></div>
  <script src="./vendors.js"></script>
  <script src="./page1.bundle.js"></script>
</body>
</html>

JavaScriptファイル:

import React from 'react'
import ReactDom from 'react-dom'
import App from './components/App'
import ComponentA from './components/ReactComponentA'
ReactDom.render(<div>
                  <App title='page1' />
                  <ReactComponentA/>
                 </div>, document.getElementById('app'))

次に、単一のページごとに異なるReactコンポーネントをロードできます。


1
以下についてwebexページで読みます。webpack version < 4 it was common to add vendors as separate entrypoint to compile it as separate file (in combination with the CommonsChunkPlugin). This is discouraged in webpack 4. Instead the optimization.splitChunks option takes care of separating vendors and app modules and creating a separate file. Do not create a entry for vendors or other stuff which is not the starting point of execution.それで、このサンプルはwebpack 4+用に更新する必要がありますか?
Ramesh、2018年

32

私は最初からアプリケーションを構築していて、学習を続けていますが、探しているのはReact-Routerだと思います。React-Routerはコンポーネントを特定のURLにマッピングします。例えば:

render((
    <Router>
        <Route path="/" component={App}>
            <Route path="api/animals" component={Animals}>
               <Route path="birds" component={Birds}/>
               <Route path="cats" component={Cats}/>
            </Route>
        </Route>
        <Route path="api/search:term" component={AnimalSearchBox}>
    </Router>
), document.body)

検索の場合、「term」はAnimalSearchBoxのプロパティとしてアクセスできます。

componentDidMount() {
    // from the path `/api/search/:term`
    const term = this.props.params.term
}

やってみよう。 このチュートリアルは、このトピックやその他の関連トピックに対する私の理解の点で私を上に置いたものです。


元の答えは次のとおりです:

私は同じ答えを探してここに自分の道を見つけました。この投稿があなたに影響を与えているかどうかを確認しください。あなたのアプリケーションが私のようなものである場合、それはほとんど変化せず、本体でのみ変化する領域があります。アプリケーションの状態に基づいて異なるウィジェットをレンダリングする責任があるウィジェットを作成できます。フラックスアーキテクチャを使用すると、ボディウィジェットが切り替わる状態を変更するナビゲーションアクションをディスパッチして、ページのボディのみを効果的に更新できます。

それが今私が試みているアプローチです。


8
URLパスがバックエンドコード(この場合はnodejs)によって作成された場合はどうなりますか?ウィルRouterの仕事は、それが単一のページのアプリで同じ方法?
Jose Carrillo

1
@Scott特別なウィジェットを持つ管理ページ機能を公開したくない場合はどうすればよいですか?反応を使用すると、実際の認証なしでルックアンドフィールを再現できます。
Kairat Kempirbaev 2017年

11

CMSを使用していますか?彼らはあなたのアプリケーションを壊す可能性のあるURLを変更するのを好む傾向があります。

別の方法は、React Habitatのようなものを使用することです。

これを使用すると、コンポーネントを登録でき、コンポーネントは自動的にdomに公開されます。

コンポーネントを登録:

container.register('AnimalBox', AnimalBox);
container.register('AnimalSearchBox', AnimalSearchBox);

次に、これらはあなたのdomで次のように利用できます:

<div data-component="AnimalBox"></div>

<div data-component="AnimalSearchBox"></div>

上記は、reactコンポーネントに自動的に置き換えられます。

次に、プロパティ(または小道具)をコンポーネントに自動的に渡すこともできます。

<div data-component="AnimalBox" data-prop-size="small"></div>

これはsizeコンポーネントの小道具として公開されます。json、配列、int、floatなどの他の型を渡すための追加オプションがあります


2

この質問が出されて久しぶりのことですが、これが誰かの役に立てば幸いです。

@Cocomicoが言及したように、webpack.config.jsファイルでアプリケーションのいくつかのエントリポイントを提供できます。静的なページにReactコンポーネントを追加できるシンプルなWebpackセットアップ(複数のエントリポイントの考え方に基づく)を探している場合は、https//github.com/przemek-nowicki/multi-pageの使用を検討してください。 -app-with-react


-1

InertiaJSをご覧になることをお勧めします:https ://inertiajs.com/

Inertiaを使用すると、選択したサーバー側のWebフレームワークでいつも行っているようにアプリを構築できます。フレームワークの既存の機能を使用して、ルーティング、コントローラー、ミドルウェア、認証、承認、データフェッチなどを行います。

唯一異なるのは、ビューレイヤーです。サーバー側のレンダリング(ブレードやERBテンプレートなど)を使用する代わりに、ビューはJavaScriptページコンポーネントです。これにより、React、Vue、またはSvelteを使用してフロントエンド全体を構築できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.