Spring MVCによるキャッシャブル静的資産

Spring MVCを使用したキャッシュ可能な静的アセット

1. 概要

この記事では、Spring MVCで提供する際の静的アセット(JavascriptやCSSファイルなど)のキャッシュに焦点を当てています。

また、「完全なキャッシュ」の概念についても触れます。基本的に、ファイルが更新されたときに、古いバージョンがキャッシュから誤って提供されないようにします。

2. 静的アセットのキャッシュ

静的アセットをキャッシュ可能にするには、対応するリソースハンドラを構成する必要があります。

これを行う方法の簡単な例を次に示します。max-age=31536000への応答にCache-Controlヘッダーを設定すると、ブラウザはキャッシュされたバージョンのファイルを1年間使用します。

@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/js/**")
                .addResourceLocations("/js/")
                .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
    }
}

キャッシュの有効期間が非常に長い理由は、ファイルが更新されるまでクライアントにキャッシュされたバージョンのファイルを使用させたいためです。RFC for the Cache-Control headerによると、365日が使用できる最大値です。

And so, when a client requests foo.js for the first timeの場合、彼はネットワーク経由でファイル全体(この場合は37バイト)をステータスコード200 OK.で受信します。応答には、キャッシュ動作を制御するための次のヘッダーがあります。

Cache-Control: max-age=31536000

これにより、次の応答の結果として、ブラウザーは有効期限が1年のファイルをキャッシュします。

cache

When the client requests the same file for the second timeの場合、ブラウザはサーバーに対して別の要求を行いません。 代わりに、キャッシュからファイルを直接提供し、ネットワークの往復を回避するため、ページの読み込みがはるかに高速になります。

cache-highlighted

Chromeブラウザのユーザーは、画面の更新ボタンを押すかF5キーを押してページを更新すると、Chromeはキャッシュを使用しないため、テスト中は注意する必要があります。 キャッシュ動作を観察するには、アドレスバーでEnterキーを押す必要があります。 そのhereに関する詳細情報。

3. 静的アセットのバージョン管理

静的アセットの提供にキャッシュを使用すると、ページの読み込みが非常に高速になりますが、重要な注意事項があります。 ファイルを更新すると、ファイルが最新かどうかをサーバーに確認せず、ブラウザキャッシュからファイルを提供するだけなので、クライアントはファイルの最新バージョンを取得しません。

ファイルが更新されたときにのみブラウザがサーバーからファイルを取得するようにするために必要なことは次のとおりです。

  • バージョンを含むURLでファイルを提供します。 たとえば、foo.js/js/foo-46944c7e3a9bd20cc30fdc085cae46f2.jsの下で提供する必要があります

  • 新しいURLでファイルへのリンクを更新します

  • ファイルが更新されるたびに、URLのバージョン部分を更新します。 たとえば、foo.jsが更新されると、/js/foo-a3d8d7780349a12d739799e9aa7d2623.js.で提供されるようになります。

ページには別のURLへのリンクがあるため、クライアントは更新時にサーバーにファイルを要求します。そのため、ブラウザはそのキャッシュを使用しません。 ファイルが更新されない場合、そのバージョン(したがってURL)は変更されず、クライアントはそのファイルのキャッシュを使用し続けます。

通常、これらのすべてを手動で行う必要がありますが、Springはこれらをすべてサポートしており、各ファイルのハッシュの計算やURLへの追加をサポートしています。 これらすべてを実行するようにSpringアプリケーションを構成する方法を見てみましょう。

3.1. バージョン付きのURLで提供

URLに更新されたバージョン文字列を含むパスの下のファイルを提供するには、パスにVersionResourceResolverを追加する必要があります。

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/js/**")
            .addResourceLocations("/js/")
            .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
            .resourceChain(false)
            .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
}

ここでは、コンテンツバージョン戦略を使用します。 /jsフォルダー内の各ファイルは、そのコンテンツから計算されたバージョンを持つURLで提供されます。 これはフィンガープリンティングと呼ばれます。 たとえば、foo.jsはURL/js/foo-46944c7e3a9bd20cc30fdc085cae46f2.js.で提供されるようになります

この構成では、クライアントがhttp://localhost:8080/js/_46944c7e3a9bd20cc30fdc085cae46f2.js:_を要求すると

curl -i http://localhost:8080/js/foo-46944c7e3a9bd20cc30fdc085cae46f2.js

サーバーはCache-Controlヘッダーで応答して、クライアントブラウザーに1年間ファイルをキャッシュするように指示します。

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Last-Modified: Tue, 09 Aug 2016 06:43:26 GMT
Cache-Control: max-age=31536000

URLにバージョンを挿入する前に、単純なscriptタグを使用してfoo.jsをインポートできます。