2015-12-21 8 views
18

完全なサーバー側のレンダリング(Web 2.0以外)では、サーバー側のコードをデプロイすると、ページの再読み込み時にクライアント側のページが直接更新されます。対照的に、Reactベースの単一ページアプリケーションでは、Reactコンポーネントが更新された後でも、古いバージョンのコンポーネントを使用しているクライアントがまだ残っています(まれにブラウザリロード時に新しいバージョンが取得されます)完全にSPAである場合、一部のクライアントは数時間後にページを更新するだけである可能性があります。シングルページアプリケーション(SPA)ページを強制的に更新するにはどうすればよいですか?

古いコンポーネントのバージョンがクライアントによって使用されていないことを確認するためにどのような手法を採用する必要がありますか?

更新:APIは変更されず、Reactコンポーネントのみが新しいバージョンに更新されます。

+1

良い質問です。私はいくつかの方法について考えることができます。 SSE(サーバー送信イベント)またはWebSocketを使用して新しい更新があることをクライアントに通知するので、準備ができたら更新することができます(自動更新によって失望する可能性があることを確認します)。 –

+3

純粋なクライアントが永遠に動くことができるので、コード更新のためだけにソケットを開いたままにしておくことは、おそらく残念です。危険にさらされるサーバー通信です。各サーバーの要求にバージョン・スタンプを送信し、サーバーが何か古いものを取得した場合は、ページをリロードするエラー・メッセージ(ユーザーに最初に質問した後)に応答します。あなたが一度に古いものと新しいものをサポートできれば、古いものが乾くまでそれは理想的です... – dandavis

答えて

2

はいサーバー側のレンダリングでは、ページの一部を更新する必要がある場合は、ページ全体を再読み込みする必要があります。しかし、SPAでは、ajaxを使ってあなたのものを更新するので、ページをリロードする必要はありません。あなたの問題を見る私はいくつかの前提を持っています:

あなたのコンポーネントの1つが更新されましたが、同じAPIからデータを取得する他のコンポーネントは更新されませんでした。ここに来るフラックスのアーキテクチャ。ストア内のデータを持ち、コンポーネントがストアの変更をリッスンすると、ストア内のデータがすべてのコンポーネントを変更するたびに、そのリスニングを更新して更新されます(キャッシングのシーンはありません)。

または

コンポーネントを自動的に更新するように制御する必要があります。その

  1. のためにあなたは
  2. WebSocketをは、サーバーからのコンポーネントのデータを更新することができ、特定の間隔でデータ用のサーバーを要求することができます。
-2

APIのバージョン。

すべてのAPIエンドポイントのURLは次のようになります。あなたはあなたの全体のウェブアプリを更新すると、上記の例では

https://example.com/api/1.0.0/REST/customer/52 

を、あなたのフロントエンドは、その威力を持つIDである52の顧客を取得することができますこのようなものに変更:バージョン1.0.0 URLで

https://example.com/api/1.1.0/REST/customer/52 

とWebサービスは、今では完全に自分自身をリロードする必要があることを意味するようにフロントエンドに理解されているエラーコードとエラーのペイロードを返します。

+0

申し訳ありませんが、質問は更新されました:APIは変更されず、React Componentのみが新しいバージョンにアップデートされます。 –

+0

しかし、実装を変更しない場合でも、URLを変更するだけではどうですか?これは問題を解決するだろう。 –

+0

問題は解決されません。古いReactコンポーネントは引き続き古いAPIエンドポイントを参照します。 –

19

アプリケーションが読み込まれたときにReactコンポーネントにサーバーにajax要求を行い、"インターフェイスバージョン"をフェッチすることができます。サーバーAPIでは、クライアントバージョンの増分値を維持できます。 Reactコンポーネントはこの値をクライアントに保存できます(Cookie /ローカルストレージ/ etc)。変更を検出すると、window.location.reload(true);force the browser to discard client cache)を呼び出してSPAをリロードできます。または、さらに良いことに、エンドユーザーに新しいバージョンがロードされることを通知し、作業を保存してリロードするかどうか尋ねます。実行したいことに依存します。

+1

すばらしい答え!私がやっていることに非常に似ています! –

2

APIの任意のエンドポイントからのすべての応答でアプリのバージョンを送信できます。アプリがAPIリクエストをしたときに、新しいバージョンがあることを簡単にチェックでき、ハードリロードが必要になります。APIレスポンスのバージョンがlocalStorageに保存されているバージョンよりも新しい場合は、window.updateRequired = trueと設定します。そして、あなたはラップ反応し、以下のコンポーネントを持つことができreact-routerLink

import React from 'react'; 
import { Link, browserHistory } from 'react-router'; 

const CustomLink = ({ to, onClick, ...otherProps }) => (
    <Link 
    to={to} 
    onClick={e => { 
     e.preventDefault(); 
     if (window.updateRequired) return (window.location = to); 
     return browserHistory.push(to); 
    }} 
    {...otherProps} 
    /> 
); 

export default CustomLink; 

そして、それを使用する代わりに反応し、ルータのLinkをアプリを通じて。したがって、アップデートがあり、ユーザーが別のページに移動すると、ハードリロードが発生し、ユーザーはアプリの最新バージョンを取得します。

また、ポップアップを表示することもできます。「アップデートがあります。[ここ]をクリックすると有効になります。ページが1つしかない場合、またはユーザーが非常にめったにナビゲートしない場合。または、尋ねることなくアプリをリロードするだけです。それはあなたとアプリに依存します。

1

スティーブ・テイラーの回答に似ていますが、APIエンドポイントのバージョニングではなく、クライアント・アプリケーションを次のようにバージョンアップします。サーバはそのようなヘッダを傍受し、それに応じて応答することができるであろう

X-Client-Version: 1.0.0

:各HTTPリクエストで

のような、カスタムヘッダを送ります。

サーバが適切にクライアントによって処理されるHTTPステータスコードで応答し、現在のバージョンが1.1.0であれば、クライアントのバージョンは、例えば、古くなっていることを認識している場合には、例えば:

418 - I'm a Teapot

window.location.reload(true)

根底にあるプレム:

クライアントは、その後でアプリをリフレッシュすることにより、このような応答に反応するようにプログラムすることができますiseは、サーバーが最新のクライアントバージョンを認識しているということです。

EDIT:

同様の答えがhereを与えています。

関連する問題