React フロントエンドとバックエンドの同型レンダリングのサンプル コード

小云云
リリース: 2018-02-12 09:10:26
オリジナル
1412 人が閲覧しました

フロントエンドとバックエンドの同型レンダリング: クライアントが React コンポーネントを含むページをリクエストすると、サーバーが最初に応答してページを出力し、クライアントとサーバーが初めて対話します。その後、コンポーネントをロードするプロセスでサーバーに対して Ajax リクエストを行う必要がある場合、クライアントとサーバーは再度対話することになり、これには比較的長い時間がかかります。フロントエンドとバックエンドの同型レンダリングは、ページが最初に読み込まれるときにすべての場所をレンダリングし、クライアントに一度に応答できます。この記事では主に、React のフロントエンドとバックエンドの同形レンダリングについて紹介します。編集者はそれを共有し、参考にします。編集者をフォローして見てみましょう。皆さんのお役に立てれば幸いです。

実装方法: パッケージ管理ツールとモジュールの依存関係メソッドが一貫していることを確認します

パッケージ管理ツール - npm管理、フロントエンドとバックエンドの両方が同じ互換性のあるパッケージを使用していることを確認します

モジュールの依存関係メソッド -webpackフロントエンドとバックエンドの両方でそれを使用するようにします commonjs の依存関係メソッドにより、コードが相互に依存できるようになります

サーバー側でレンダリングする方法:
react ファミリーバケット: React、react-router、redux

react と ReactDOM

ここで、reactDOM によって提供されるサポートは、reactDOM .render 関数と ReactDOM.renderToString 関数です。そのうちの 1 つはブラウザーで DOM 構造を生成し、後者はサーバー上で対応する HTML 文字列テンプレートを生成します。 React は、生成された DOM 構造に data-react-checksum 属性を追加します。これは、2 つのテンプレートの一貫性を確保するための adler32 アルゴリズムのチェックサムです。

React フロントエンドとバックエンドの同型レンダリングのサンプル コード

同時に、reactのライフサイクルもフロントエンドとバックエンドのレンダリングプロセスで異なります。フロントエンド レンダリング コンポーネントには完全なライフ サイクルがありますが、バックエンド レンダリングには、componentWillMount のライフ サイクルのみがあります。これは、データリクエストの送信など、フロントエンドとバックエンドで共同操作ロジックを実行したい場合は、クライアントのロジックを個別に処理したい場合は、それをコンポーネントウィルマウントのライフサイクルに配置できることを意味します。これを、componentDidMount などの他のライフサイクルに配置します。

react-router

react-router は、境界宣言型ルーティングを記述してさまざまなページのレンダリングを制御できる反応ルーティング ビュー制御ライブラリです。 React-router 自体はステート マシンであり、設定されたルーティング ルールと入力 URL パスに従って、対応するコンポーネントが検索され、match メソッドによってレンダリングされます。

React フロントエンドとバックエンドの同型レンダリングのサンプル コード

このメカニズムはフロントエンドとバックエンドの両方に接続されています。たとえば、バックエンドでは、次の実装形式がレンダリングに使用されます。上記のロジックはコンポーネントに適切にカプセル化されており、宣言的なルーティングを記述するだけで、URL が変更されると自動的に処理されます。


redux

redux は、React 用のデータ フロー管理ライブラリです。サーバー側レンダリングのサポートは非​​常にシンプルです。つまり、単一のストアと状態を初期化できます。バックエンドはレンダリング時に単一のストアを構築し、構築された初期状態を生成された HTML 文字列テンプレートに json 形式でグローバル変数を通じて書き込みます。 初期状態を取得し、完了後にバックエンドとまったく同じストアを生成することで、フロントエンドはフロントエンドとバックエンドのレンダリング データの一貫性を確保し、によって生成された DOM 構造を保証します。フロントエンドとバックエンドは一貫しています。

最適化の結果:


開発効率が低いという問題: 同型アプリケーションには 1 つのプロジェクトと一連のテクノロジー スタックしかありません。反応開発の経験がある限り、フロントエンドとバックエンドにすぐに投資できます。開発を終了する; 保守性が低い 問題: 同型アプリケーションは、ツールメソッド、定数、ページコンポーネント、redux のロジックのほとんどなどを含む大量のコードを共有できるため、最初の画面のパフォーマンスや SEO などが大幅に向上します。
処理プロセス:


