From 6990260b5983e82df799a5bccfe23b0b7e05c6cb Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 30 Jan 2013 17:11:34 -0500 Subject: [PATCH] [manual] Minify JavaScript and CSS in production Manual deployment steps: The same Nginx reload as for "Get rid of the static-access-control mechanism". If deploying both commits at once, just do it once. (imported from commit dd8dbbf14b95fce0a4b6f66f462fa0a6b50bfb8c) --- .gitignore | 2 + humbug/settings.py | 59 +++++++++++++++++++ humbug/urls.py | 5 +- servers/puppet/files/nginx/humbug-include/app | 2 +- templates/zephyr/index.html | 24 ++------ tools/restart-server | 3 + tools/update-prod-static | 28 +++++++++ 7 files changed, 99 insertions(+), 24 deletions(-) create mode 100755 tools/update-prod-static diff --git a/.gitignore b/.gitignore index 1a70ca118c..bbe4c7a833 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ /all_messages_log.* /event_log/* /server.log +/update-prod-static.log +/prod-static *.sw[po] diff --git a/humbug/settings.py b/humbug/settings.py index c6ab5fdf1f..913733550e 100644 --- a/humbug/settings.py +++ b/humbug/settings.py @@ -172,12 +172,71 @@ INSTALLED_APPS = ( 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', + 'django.contrib.staticfiles', 'south', 'jstemplate', 'confirmation', + 'pipeline', 'zephyr', ) + +# Static files and minification + +STATIC_URL = '/static/' + +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +) + +STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage' + +STATIC_ROOT = 'prod-static/collected' + +PIPELINE_CSS = { + 'app': { + 'source_filenames': ( + 'styles/zephyr.css', + 'styles/pygments.css', + ), + 'output_filename': 'min/app.css' + }, +} + +PIPELINE_JS = { + 'app': { + 'source_filenames': ( + 'js/util.js', + 'js/setup.js', + 'js/rows.js', + 'js/narrow.js', + 'js/reload.js', + 'js/compose.js', + 'js/subs.js', + 'js/ui.js', + 'js/typeahead_helper.js', + 'js/search.js', + 'js/composebox_typeahead.js', + 'js/hotkey.js', + 'js/notifications.js', + 'js/hashchange.js', + 'js/invite.js', + 'js/zephyr.js', + ), + 'output_filename': 'min/app.js' + }, +} + +PIPELINE_CSS_COMPRESSOR = 'pipeline.compressors.yui.YUICompressor' +PIPELINE_JS_COMPRESSOR = 'pipeline.compressors.yui.YUICompressor' +PIPELINE_YUI_BINARY = '/usr/bin/env yui-compressor' + +# Disable stuffing the entire JavaScript codebase inside an anonymous function. +# We need modules to be externally visible, so that methods can be called from +# event handlers defined in HTML. +PIPELINE_DISABLE_WRAPPER = True + + USING_RABBITMQ = DEPLOYED # This password also appears in servers/configure-rabbitmq RABBITMQ_PASSWORD = 'xxxxxxxxxxxxxxxx' diff --git a/humbug/urls.py b/humbug/urls.py index a9dab58fc7..e2aa413e63 100644 --- a/humbug/urls.py +++ b/humbug/urls.py @@ -85,7 +85,4 @@ urlpatterns = patterns('', url(r'^notify_pointer_update$', 'zephyr.tornadoviews.notify_pointer_update'), ) -if not settings.DEPLOYED: - urlpatterns += patterns('', - url(r'^static/(?P.*)$', 'django.views.static.serve', - {'document_root': os.path.join(settings.SITE_ROOT, '../zephyr/static')})) +# Static file serving in dev is now handled by django.contrib.staticfiles diff --git a/servers/puppet/files/nginx/humbug-include/app b/servers/puppet/files/nginx/humbug-include/app index 994009fdd4..ad6ffd5919 100644 --- a/servers/puppet/files/nginx/humbug-include/app +++ b/servers/puppet/files/nginx/humbug-include/app @@ -9,7 +9,7 @@ error_page 502 503 504 /static/html/5xx.html; # Serve static files directly location /static/ { - alias /home/humbug/humbug/zephyr/static/; + alias /home/humbug/humbug/prod-static/serve/; error_page 404 /static/html/404.html; } diff --git a/templates/zephyr/index.html b/templates/zephyr/index.html index 5200f95c80..c12657a7d9 100644 --- a/templates/zephyr/index.html +++ b/templates/zephyr/index.html @@ -4,6 +4,7 @@ {# Includes some other templates as tabs. #} {% load jstemplate %} +{% load compressed %} {% block customhead %} @@ -29,8 +30,9 @@ {% rawjstemplate "timeinfo_popover_content" %} - - +{% compressed_css 'app' %} + + @@ -40,24 +42,8 @@ - - - - - - - - - - - - - - - - - +{% compressed_js 'app' %} {% if debug %} diff --git a/tools/restart-server b/tools/restart-server index 244d417d46..59818dbaf2 100755 --- a/tools/restart-server +++ b/tools/restart-server @@ -27,6 +27,9 @@ except: # Delete all .pyc files to avoid old module files hanging around subprocess.check_call(["find", ".", "-name", "*.pyc", "-delete"], stdout=open('/dev/null', 'w')) +# Update static files +subprocess.check_call(["./tools/update-prod-static"]) + # Restart the FastCGI process, which is running in a shell loop in screen. # TODO: real daemonization for cmd in ('runfcgi', 'runtornado', "process_user_activity"): diff --git a/tools/update-prod-static b/tools/update-prod-static new file mode 100755 index 0000000000..dff7441dbf --- /dev/null +++ b/tools/update-prod-static @@ -0,0 +1,28 @@ +#!/bin/bash -e + +# Update static files in production. + +cd "$(dirname "$0")"/.. + +# Redirect output to a log file (most recent run only) +exec >update-prod-static.log + +# Collect both original and minified files +rm -rf prod-static/collected +./manage.py collectstatic --noinput + +# Copy the files we want to expose +rm -rf prod-static/serve-new +mkdir -p prod-static/serve-new/{js,styles} +cp -r prod-static/collected/{favicon.ico,robots.txt,html,third,min} prod-static/serve-new/ +cp prod-static/collected/js/{common,debug,signup}.js prod-static/serve-new/js/ +cp prod-static/collected/styles/{activity,portico}.css prod-static/serve-new/styles/ + +# Sync the new directory to the one nginx actually serves. +# Hopefully this doesn't race too badly for clients loading +# right as a deploy happens. +mkdir -p prod-static/serve +rsync -ar --delete prod-static/serve-new/* prod-static/serve/ + +# Clean up +rm -rf prod-static/{collected,serve-new}