Ticket #1015 (new Enhancement)

Opened 8 years ago

Last modified 8 years ago

Enable setting maximum age or expiry date for web bundle static resources

Reported by: Malte Owned by:
Priority: Major Milestone: Release 4.8.4
Component: DeepaMehta Standard Distribution Version: 4.8.3
Keywords: Cc: jri, dgf, JuergeN
Complexity: 3 Area: Performance
Module: deepamehta-webservice

Description

Concerning the resource my plugin bundles in:
src/main/resources/web/...

Setting an "expiration date" for about 10mins into the future should be a fine default for all those resources and already lead to quite an improvement. I haven't looked into the sources yet.

It would be great if i could return my a "maximum age" or "expiry" value set in the HTTP Header of the response. If we can manage this, javascript and css resources on subsequent requests to a website could be loaded from the users disk and not over the network. This issue more significant for web app experience on mobile phones without a landline connection.

This issue currently mainly affects user experience of the new kiezatlas site but basically all web apps delivered by our own jetty service could immediately benefit.

For example:
http://mitte.kiezatlas.de/angebote/376954
This page tested with Googles Page Speed Test.

GZIP Compression would be also great but in my case i think we could just turn this feature "on" via tewaking the apache proxy setup/configuration.

What i can and already have done (locally) is concatenating all my js files into one and minify it. So, across all pages of the angebote ui there would be always just one script file necessary to get loaded and ideally, it would not be needed to load on every page request.

If we can fine tune this a bit, i think that would be great.
Thanks for your time.

Change History

comment:1 Changed 8 years ago by jri

Note that for static resources the browser cache is leveraged already by the means of the Last-Modified response header and conditional requests (If-Modified-Since request header). That is requests are possibly answered with 304 Not Modified. So, your one big js file will not be transferred with every request. Please check this.

Yes, by setting a max-age value in the Cache-Control response header we could avoid sending the request in the first place. But I think setting max-age=600 for just all static resources is not a good idea as this would destroy e.g. the save-reload turnaround while development (which relies on max-age=0). So we need further conceptualization here.

What about this:

  • Set max-age=600 for the jar-bundled static resources as served via /<bundle-symbolic-name>/...
  • Set max-age=0 for static resources served via filerepo, that is /filerepo/... (the Last-Modified header is set anyways).

However this still might hinder development as not all static resources can be served via filerepo in some cases.

We might want introduce further configuration options, e.g. by explicitly differentiating a "development" mode and a "production" mode (as Rails does).

Last edited 8 years ago by jri (previous) (diff)

comment:2 Changed 8 years ago by Malte

Thanks and yes, having a production switch would be great and probably the best, transparent solution. However i would be fine with none. From my perspective (and i have not yet used the filerepo for web app dev) we could turn the max-age setting on by default for all jar-bundled resources. Because:

In Chromiums inspection tool (called DevTools?) there is also a simple switch called:
"Disable cache (when DevTools? is open" to find in the "Network" tab and I usually have this box ticked.

The same setting is also available for developrs using Firefox:
"Default Firefox Developer Tool" (Inspection Tool) via the "Settings" icon on the right, and then "Disable HTTP Cache" (effectively simulating first-load performance in all tabs that have the Toolbox open).
https://developer.mozilla.org/en-US/docs/Tools/Settings

In Firefox there is also CTRL + F5 / CTRL + SHIFT + RELOAD, which lets the user overwrite the browser cache per request (and which somehow sneaked into my habits during web development already): https://support.mozilla.org/de/kb/Tastaturkuerzel

But yes, having some kind of "production" switch in our build system would be more transparent and therefore probably the best solution. Thanks again for your time!

comment:3 Changed 8 years ago by Malte

BTW: See also #501, that should be considered a duplicate.

We might want introduce further configuration options, e.g. by explicitly differentiating a "development" mode and a "production" mode (as Rails does).

Yes, that would be fine forme. By default the development mode should be active (so no max-age header would be set). And i like the proposed defaults (600s).

Thanks for improving dm 4 webapps!

comment:4 Changed 8 years ago by JuergeN

Apache config for Cashing an Compression:

## compression mod_deflate ##

    SetOutputFilter DEFLATE                                      # <= enables compression
    SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip    # <= disables compression for pre-compressed content

    ## MimeTypes ##

    AddType application/json .geojson                            # <= in case you are using it.

    ## browser cache ##

    <ifmodule mod_expires.c>
	ExpiresActive On                                         # <= set Browser Caching Headers
	ExpiresDefault "access plus 30 days"                     #    e.g. to 30 days after last access. 
    </ifmodule>    

comment:5 Changed 8 years ago by Malte

Wow, cool.

So, just to better understand this configuration, the "access plus 30 days" concerns ALL files served by DeepaMehta 4 jetty, also JavaScripts? (bundled as a bundles static resource) as well as files in the filerepo?

Thanks for sharing this solution for users of Apache!

comment:6 Changed 8 years ago by JuergeN

In addition, you can always add more specific time ranges for each content type:

ExpiresByType text/html "access plus 1 month 15 days 2 hours"
ExpiresByType image/gif "modification plus 5 hours 3 minutes"

It would be great to have a good default setting for a default DeepaMehta installation. Could you provide a reasonable suggestion, please?

comment:7 Changed 8 years ago by Malte

Hi JuergeN!

It would be great to have a good default setting for a default DeepaMehta installation. Could you provide a reasonable suggestion, please?

Ok, sure. Regarding your example apache conf (see comments above) I would suggest to add an "exclude" rule to deactivate compression and browser caching for all files served to clients via the "/filerepo/" resource. If that is possible.

Regarding the "compression" part, here my suggestion would be to switch away from an "exclude" to an "include" rule and thus let compression be active for certain web app assets only (in particular css, js, json, svg).

The same for the browser cache: Browser should cache (by default) only files ending on JS, JSON, SVG, and CSS for "10 minutes" (see also above) as that should already improve the web apps performance for many user actions (from the 2nd on).

Considering that i also rely on using apache in production the following distinction between production and development mode would work for me: Behind an Apache=production, DeepaMehta 4 Jetty Standalone=Development. Nonetheless, having a configuration switch/option in DM4 to control the discussed settings would be nice to have.

Note: See TracTickets for help on using tickets.