web-dev-qa-db-ja.com

展開後にクライアントを強制的にリロードするにはどうすればよいですか?

私はMEANスタックを使用しています(mongo、express、angular and node)。私は比較的頻繁に本番環境にデプロイしています...数日おきに。クライアント側のコードとAPIは時々あり、APIと以前のバージョンのクライアントコードとの下位互換性を保証する必要はありません。

そのようなシナリオで、運用環境にプッシュしたときにすべてのクライアントが確実にリロードするようにする最も効果的な方法は何ですか?たとえば、Evernoteには、最新バージョンのEvernote用にブラウザをリロードしてくださいというメッセージが表示されるポップアップが表示されます。似たようなことをしたいのですが... socket.ioまたはsock.jsのパスをたどる必要がありますか、それとも単純なものが不足していて、これを達成するためのより簡単な方法がありますか?

16
Andrew

更新:AppCacheは2015年夏に非推奨になったため、以下はもはや最善の解決策ではありません。新しい推奨事項は、代わりに Service Workers を使用することです。ただし、Service Workerは現在、IEおよびSafariで大ざっぱな(おそらくない)サポートを実験的に行っています。

あるいは、多くのビルドツールは、OPの問題に対処するために、キャッシュ無効化とファイルの「バージョン管理」技術をシームレスに組み込んでいます。 WebPack は、間違いなくこの分野の現在のリーダーです。


これは、HTML5の AppCache を使用するのに適したユースケースです。

これらのステップのいくつかをデプロイメントスクリプトに自動化することをお勧めしますが、ここでは、開始するのに役立つと思われるコードをいくつか示します。

まず、appcacheマニフェストファイルを作成します。これにより、appcacheマニフェストファイルの日付を明示的に変更するまで、クライアントのブラウザーにリソースをキャッシュすることもできます。

/ app.appcache:

CACHE MANIFEST

#v20150327.114142

CACHE:
/appcache.js
/an/image.jpg
/a/javascript/file.js
http://some.resource.com/a/css/file.css

NETWORK:
*
/

app.appcacheの行#v20150327.114142のコメントは、マニフェストが変更され、リソースを再ロードする必要があることをブラウザーに示す方法です。ファイルが以前のバージョンとは異なるブラウザに見える限り、実際には何でもかまいません。アプリケーションに新しいコードをデプロイするときに、この行を変更する必要があります。代わりにビルドIDを使用することもできます。

次に、appcacheを使用するページで、ヘッダータグを次のように変更します。

<html manifest="/app.appcache"></html>

最後に、Javascriptを追加して、appcacheに変更がないかどうかを確認し、変更がある場合は何かを行います。これが Angularモジュール です。この答えのために、ここにバニラの例があります:

appcache.js:

window.applicationCache.addEventListener('updateready', function(e) {
    if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
        // Browser downloaded a new app cache.
        // Swap it in and reload the page to get the latest hotness.
        window.applicationCache.swapCache();
        if (confirm('A new version of the application is available. Would you like to load it?')) {
            window.location.reload();
        }
    }
    else {
        // Manifest didn't changed. Don't do anything.
    }
}, false);

または、AppCacheが状況に応じて機能しない場合、より適切な解決策は、現在のビルドIDまたは最終展開日時を返す単純なAPIエンドポイントを作成することです。 Angularアプリケーションがこのエンドポイントにヒットし、結果を内部バージョンと比較し、異なる場合はそれ自体をリロードすることがあります。

または、ライブリロードスクリプト( )を検討することもできますが、開発には非常に役立ちますが、ライブ/インプレースリロードを使用することがどれほど優れているかはわかりません。生産中の資産の。

8
Marco Lüthy

たぶん、クライアントコードファイル名にハッシュを追加できます。例:app-abcd23.js
したがって、ブラウザはファイルをキャッシュから取得するのではなく、リロードします。または、ハッシュをurl.eg app.js?hash=abcd23に追加することもできますが、ブラウザによってはキャッシュされたバージョンを使用する場合があります。

私はRailsにはアセットがあります-それを処理するためのパイプラインがありますが、私は MEANスタック に精通していません。そのためにnpmにいくつかのパッケージがあるはずです目的。

また、ユーザーにクライアントコードが古くなっていることをユーザーに通知する場合は、socket.ioを使用する必要はないと思います。 html meta tagファイルとjsファイルの両方でバージョンを定義できます。不一致の場合は、ポップアップを表示して、ユーザーに更新するように指示します。

1
at15
  1. Js /ファイルがより短い定期的な時間内に期限切れになるように制限してみてください。つまり、1日です。
  2. しかし、ポップアウトしてユーザーにリロードするように指示するものが必要な場合は(ctrl+f5)彼らのブラウザで、ファイルの一部を変更した場合にそのニュースをポップアップするスクリプトを作成し、リロード/リロードを行ったばかりのip/sessionにマークを付けると、複数のポップアップに悩まされることがなくなります。
0
rezashamdani

私は最近同じ問題に直面していました。アプリのビルド番号をjs/cssファイルに追加することで、これを修正しました。私のすべてのスクリプトとスタイルタグは、共通のインクルードファイルのスクリプトに含まれているため、このようにjs/cssファイルパスの最後に「ビルド番号」を追加するのは簡単でした。

/foo/bar/main.js?123

この123は、同じヘッダーファイルで追跡している番号です。クライアントがアプリのすべてのjsファイルを強制的にダウンロードするようにしたいときはいつでも、それを増やします。これにより、新しいバージョンをダウンロードするタイミングを制御できますが、ブラウザは最初のリクエスト以降のすべてのリクエストにキャッシュを利用できます。それは、ビルド番号をインクリメントして別の更新をプッシュするまでです。

これは、必要な長さのキャッシュ有効期限ヘッダーを持つことができることも意味します。

0
Achshar