Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.
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:
Próxima SlideShare
Cargando en…5
×

Font End Development + Automation with Django

5.787 visualizaciones

Publicado el

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

Publicado en: Tecnología, Educación
  • Inicia sesión para ver los comentarios

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 />

×