クライアントがリクエストを行い、サーバーがコンポーネントをレンダリングし、それをクライアントに返します

1. 同型である必要があるページにプレースホルダー


app.use(async (ctx, next) => { 
match({ 
location: ctx.originalUrl, 
routes 
}, callback) 
// 渲染完成之后,调用 callback 回调 
// 将 组件 renderToString 返回前端即可 
})
ログイン後にコピー

を置きます。クライアントが最初のリクエストを行うと、サーバーはコンポーネントの HTML コンテンツをレンダリングして @@@ の位置に配置し、次にサーバーは次のような JS コード スニペットをレンダリングして最終的にレンダリングします。コンポーネントを DOM に追加します。つまり、renderApp メソッドは実際にコンポーネントをレンダリングします。

2. renderApp メソッドを直接呼び出すには、renderApp メソッドが window


<p id="root">@@@</p>
###
ログイン後にコピー

3 の下のメソッドである必要があります。サーバーは、index.html を取り出し、プレースホルダーのコンテンツをレンダリングし、プレースホルダーを置き換えます。クライアントに応答します

ケース


ファイル構造

window.renderApp = function(){ReactDOM.render(...)}
ログイン後にコピー

index.html、プレースホルダーをページに直接配置します


browser.js(在这里把渲染组件的过程赋值给window.renderApp)

bundle.js(把browser.js内容bundle到这里)

Component.js(组件在这里定义)

express.js(服务端)

index.html(同构直出的页面)

package.json
ログイン後にコピー

Component.js、ここでコンポーネントを定義します


<!doctype html>
<html>
<head>
 <meta charset="UTF-8">
 <title>Untitled Document</title>
</head>
<body>

 <p id="root">@@@</p>
 <script src="bundle.js"></script>
 ###
</body>
</html>
ログイン後にコピー

ブラウザ。 jsでコンポーネントのレンダリング処理をウィンドウオブジェクトに割り当てます


var React = require(&#39;react&#39;);
var ReactDOM = require(&#39;react-dom&#39;);

var Component = React.createFactory(require(&#39;./Component&#39;));

window.renderApp = function(msg){
 ReactDOM.render(Component({msg: msg}), document.getElementById(&#39;root&#39;)); 
}
ログイン後にコピー

可以通过来触发组件的渲染。稍后,在服务端会把这段代码渲染出来。

express.js,服务端

以上,需要直出的页面有了占位符,定义了组件,并把渲染组件的过程赋值给了window对象,服务端现在要做的工作就是:生成组件的html和渲染组件的js,放到直出页面index.html的占位符位置。


var express = require(&#39;express&#39;);
var React = require(&#39;react&#39;);
var ReactDOMServer = require(&#39;react-dom/server&#39;);
var fs = require(&#39;fs&#39;);
var Component = React.createFactory(require(&#39;./Component&#39;));

//原先把文件读出来
var BUNDLE = fs.readFileSync(&#39;./bundle.js&#39;,{encoding:&#39;utf8&#39;});
var TEMPLATE = fs.readFileSync(&#39;./index.html&#39;,{encoding:&#39;utf8&#39;});

var app = express();

function home(req, res){
 var msg = req.params.msg || &#39;Hello&#39;;
 var comp = Component({msg: msg});

 //@@@占位符的地方放组件
 var page = TEMPLATE.replace(&#39;@@@&#39;, ReactDOMServer.renderToString(comp));

 //###占位符的地方放js
 page = page.replace(&#39;###&#39;, &#39;<script>renderApp("&#39;+msg+&#39;")</script>&#39;)
 res.send(page);
}

//路由
app.get(&#39;&#39;, home);
app.get(&#39;/bundle.js&#39;, function(req, res){
 res.send(BUNDLE);
})
app.get(&#39;/:msg&#39;, home);

app.listen(4000);
ログイン後にコピー

package.json中的配置


"scripts": {
"start": "watchify ./browser.js -o ./bundle.js"
},
ログイン後にコピー

启动方式
运行:npm start
运行:node express.js
浏览:localhost:4000

相关推荐:

实现react服务器渲染基础方法

React前后端同构防止重复渲染

React将组件渲染到指定DOM节点的方法详解

以上がReact フロントエンドとバックエンドの同型レンダリングのサンプル コードの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート