33
Tips & Tricks for Front End Development Automation Evan Reiser

Font End Development + Automation with Django

Embed Size (px)

DESCRIPTION

Tips and tricks for front end development automation using python and django by Evan Reiser

Citation preview

Page 1: Font End Development + Automation with Django

Tips & Tricks for Front End Development Automation

Evan Reiser

Page 2: Font End Development + Automation with Django

Front End Automation? Tools / Tricks to speed up front end dev work

Why talk about this? Same reason we all like Django:▪ More time solving our biz/eng problems▪ Less time doing the same repeatable patterns

We want to: Build web apps + add features Not: waste time deploying media,

organizing assets, minifying js/css, making sprites etc.

Page 3: Font End Development + Automation with Django

django experience

Co-founder @ GamerNook Social Network for Gamers▪ 100k+ Members

Co-founder @ BloomSpot Luxury Daily Deals▪ 3rd Largest Daily Deals site

Co-founder @ AdStack Algorithmically Managed

Facebook Advertising

Page 4: Font End Development + Automation with Django

Overview

Pains with Front end Development Deploying Media Files Compressing / Combine media files Generating Sprites Automate all of this

Page 5: Font End Development + Automation with Django

Problems / Pains

Annoying parts of front end development Deploying media to media server / CDN Combining JS / CSS files Minimizing JS / CSS Cache-busting media files in prod Building sprite images Referencing sprites in CSS Having to do this all manually

These are all common patterns We shouldn’t have to waste time on them

Page 6: Font End Development + Automation with Django

Tools

django.contrib.staticfiles django_storages boto

django_compressor YUI JS/CSS Compressor

django_media_bundler PIL pngcrush

Page 7: Font End Development + Automation with Django

django.contrib.staticfiles

Pulls media from various places Places them in another place

Different folder Media Server Or any custom storage backend▪ S3 / CloudFront▪CDN

Page 8: Font End Development + Automation with Django

Media Files => CDN

1. #settings.py

2. STATICFILES_DIRS = (3. os.path.join(os.getcwd(),"media"),4. )5. STATICFILES_FINDERS = (6. 'django.contrib.staticfiles.finders.FileSystemFinder',7. 'django.contrib.staticfiles.finders.AppDirectoriesFinder',8. )9. STATIC_ROOT = os.path.join(os.getcwd(),"static")

1) Set up static files to find

Page 9: Font End Development + Automation with Django

Media Files => CDN

1. #settings.py

2. STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage '

2) Set Storage backend to be S3 / CloudFront

• boto• Is a python library for interacting with

Amazon Web Services• django_storages• A series of storage backends including a

S3

Page 10: Font End Development + Automation with Django

Media Files => CDN

python manage.py collectstatic

2) Push media files to CDN

Page 11: Font End Development + Automation with Django

Media Files => CDN

1. #settings.py2. TEMPLATE_CONTEXT_PROCESSORS += (3. 'django.core.context_processors.static',4. )

4) Reference media in your templates

