Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.
Tips & Tricks for Front End Development Automation<br />Evan Reiser<br />
Front End Automation?<br />Tools / Tricks to speed up front end dev work<br />Why talk about this?<br />Same reason we all...
django experience<br />Co-founder @ GamerNook<br />Social Network for Gamers<br />100k+ Members<br />Co-founder @ BloomSpo...
Overview<br />Pains with Front end Development<br />Deploying Media Files<br />Compressing / Combine media files<br />Gene...
Problems / Pains<br />Annoying parts of front end development<br />Deploying media to media server / CDN<br />Combining JS...
Tools<br />django.contrib.staticfiles<br />django_storages<br />boto<br />django_compressor<br />YUI JS/CSS Compressor<br ...
django.contrib.staticfiles<br />Pulls media from various places<br />Places them in another place<br />Different folder<br...
Media Files => CDN<br />1) Set up static files to find <br />#settings.py<br />STATICFILES_DIRS = (<br />os.path.join(os.g...
Media Files => CDN	<br />2) Set Storage backend to be S3 / CloudFront<br />#settings.py<br />STATICFILES_STORAGE = 'storag...
Is a python library for interacting with Amazon Web Services
django_storages
A series of storage backends including  a S3</li></li></ul><li>Media Files => CDN<br />2) Push media files to CDN<br />pyt...
Media Files => CDN	<br />4) Reference media in your templates<br />#settings.py<br />TEMPLATE_CONTEXT_PROCESSORS += (<br /...
 Managing Media<br />Managing Media<br />CSS / JavaScript assets<br />We want to:<br />Reduce Http requests<br />Reduce ba...
 Managing Media<br />1. We want to reduce the number of HTTP requests for serving JS + CSS<br /><link rel="stylesheet" hre...
 Managing Media<br />2. We want to minify css / js content and only include what’s needed (reduce bandwidth)<br />/*  <br ...
 Managing Media<br />3. Don’t want to have to change the asset names to prevent client side caching<br />Style.css<br />St...
 Managing Media<br />One way to do this is django_compressor<br />Converts & combines linked or inline css/js into cacheab...
 Managing Media<br />Template changes are minimal<br />{% compress css %}<br /><link href="{{STATIC_URL}}css/admin/base.cs...
Compressor Settings<br />We use a custom Storage Class to store the results on S3<br />from django.core.files.storage impo...
Compressor Settings<br />Compressor settings for offline / pre-greneration<br />import os<br />STATICFILES_FINDERS += (<br...
 Managing Media<br />python manage.py compress<br /><ul><li>combines  static content
applies post processing filters
creates unique name from hash of content
pushes to S3/CDN</li></li></ul><li> Managing Media<br />When template renders<br />Content is hashed => hash value stored ...
Automatic Sprites<br />What are sprites?<br />Sprites are composite images <br />   made up of other images<br />Why?<br /...
Automatic Sprites<br />How do we use sprites?<br />Set them as a css background on a fixed size element<br />Position them...
Automatic Sprites<br /><ul><li>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:
Nächste SlideShare
Wird geladen in …5
×

Font End Development + Automation with Django

5.738 Aufrufe

Veröffentlicht am

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

Veröffentlicht in: Technologie, Bildung
  • Als Erste(r) kommentieren

Font End Development + Automation with Django

  1. 1. Tips & Tricks for Front End Development Automation<br />Evan Reiser<br />
  2. 2. Front End Automation?<br />Tools / Tricks to speed up front end dev work<br />Why talk about this?<br />Same reason we all like Django:<br />More time solving our biz/eng problems<br />Less time doing the same repeatable patterns<br />We want to: Build web apps + add features<br />Not: waste time deploying media, organizing assets, minifying js/css, making sprites etc.<br />
  3. 3. django experience<br />Co-founder @ GamerNook<br />Social Network for Gamers<br />100k+ Members<br />Co-founder @ BloomSpot<br />Luxury Daily Deals<br />3rd Largest Daily Deals site<br />Co-founder @ AdStack<br />Algorithmically Managed Facebook Advertising<br />
  4. 4. Overview<br />Pains with Front end Development<br />Deploying Media Files<br />Compressing / Combine media files<br />Generating Sprites<br />Automate all of this<br />
  5. 5. Problems / Pains<br />Annoying parts of front end development<br />Deploying media to media server / CDN<br />Combining JS / CSS files<br />Minimizing JS / CSS<br />Cache-busting media files in prod<br />Building sprite images<br />Referencing sprites in CSS<br />Having to do this all manually<br />These are all common patterns<br />We shouldn’t have to waste time on them<br />
  6. 6. Tools<br />django.contrib.staticfiles<br />django_storages<br />boto<br />django_compressor<br />YUI JS/CSS Compressor<br />django_media_bundler<br />PIL<br />pngcrush<br />
  7. 7. django.contrib.staticfiles<br />Pulls media from various places<br />Places them in another place<br />Different folder<br />Media Server<br />Or any custom storage backend<br />S3 / CloudFront<br />CDN <br />
  8. 8. Media Files => CDN<br />1) Set up static files to find <br />#settings.py<br />STATICFILES_DIRS = (<br />os.path.join(os.getcwd(),"media"),<br /> )<br />STATICFILES_FINDERS = (<br /> 'django.contrib.staticfiles.finders.FileSystemFinder',<br /> 'django.contrib.staticfiles.finders.AppDirectoriesFinder',<br />)<br />STATIC_ROOT = os.path.join(os.getcwd(),"static")<br />
  9. 9. Media Files => CDN <br />2) Set Storage backend to be S3 / CloudFront<br />#settings.py<br />STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage '<br /><ul><li>boto
  10. 10. Is a python library for interacting with Amazon Web Services
  11. 11. django_storages
  12. 12. A series of storage backends including a S3</li></li></ul><li>Media Files => CDN<br />2) Push media files to CDN<br />python manage.py collectstatic<br />
  13. 13. Media Files => CDN <br />4) Reference media in your templates<br />#settings.py<br />TEMPLATE_CONTEXT_PROCESSORS += (<br /> 'django.core.context_processors.static',<br />)<br />{# Some Template #}<br /><link rel="stylesheet" href="{{STATIC_URL}}style.css" /><br /><link rel="stylesheet" href=“http://cdn.adstack.com/style.css" /><br />
  14. 14. Managing Media<br />Managing Media<br />CSS / JavaScript assets<br />We want to:<br />Reduce Http requests<br />Reduce bandwidth<br />We don’t want to:<br />Think about front-end performance while coding<br />Interrupt our development<br />
  15. 15. Managing Media<br />1. We want to reduce the number of HTTP requests for serving JS + CSS<br /><link rel="stylesheet" href="{{STATIC_URL}}css/admin/base.css" /><br /><link rel="stylesheet" href="{{STATIC_URL}}css/admin/changelists.css" /><br /><link rel="stylesheet" href="{{STATIC_URL}}css/icon_sprites.css"/><br /><link rel="stylesheet" href="{{STATIC_URL}}css/common_10.css" /><br /><link rel="stylesheet" href="{{STATIC_URL}}css/tablesorter.css" /><br /><link rel="stylesheet" href="{{STATIC_URL}}css/multiselect.css" /><br /><link rel="stylesheet" href="{{STATIC_URL}}css/superfish.css" /><br /><link rel="stylesheet" href="{{STATIC_URL}}css/all.css" /><br />
  16. 16. Managing Media<br />2. We want to minify css / js content and only include what’s needed (reduce bandwidth)<br />/* <br /> Make sure to rename this file before you deploy to break client caching!!!<br />*/<br />/* Headers */<br />H1 { <br />font-weight:bold;<br />}<br />H2 {<br />font-weight;bold;<br />}<br />H1,H2 {font-weight:bold}<br />Obviously the same thing goes for JS<br />
  17. 17. Managing Media<br />3. Don’t want to have to change the asset names to prevent client side caching<br />Style.css<br />Style2.css<br />Style3.css<br />Style4.css<br />Style5.css<br />
  18. 18. Managing Media<br />One way to do this is django_compressor<br />Converts & combines linked or inline css/js into cacheable static files<br />Compression / minification support for: CSS Tidy, YUI CSS + JS, Google’s Closure Compiler, JSmin, cssmin<br />Builds unique static file names to bust cache<br />No need to heavily modify existing templates<br />Plus:<br />Extendable for custom post processing / filtering via python<br />
  19. 19. Managing Media<br />Template changes are minimal<br />{% compress css %}<br /><link href="{{STATIC_URL}}css/admin/base.css" /><br /><link href="{{STATIC_URL}}css/admin/changelists.css" /><br /><link href="{{STATIC_URL}}css/icon_sprites.css"/><br /><link href="{{STATIC_URL}}css/common_10.css" /><br /><link href="{{STATIC_URL}}css/tablesorter.css" /><br /><link href="{{STATIC_URL}}css/multiselect.css" /><br /><link href="{{STATIC_URL}}css/superfish.css" /><br />{% endcompress %}<br />{% compress js %}<br /><script src="{{STATIC_URL}}js/jquery-1.5.1.min.js"></script><br /><script src="{{ STATIC_URL }}js/jquery.hoverIntent.js"></script><br /><script src="{{STATIC_URL}}js/common.js"></script><br /><script src="{{STATIC_URL}}js/jquery.multiselect.min.js"></script><br /><script src="{{STATIC_URL}}js/jquery.cluetip.min.js"></script><br /><script src="{{STATIC_URL}}js/jquery.tablesorter.js"></script><br /><script src="{{ STATIC_URL }}js/jquery.tooltip.pack.js"></script><br /><script src="{{ STATIC_URL }}js/superfish.js"></script><br />{% endcompress %}<br />
  20. 20. Compressor Settings<br />We use a custom Storage Class to store the results on S3<br />from django.core.files.storage import get_storage_class<br />from storages.backends.s3boto import S3BotoStorage<br /> <br />#A special Storage class that saves to S3 and Locally<br />class CachedS3BotoStorage(S3BotoStorage):<br />   <br />    def __init__(self, *args, **kwargs):<br />        super(CachedS3BotoStorage, self).__init__(*args, **kwargs)<br />        self.local_storage = get_storage_class(<br />            "compressor.storage.CompressorFileStorage")()<br /> <br />    def save(self, name, content):<br />        name = super(CachedS3BotoStorage, self).save(name,content)<br />        self.local_storage._save(name, content)<br />        return name<br />
  21. 21. Compressor Settings<br />Compressor settings for offline / pre-greneration<br />import os<br />STATICFILES_FINDERS += (<br /> 'compressor.finders.CompressorFinder',<br />)<br />COMPRESS_OFFLINE = True<br />COMPRESS_STORAGE = "common.common_storages.CachedS3BotoStorage"<br />COMPRESS_ROOT = os.path.join(os.path.dirname(__file__), 'media')<br />COMPRESS_OUTPUT_DIR = "compress_cache"<br />COMPRESS_OFFLINE_CONTEXT = {"STATIC_URL":STATIC_URL}<br />COMPRESS_URL = STATIC_URL<br /> <br />#post processing filters<br />COMPRESS_CSS_FILTERS = ['compressor.filters.yui.YUICSSFilter‘]<br />COMPRESS_JS_FILTERS = ['compressor.filters.jsmin.JSMinFilter']<br />COMPRESS_YUI_BINARY = 'java -jar %s yuicompressor-2.4.6.jar'<br />
  22. 22. Managing Media<br />python manage.py compress<br /><ul><li>combines static content
  23. 23. applies post processing filters
  24. 24. creates unique name from hash of content
  25. 25. pushes to S3/CDN</li></li></ul><li> Managing Media<br />When template renders<br />Content is hashed => hash value stored in cache<br />Individual reference in template replaced<br />{% compress css %}<br /><link href="{{STATIC_URL}}css/admin/base.css" /><br /><link href="{{STATIC_URL}}css/admin/changelists.css" /><br /><link href="{{STATIC_URL}}css/icon_sprites.css"/><br /><link href="{{STATIC_URL}}css/common_10.css" /><br /><link href="{{STATIC_URL}}css/tablesorter.css" /><br /><link href="{{STATIC_URL}}css/multiselect.css" /><br /><link href="{{STATIC_URL}}css/superfish.css" /><br />{% endcompress %}<br /><link rel="stylesheet" href="http://cdn.adstack.com/compress_cache/css/32dd63bd423c.css" /><br />
  26. 26. Automatic Sprites<br />What are sprites?<br />Sprites are composite images <br /> made up of other images<br />Why?<br />Reduce # HTTP requests<br />How?<br />CSS is used to only show part of the composite image<br />
  27. 27. Automatic Sprites<br />How do we use sprites?<br />Set them as a css background on a fixed size element<br />Position them so only<br /> part of the larger<br /> image shows<br />Cool.<br />But this is really a pain<br />Creating images<br />Custom css for positioning<br />
  28. 28. Automatic Sprites<br /><ul><li>django_media_bundler
  29. 29. can help build the sprite automatically
  30. 30. Generates positioning CSS
  31. 31. Uses python + PIL to generate the sprite
  32. 32. Uses pngcrush to optimize the final image size
  33. 33. Use Case:
  34. 34. We have a folder full of icons
  35. 35. user.png, email.png, add.png
  36. 36. We want to easily put these in templates
  37. 37. {% icon "email" %}</li></li></ul><li>Automatic Sprites<br /><ul><li>Simple example: lots of icons</li></ul>*doing this can be a pain<br />
  38. 38. Automatic Sprites<br />1) Configure Media bundler settings<br />MEDIA_BUNDLES = (<br />    {"type": "png-sprite",<br />     "name": "icon",<br />     "path": os.path.join(MEDIA_ROOT,"icons"),<br />     "url": "../icons/",<br />     "css_file": os.path.join(MEDIA_ROOT,"css","icon_sprites.css"),<br />     "files": [<br /> “add.png”,<br />“delete.png”,<br />“user.png”,<br />“delete.png”,<br />“group.png”,<br /> ]<br />    },<br />)<br />
  39. 39. Automatic Sprites<br />1) Configure Media bundler settings<br />MEDIA_BUNDLES = (<br />    {"type": "png-sprite",<br />     "name": "icon",<br />     "path": os.path.join(MEDIA_ROOT,"icons"),<br />     "url": "../icons/",<br />     "css_file": os.path.join(MEDIA_ROOT,"css","icon_sprites.css"),<br />     "files": filter(lambda x: x[-4:]== '.png',          <br />               os.listdir(os.path.join(MEDIA_ROOT,"icons")))<br />    },<br />)<br />
  40. 40. Automatic Sprites<br />2) Bundle our media<br />python manage.py bundle_media<br />3) This creates a sprite.png + sprite.css<br />.icon {background-image: url('http://cdn.adstack.com/icons/sprites/icon110701154833.png?675d7dfaa1e1');}<br />.icon_user {width: 16px;background-position: 0px 0px;height: 16px;}<br />.icon_add {width: 16px;background-position: -16px 0px;height: 16px;}<br />Etc…<br />
  41. 41. <style><br />.icon {width: 16px;height: 16px;margin: 0;padding: 0;display: inline-block;position: relative;top: 2px;}<br /></style><br /><div><span class=“icon icon_user”></span> Hello Evan</div><br />Automatic Sprites<br />4) We can then show icons using css<br />Hello Evan<br />
  42. 42. Automatic Sprites<br />5) We can easily write template tags to make this easier<br />#front_end_tags.py<br />from django import template<br />register = template.Library()<br />@register.inclusion_tag("common/front_end/icon.html")<br />def icon(icon_name):<br /> return locals()<br />{# common/front_end/icon.html #}<br /><span class="icon icon_{{ icon_name }}"></span><br />6) Now it’s a bit easier to develop<br /><div> {% icon "user" %} Hello Evan</div><br />
  43. 43. Automation<br />Fabric Deploy Script <br />from fabric.api import *<br />defcdn_deploy():<br />run('python manage.py bundle_media')<br />run('python manage.py collectstatic --noinput')<br />run('python manage.py compress')<br />fab cdn_deploy<br />
  44. 44. References<br />django.contrib.staticfiles<br />https://docs.djangoproject.com/en/dev/howto/static-files/<br />Boto<br />http://code.google.com/p/boto/<br />Fabric<br />http://docs.fabfile.org/en/1.1.1/index.html<br />django_compressor<br />http://code.google.com/p/django-compressor/<br />Boto<br />http://code.google.com/p/boto/<br />django_storages<br />https://bitbucket.org/david/django-storages/wiki/Home<br />django_media_bundler<br />https://github.com/fabiocorneti/django-media-bundler<br />Pngcrush<br />http://pmt.sourceforge.net/pngcrush/<br />YUI compressor<br />http://developer.yahoo.com/yui/compressor/<br />
  45. 45. Questions?<br />Evan Reiser<br />evan@adstack.com<br />

×