Closed Bug 1197796 Opened 9 years ago Closed 9 years ago

Make WhiteNoise serve gzipped static assets on Heroku

Categories

(Tree Management :: Treeherder: Infrastructure, defect, P3)

defect

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: emorley, Assigned: emorley)

References

Details

Attachments

(1 file)

Bug 1176482 added a custom WhiteNoise class that made sure the correct max-age was set for minified js/css assets. However we also now need to make sure these assets are served gzipped. Since we're not able to use the WhiteNoise Django features directly (since we're not using Django templates, so have no way for the paths to be mapped), we'll need to manually gzip the UI files on Heroku build, by following the steps here: http://whitenoise.evans.io/en/latest/base.html#gzip-support For the Django static assets themselves (ie admin CSS, embed view assets etc), we'll still use the WhiteNoise Django storage backend: http://whitenoise.evans.io/en/latest/django.html#add-gzip-and-caching-support Note bug 1176489 is filed for making sure the Django dynamic responses are gzipped; this bug is just about the static assets.
Summary: gzip static assets during the Heroku build, for use with WhiteNoise → Make WhiteNoise serve gzipped static assets on Heroku
Depends on: 1198265
We'll need to wait for bug 1124382 to land first, since otherwise we end up with progressively more duplicate files in the static directory after each collectstatic run (see bug 1198265 for more details).
Status: NEW → ASSIGNED
Depends on: 1124382
No longer depends on: 1198265
Requesting review now, but this won't land until bug 1124382 does (which itself needs bug 1197799).
Attachment #8652786 - Flags: review?(mdoglio)
Attachment #8652786 - Flags: review?(mdoglio) → review+
Commits pushed to master at https://github.com/mozilla/treeherder https://github.com/mozilla/treeherder/commit/5892c72eb269e656db959cdbcf4976f3052d0082 Bug 1197796 - Make WhiteNoise serve the static assets gzipped On Heroku, there is no load balancer or Varnish-like cache in front of gunicorn, so we must handle gzipping responses in the app. In order for WhiteNoise to serve gzipped static content, assets must be gzipped on disk in advance (doing so on-demand in Python would not be as performant). WhiteNoise will then serve the `.gz` version of files in preference to the original, if the client indicated it supported gzip. For assets covered by Django's collectstatic, gzipping the assets only requires using WhiteNoise's GzipManifestStaticFilesStorage backend, which wraps Django's ManifestStaticFilesStorage to create hashed+gzipped versions of static assets: http://whitenoise.evans.io/en/latest/django.html#add-gzip-and-caching-support The collectstatic generated files will then contain the file hash in their filename, so WhiteNoise can also serve them with a large max-age to avoid further requests if the file contents have not changed. For the UI files under `dist/`, we cannot rely on the Django storage backend, since the directory isn't covered by STATICFILES_DIRS (it is instead made known to WhiteNoise via `WHITENOISE_ROOT`). As such, files under `dist/` are gzipped via an additional step during deployment. See: http://whitenoise.evans.io/en/latest/base.html#gzip-support Files whose extension is on the blacklist, or that are not >5% smaller when compressed, are skipped during compression. https://github.com/mozilla/treeherder/commit/5c085724b32b89e49a7af3e5a46670a70e2f41dd Bug 1197796 - Set appropriate max-age for collectstatic generated files Now that we're using WhiteNoise's `GzipManifestStaticFilesStorage` to produce hashed (and gzipped) versions of Django static files, we need to modify `CustomWhiteNoise` so that it supports not only grunt-cache-busting's style of hash filenames, but those generated by `GzipManifestStaticFilesStorage` too. For the latter we fall back to the default DjangoWhiteNoise `is_immutable_file()` method. The grunt-cache-busting's regex has also been made more strict, to reduce the chance of false positives, since the hashes are always 32 characters in length.
serving minified assets + max-age/gzip look fine for: [~/src/treeherder]$ curl -I --compressed https://treeherder-heroku.herokuapp.com/ HTTP/1.1 200 OK Connection: keep-alive Server: gunicorn/19.3.0 Date: Wed, 26 Aug 2015 21:16:45 GMT Last-Modified: Wed, 26 Aug 2015 21:10:06 GMT Content-Type: text/html; charset="utf-8" Cache-Control: public, max-age=60 Access-Control-Allow-Origin: * Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 1746 Via: 1.1 vegur [~/src/treeherder]$ curl -s https://treeherder-heroku.herokuapp.com/ | grep '.min-' <link rel="stylesheet" href="css/index.min-a1860048db7142da031d4d4868bddcab.css" media="screen"> <script src="js/index.min-e432baad1aeac5177b16df7f34f200fc.js"></script> [~/src/treeherder]$ curl -I --compressed https://treeherder-heroku.herokuapp.com/js/index.min-e432baad1aeac5177b16df7f3 4f200fc.js HTTP/1.1 200 OK Connection: keep-alive Server: gunicorn/19.3.0 Date: Wed, 26 Aug 2015 21:17:16 GMT Last-Modified: Wed, 26 Aug 2015 21:10:06 GMT Content-Type: application/javascript; charset="utf-8" Cache-Control: public, max-age=315360000 Access-Control-Allow-Origin: * Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 217807 Via: 1.1 vegur [~/src/treeherder]$ curl -I --compressed https://treeherder-heroku.herokuapp.com/static/embed/css/embed.css HTTP/1.1 200 OK Connection: keep-alive Server: gunicorn/19.3.0 Date: Wed, 26 Aug 2015 21:17:17 GMT Last-Modified: Wed, 26 Aug 2015 21:16:03 GMT Content-Type: text/css; charset="utf-8" Cache-Control: public, max-age=60 Access-Control-Allow-Origin: * Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 159 Via: 1.1 vegur
Status: ASSIGNED → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: