フロントエンドとバックエンドの同形レンダリング: クライアントが React コンポーネントを含むページをリクエストすると、サーバーが最初に応答してページを出力し、クライアントとサーバーが初めて対話します。その後、コンポーネントをロードするプロセスで Ajax リクエストをサーバーに送信する必要がある場合、クライアントとサーバーは再度対話することになり、これには比較的長い時間がかかります。フロントエンドとバックエンドの同型レンダリングは、ページが最初に読み込まれるときに、すべての場所をレンダリングしてクライアントに一度に応答できます。
この記事では、主に React フロントエンドとバックエンドの同型レンダリングについて共有します。編集者はそれが非常に優れていると考えているので、参考として共有します。編集者をフォローして見てみましょう。皆さんのお役に立てれば幸いです。
実装方法: パッケージ管理ツールとモジュール依存関係メソッドが一貫していることを確認します
パッケージ管理ツール - npm管理、フロントエンドとバックエンドの両方が同じ互換性のあるパッケージを使用していることを確認します
モジュール依存関係メソッド - webpack 、フロントエンドとバックエンドの両方が commonjs を使用していることを確認します 依存関係メソッドにより、コードが相互に依存できることが保証されます
サーバー側でレンダリングする方法:
react ファミリーバケット: React、react-router、redux
react と ReactDOM
ここで、reactDOM によって提供されるサポートは、reactDOM です。 render 関数と、reactDOM.renderToString 関数は、ブラウザーで DOM 構造を生成し、後者は、サーバー上で対応する HTML 文字列テンプレートを生成します。 React は、生成された DOM 構造に data-react-checksum 属性を追加します。これは、2 つのテンプレートの一貫性を確保するための adler32 アルゴリズムのチェックサムです。
同時に、reactのライフサイクルもフロントエンドとバックエンドのレンダリングプロセスで異なります。フロントエンド レンダリング コンポーネントには完全なライフ サイクルがありますが、バックエンド レンダリングには、componentWillMount のライフ サイクルのみがあります。これは、データリクエストの送信など、フロントエンドとバックエンドで共同操作ロジックを実行したい場合は、クライアントのロジックを個別に処理したい場合は、それをコンポーネントウィルマウントのライフサイクルに配置できることを意味します。これを、componentDidMount などの他のライフサイクルに配置します。
react-router
react-router は、境界宣言型ルーティングを記述してさまざまなページのレンダリングを制御できる反応ルーティング ビュー制御ライブラリです。 React-router 自体はステート マシンであり、設定されたルーティング ルールと入力 URL パスに従って、対応するコンポーネントが検索され、match メソッドによってレンダリングされます。
このメカニズムはフロントエンドとバックエンドの両方に接続されています。たとえば、バックエンドでは、次の実装形式がレンダリングに使用されます。上記のロジックはコンポーネントに適切にカプセル化されており、宣言的なルーティングを記述するだけで、URL が変更されると自動的に実行されます。
redux
redux は、React 用のデータ フロー管理ライブラリです。サーバー側レンダリングのサポートは非常にシンプルです。つまり、単一のストアと状態を初期化できます。バックエンドはレンダリング時に単一のストアを構築し、構築された初期状態を生成された HTML 文字列テンプレートに json 形式でグローバル変数を通じて書き込みます。 初期状態を取得し、完了後にバックエンドとまったく同じストアを生成することで、フロントエンドはフロントエンドとバックエンドのレンダリング データの一貫性を確保し、によって生成された DOM 構造を保証します。フロントエンドとバックエンドは一貫しています。
開発効率が低いという問題: 同型アプリケーションには 1 つのプロジェクトと 1 セットのテクノロジー スタックしかありません。反応開発の経験がある限り、フロントエンドとバックエンドにすぐに投資できます。開発を終了する; 保守性が低い 問題: 同型アプリケーションは、ツールメソッド、定数、ページコンポーネント、redux のロジックのほとんどなどを含む大量のコードを共有できるため、最初の画面のパフォーマンスや SEO などが大幅に向上します。
処理プロセス:
1. 同型である必要があるページにプレースホルダー
app.use(async (ctx, next) => { match({ location: ctx.originalUrl, routes }, callback) // 渲染完成之后,调用 callback 回调 // 将 组件 renderToString 返回前端即可 })
<p id="root">@@@</p> ###
ファイル構造
window.renderApp = function(){ReactDOM.render(...)}
browser.js(在这里把渲染组件的过程赋值给window.renderApp) bundle.js(把browser.js内容bundle到这里) Component.js(组件在这里定义) express.js(服务端) index.html(同构直出的页面) package.json
<!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>
var React = require('react'); var ReactDOM = require('react-dom'); var Component = React.createFactory(require('./Component')); window.renderApp = function(msg){ ReactDOM.render(Component({msg: msg}), document.getElementById('root')); }
可以通过来触发组件的渲染。稍后,在服务端会把这段代码渲染出来。
express.js,服务端
以上,需要直出的页面有了占位符,定义了组件,并把渲染组件的过程赋值给了window对象,服务端现在要做的工作就是:生成组件的html和渲染组件的js,放到直出页面index.html的占位符位置。
var express = require('express'); var React = require('react'); var ReactDOMServer = require('react-dom/server'); var fs = require('fs'); var Component = React.createFactory(require('./Component')); //原先把文件读出来 var BUNDLE = fs.readFileSync('./bundle.js',{encoding:'utf8'}); var TEMPLATE = fs.readFileSync('./index.html',{encoding:'utf8'}); var app = express(); function home(req, res){ var msg = req.params.msg || 'Hello'; var comp = Component({msg: msg}); //@@@占位符的地方放组件 var page = TEMPLATE.replace('@@@', ReactDOMServer.renderToString(comp)); //###占位符的地方放js page = page.replace('###', '<script>renderApp("'+msg+'")</script>') res.send(page); } //路由 app.get('', home); app.get('/bundle.js', function(req, res){ res.send(BUNDLE); }) app.get('/:msg', home); app.listen(4000);
package.json中的配置
"scripts": { "start": "watchify ./browser.js -o ./bundle.js" },
启动方式
运行:npm start
运行:node express.js
浏览:localhost:4000
相关推荐:
以上がReact フロントエンドとバックエンドの同型レンダリングのサンプルの共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。