1. {# Some Template #}2. <link rel="stylesheet" href="{{STATIC_URL}}style.css" />

1. <link rel="stylesheet" href=“http://cdn.adstack.com/style.css" />

Page 12: Font End Development + Automation with Django

Managing Media

Managing Media CSS / JavaScript assets

We want to: Reduce Http requests Reduce bandwidth

We don’t want to: Think about front-end performance while

coding Interrupt our development

Page 13: Font End Development + Automation with Django

Managing Media

1. We want to reduce the number of HTTP requests for serving JS + CSS

<link rel="stylesheet" href="{{STATIC_URL}}css/admin/base.css" /><link rel="stylesheet" href="{{STATIC_URL}}css/admin/changelists.css" /><link rel="stylesheet" href="{{STATIC_URL}}css/icon_sprites.css"/><link rel="stylesheet" href="{{STATIC_URL}}css/common_10.css" /><link rel="stylesheet" href="{{STATIC_URL}}css/tablesorter.css" /><link rel="stylesheet" href="{{STATIC_URL}}css/multiselect.css" /><link rel="stylesheet" href="{{STATIC_URL}}css/superfish.css" />

<link rel="stylesheet" href="{{STATIC_URL}}css/all.css" />

Page 14: Font End Development + Automation with Django

Managing Media

2. We want to minify css / js content and only include what’s needed (reduce bandwidth)/*

Make sure to rename this file before you deploy to break client caching!!!*/

/* Headers */H1 {

font-weight:bold;}H2 {

font-weight;bold;}

H1,H2 {font-weight:bold}

Obviously the same thing goes for JS

Page 15: Font End Development + Automation with Django

Managing Media

3. Don’t want to have to change the asset names to prevent client side caching

Style.css Style2.css Style3.css Style4.css Style5.css

Page 16: Font End Development + Automation with Django

Managing Media

One way to do this is django_compressor Converts & combines linked or inline css/js

into cacheable static files Compression / minification support for: CSS

Tidy, YUI CSS + JS, Google’s Closure Compiler, JSmin, cssmin

Builds unique static file names to bust cache No need to heavily modify existing

templates Plus:▪ Extendable for custom post processing / filtering

via python

Page 17: Font End Development + Automation with Django

Managing Media Template changes are minimal

{% compress css %}<link href="{{STATIC_URL}}css/admin/base.css" /><link href="{{STATIC_URL}}css/admin/changelists.css" /><link href="{{STATIC_URL}}css/icon_sprites.css"/><link href="{{STATIC_URL}}css/common_10.css" /><link href="{{STATIC_URL}}css/tablesorter.css" /><link href="{{STATIC_URL}}css/multiselect.css" /><link href="{{STATIC_URL}}css/superfish.css" />{% endcompress %}

{% compress js %}<script src="{{STATIC_URL}}js/jquery-1.5.1.min.js"></script><script src="{{ STATIC_URL }}js/jquery.hoverIntent.js"></script><script src="{{STATIC_URL}}js/common.js"></script><script src="{{STATIC_URL}}js/jquery.multiselect.min.js"></script><script src="{{STATIC_URL}}js/jquery.cluetip.min.js"></script><script src="{{STATIC_URL}}js/jquery.tablesorter.js"></script><script src="{{ STATIC_URL }}js/jquery.tooltip.pack.js"></script><script src="{{ STATIC_URL }}js/superfish.js"></script>{% endcompress %}

Page 18: Font End Development + Automation with Django

Compressor Settings

1. from django.core.files.storage import get_storage_class2. from storages.backends.s3boto import S3BotoStorage3.  4. #A special Storage class that saves to S3 and Locally5. class CachedS3BotoStorage(S3BotoStorage):6.    7.     def __init__(self, *args, **kwargs):8.         super(CachedS3BotoStorage, self).__init__(*args, **kwargs)9.         self.local_storage = get_storage_class(10.            "compressor.storage.CompressorFileStorage")()11. 12.    def save(self, name, content):13.        name = super(CachedS3BotoStorage, self).save(name,content)14.        self.local_storage._save(name, content)15.        return name

We use a custom Storage Class to store the results on S3

Page 19: Font End Development + Automation with Django

Compressor Settings

1. import os2. STATICFILES_FINDERS += (3. 'compressor.finders.CompressorFinder',4. )

5. COMPRESS_OFFLINE = True6. COMPRESS_STORAGE = "common.common_storages.CachedS3BotoStorage"

7. COMPRESS_ROOT = os.path.join(os.path.dirname(__file__), 'media')8. COMPRESS_OUTPUT_DIR = "compress_cache"

9. COMPRESS_OFFLINE_CONTEXT = {"STATIC_URL":STATIC_URL}10.COMPRESS_URL = STATIC_URL11. 12.#post processing filters13.COMPRESS_CSS_FILTERS = ['compressor.filters.yui.YUICSSFilter‘]14.COMPRESS_JS_FILTERS = ['compressor.filters.jsmin.JSMinFilter']15.COMPRESS_YUI_BINARY = 'java -jar %s yuicompressor-2.4.6.jar'

Compressor settings for offline / pre-greneration

Page 20: Font End Development + Automation with Django

Managing Media

python manage.py compress

• combines static content• applies post processing filters• creates unique name from hash of

content• pushes to S3/CDN

Page 21: Font End Development + Automation with Django

Managing Media

{% compress css %}<link href="{{STATIC_URL}}css/admin/base.css" /><link href="{{STATIC_URL}}css/admin/changelists.css" /><link href="{{STATIC_URL}}css/icon_sprites.css"/><link href="{{STATIC_URL}}css/common_10.css" /><link href="{{STATIC_URL}}css/tablesorter.css" /><link href="{{STATIC_URL}}css/multiselect.css" /><link href="{{STATIC_URL}}css/superfish.css" />{% endcompress %}

<link rel="stylesheet" href="http://cdn.adstack.com/compress_cache/css/32dd63bd423c.css" />

When template renders Content is hashed => hash value stored

in cache Individual reference in template replaced

Page 22: Font End Development + Automation with Django

Automatic Sprites

What are sprites? Sprites are composite images made up of other images

Why? Reduce # HTTP requests

How? CSS is used to only show part of

the composite image

Page 23: Font End Development + Automation with Django

Automatic Sprites

How do we use sprites? Set them as a css background on a fixed

size element Position them so only part of the larger image shows

Cool. But this is really a pain▪ Creating images▪ Custom css for positioning

Page 24: Font End Development + Automation with Django

Automatic Sprites

• django_media_bundler • can help build the sprite automatically• Generates positioning CSS• Uses python + PIL to generate the sprite• Uses pngcrush to optimize the final

image size

• Use Case:• We have a folder full of icons• user.png, email.png, add.png

• We want to easily put these in templates• {% icon "email" %}

Page 25: Font End Development + Automation with Django

Automatic Sprites

• Simple example: lots of icons

*doing this can be a pain

Page 26: Font End Development + Automation with Django

Automatic Sprites

1. MEDIA_BUNDLES = (2.     {"type": "png-sprite",3.      "name": "icon",4.      "path": os.path.join(MEDIA_ROOT,"icons"),5.      "url": "../icons/",6.      "css_file": os.path.join(MEDIA_ROOT,"css","icon_sprites.css"),7.      "files": [8. “add.png”,9. “delete.png”,10. “user.png”,11. “delete.png”,12. “group.png”,13. ]14.    },15.)

1) Configure Media bundler settings

