4

私たちは、webapp で wro を介して JavaScript リソース (およびその他) を提供しています。PROD 環境では、ブラウザーは (たとえば) app.js angular webapp のコンテンツを 1 年後に「期限切れ」ヘッダーで取得します。

後続のリクエストでは、ブラウザはサーバーへのリクエストなしでキャッシュから取得することを意味します。新しいバージョンの webapp をデプロイすると、ブラウザはローカル キャッシュから取得するため、新しいバージョンを取得しません。

目標は、ブラウザーが毎回リクエストを実行するようにヘッダーが正しく設定され、サーバーが変更されていない 304 を返すように、wro または spring を構成することです。そのため、新しい展開時にクライアントを自動的に「更新」します。誰かがすでにこれを達成しましたか?

Spring の Java 構成を使用します。

@Configuration
public class Wro4jConfiguration {   

@Value("${app.webapp.web.minimize}")
private String minimize;

@Value("${app.webapp.web.disableCache}")
private String disableCache;

@Autowired
private Environment env;

@Bean(name = "wroFilter")
public WroFilter wroFilter() {
    ConfigurableWroFilter filter = new ConfigurableWroFilter();
    filter.setWroManagerFactory(new Wro4jManagerFactory());
    filter.setWroConfigurationFactory(createProperties());
    return filter;
}

private PropertyWroConfigurationFactory createProperties() {
    Properties props = new Properties();
    props.setProperty("jmxEnabled", "false");
    props.setProperty("debug", String.valueOf(!env.acceptsProfiles(EnvConstants.PROD)));
    props.setProperty("gzipResources", "false");
    props.setProperty("ignoreMissingResources", "true");
    props.setProperty("minimizeEnabled", minimize);
    props.setProperty("resourceWatcherUpdatePeriod", "0");
    props.setProperty("modelUpdatePeriod", "0");
    props.setProperty("cacheGzippedContent", "false");
    // let's see if server-side cache is disabled (DEV only)
    if (Boolean.valueOf(disableCache)) {
        props.setProperty("resourceWatcherUpdatePeriod", "1");
        props.setProperty("modelUpdatePeriod", "5");
    }
    return new PropertyWroConfigurationFactory(props);
}
}
4

2 に答える 2

3

デフォルトでは、WroFilter は次のヘッダーを設定します: ETag (リソースの md5 チェックサム)、Cache-Control (public、max-age=315360000)、Expires (リソース作成から 1 年)。

これらのヘッダーの重要性については、多くの詳細があります。簡単な説明は次のとおりです。

サーバーがクライアント要求から ETag を読み取ると、サーバーはファイルを送信するか (HTTP 200)、クライアントにローカル コピーのみを使用するように指示するか (HTTP 304) を決定できます。ETag は基本的に、ファイルの内容が変更されると意味的に変更されるファイルのチェックサムにすぎません。ETag のみが送信される場合、クライアントは常に要求を行う必要があります。

Expires ヘッダーと Cache-Control ヘッダーは非常に似ており、クライアント (およびプロキシ/キャッシュ) がサーバーに要求を行う必要があるかどうかを判断するために使用されます。

したがって、実際にやりたいことは、両方のヘッダーを使用することです。コンテンツが変更される頻度に基づいて、Expires ヘッダーを適切な値に設定します。次に、ETag が送信されるように構成して、クライアントがサーバーに要求を送信したときに、ファイルを返送するかどうかをより簡単に判断できるようにします。

クライアントに常に最新のリソース バージョンを確認させたい場合は、expires & cache-control ヘッダーを送信しないでください。

または、より積極的なキャッシング手法があります。リソースのチェックサムをそのパスにエンコードします。その結果、リソースが変更されるたびに、そのリソースへのパスが変更されます。このアプローチにより、クライアントが常に最新バージョンを要求することが保証されます。このアプローチでは、リソースが変更されるたびにチェックサムが変更されるため、理論的にはリソースが期限切れになることはありません。

于 2015-06-16T14:51:41.630 に答える
2

Alex の情報とドキュメント リファレンスに基づいて、最終的に WroFilter.setResponseHeaders をオーバーライドして、適切な有効期限の値を設定しました。これはうまくいっています。Wro は既に ETag や Date などの設定を行っているので、有効期限の遅延と日付のみを上書きします。

@Configuration
public class Wro4jConfiguration {

    @Value("${app.webapp.web.browserCache.maxAgeInHours}")
    private String maxAgeInHours;

    @Bean(name = "wroFilter")
    public WroFilter wroFilter() {
        ConfigurableWroFilter filter = createFilter();

        filter.setWroManagerFactory(new Wro4jManagerFactory());
        filter.setWroConfigurationFactory(createProperties());

        return filter;
    }

    private ConfigurableWroFilter createFilter() {
        return new ConfigurableWroFilter() {

            private final int BROWSER_CACHE_HOURS = Integer.parseInt(maxAgeInHours);
            private final int BROWSER_CACHE_SECONDS = BROWSER_CACHE_HOURS * 60 * 60;

            @Override
            protected void setResponseHeaders(final HttpServletResponse response){
                super.setResponseHeaders(response);

                if (!getConfiguration().isDebug()) {
                    ZonedDateTime cacheExpires = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("GMT")).plusHours(BROWSER_CACHE_HOURS);
                    String cacheExpiresStr = cacheExpires.format(DateTimeFormatter.RFC_1123_DATE_TIME);

                    response.setHeader(HttpHeader.EXPIRES.toString(), cacheExpiresStr);
                    response.setHeader(HttpHeader.CACHE_CONTROL.toString(), "public,  max-age=" + BROWSER_CACHE_SECONDS);
                }
            }
        };
    }

    // Other config methods

}
于 2015-06-18T10:23:02.473 に答える