Page 27: Font End Development + Automation with Django

Automatic Sprites

1. MEDIA_BUNDLES = (2.     {"type": "png-sprite",3.      "name": "icon",4.      "path": os.path.join(MEDIA_ROOT,"icons"),5.      "url": "../icons/",6.      "css_file": os.path.join(MEDIA_ROOT,"css","icon_sprites.css"),7.      "files": filter(lambda x: x[-4:]== '.png',          8.                os.listdir(os.path.join(MEDIA_ROOT,"icons")))9.     },10.)

1) Configure Media bundler settings

Page 28: Font End Development + Automation with Django

Automatic Sprites

python manage.py bundle_media

2) Bundle our media

3) This creates a sprite.png + sprite.css

.icon {background-image: url('http://cdn.adstack.com/icons/sprites/icon110701154833.png?675d7dfaa1e1');}

.icon_user {width: 16px;background-position: 0px 0px;height: 16px;}.icon_add {width: 16px;background-position: -16px 0px;height: 16px;}

Etc…

Page 29: Font End Development + Automation with Django

<style>.icon {width: 16px;height: 16px;margin: 0;padding: 0;display: inline-block;position: relative;top: 2px;}</style>

<div><span class=“icon icon_user”></span> Hello Evan</div>

Automatic Sprites4) We can then show icons using css

Hello Evan

Page 30: Font End Development + Automation with Django

#front_end_tags.pyfrom django import templateregister = template.Library()

@register.inclusion_tag("common/front_end/icon.html")def icon(icon_name): return locals()

{# common/front_end/icon.html #}<span class="icon icon_{{ icon_name }}"></span>

<div> {% icon "user" %} Hello Evan</div>

5) We can easily write template tags to make this easier

6) Now it’s a bit easier to develop

Automatic Sprites

Page 31: Font End Development + Automation with Django

Automation

Fabric Deploy Script

from fabric.api import *def cdn_deploy():

run('python manage.py bundle_media')run('python manage.py collectstatic --noinput')run('python manage.py compress')

fab cdn_deploy

Page 32: Font End Development + Automation with Django

References django.contrib.staticfiles

https://docs.djangoproject.com/en/dev/howto/static-files/ Boto

http://code.google.com/p/boto/ Fabric

http://docs.fabfile.org/en/1.1.1/index.html django_compressor

http://code.google.com/p/django-compressor/ Boto

http://code.google.com/p/boto/ django_storages

https://bitbucket.org/david/django-storages/wiki/Home django_media_bundler

https://github.com/fabiocorneti/django-media-bundler Pngcrush

http://pmt.sourceforge.net/pngcrush/ YUI compressor

http://developer.yahoo.com/yui/compressor/

Page 33: Font End Development + Automation with Django

Questions?

Evan [email protected]