SlideShare une entreprise Scribd logo
1  sur  33
Tips & Tricks for Front End Development Automation Evan Reiser
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.
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
Overview Pains with Front end Development Deploying Media Files Compressing / Combine media files Generating Sprites Automate all of this
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
Tools django.contrib.staticfiles django_storages boto django_compressor YUI JS/CSS Compressor django_media_bundler PIL pngcrush
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
Media Files => CDN 1) Set up static files to find  #settings.py STATICFILES_DIRS = ( os.path.join(os.getcwd(),"media"),     ) STATICFILES_FINDERS = (     'django.contrib.staticfiles.finders.FileSystemFinder',     'django.contrib.staticfiles.finders.AppDirectoriesFinder', ) STATIC_ROOT = os.path.join(os.getcwd(),"static")
Media Files => CDN	 2) Set Storage backend to be S3 / CloudFront #settings.py STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage ' ,[object Object]
Is a python library for interacting with Amazon Web Services
django_storages
A series of storage backends including  a S3,[object Object]
Media Files => CDN	 4) Reference media in your templates #settings.py TEMPLATE_CONTEXT_PROCESSORS += (     'django.core.context_processors.static', ) {# Some Template #} <link rel="stylesheet" href="{{STATIC_URL}}style.css" /> <link rel="stylesheet" href=“http://cdn.adstack.com/style.css" />
 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
 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" />
 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
 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
 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
 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 %}
Compressor Settings We use a custom Storage Class to store the results on S3 from django.core.files.storage import get_storage_class from storages.backends.s3boto import S3BotoStorage   #A special Storage class that saves to S3 and Locally class CachedS3BotoStorage(S3BotoStorage):         def __init__(self, *args, **kwargs):         super(CachedS3BotoStorage, self).__init__(*args, **kwargs)         self.local_storage = get_storage_class(             "compressor.storage.CompressorFileStorage")()       def save(self, name, content):         name = super(CachedS3BotoStorage, self).save(name,content)         self.local_storage._save(name, content)         return name
Compressor Settings Compressor settings for offline / pre-greneration import os STATICFILES_FINDERS += (     'compressor.finders.CompressorFinder', ) COMPRESS_OFFLINE = True COMPRESS_STORAGE = "common.common_storages.CachedS3BotoStorage" COMPRESS_ROOT = os.path.join(os.path.dirname(__file__), 'media') COMPRESS_OUTPUT_DIR = "compress_cache" COMPRESS_OFFLINE_CONTEXT = {"STATIC_URL":STATIC_URL} COMPRESS_URL = STATIC_URL   #post processing filters COMPRESS_CSS_FILTERS = ['compressor.filters.yui.YUICSSFilter‘] COMPRESS_JS_FILTERS = ['compressor.filters.jsmin.JSMinFilter'] COMPRESS_YUI_BINARY = 'java -jar %s yuicompressor-2.4.6.jar'
 Managing Media python manage.py compress ,[object Object]
applies post processing filters
creates unique name from hash of content
pushes to S3/CDN,[object Object]
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
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
Automatic Sprites ,[object Object]
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:

Contenu connexe

Tendances

Latency Kills by Shishir Birmiwal
Latency Kills by Shishir BirmiwalLatency Kills by Shishir Birmiwal
Latency Kills by Shishir Birmiwal
Pravin Nirmal
 
Social Media Workshop - Word Press
Social Media Workshop - Word PressSocial Media Workshop - Word Press
Social Media Workshop - Word Press
Romany Thresher
 
Joomla 1.6 Core SEO and Best Practices
Joomla 1.6 Core SEO and Best PracticesJoomla 1.6 Core SEO and Best Practices
Joomla 1.6 Core SEO and Best Practices
FinishJoomla
 

Tendances (19)

Seo cheat sheet_2-2013
Seo cheat sheet_2-2013Seo cheat sheet_2-2013
Seo cheat sheet_2-2013
 
ARTICULOENINGLES
ARTICULOENINGLESARTICULOENINGLES
ARTICULOENINGLES
 
Seo for Engineers
Seo for EngineersSeo for Engineers
Seo for Engineers
 
What's Next for Page Experience - SMX Next 2021 - Patrick Stox
What's Next for Page Experience - SMX Next 2021 - Patrick StoxWhat's Next for Page Experience - SMX Next 2021 - Patrick Stox
What's Next for Page Experience - SMX Next 2021 - Patrick Stox
 
Latency Kills by Shishir Birmiwal
Latency Kills by Shishir BirmiwalLatency Kills by Shishir Birmiwal
Latency Kills by Shishir Birmiwal
 
Social Media Workshop - Word Press
Social Media Workshop - Word PressSocial Media Workshop - Word Press
Social Media Workshop - Word Press
 
Blackhat Analyics 4: May the 25th be with you!
Blackhat Analyics 4:  May the 25th be with you!Blackhat Analyics 4:  May the 25th be with you!
Blackhat Analyics 4: May the 25th be with you!
 
Joomla 1.6 Core SEO and Best Practices
Joomla 1.6 Core SEO and Best PracticesJoomla 1.6 Core SEO and Best Practices
Joomla 1.6 Core SEO and Best Practices
 
Joomla 1.7 SEO
Joomla 1.7 SEOJoomla 1.7 SEO
Joomla 1.7 SEO
 
Global SharePoint Users Group 1/5/10 - Creating Custom Actions Within SharePoint
Global SharePoint Users Group 1/5/10 - Creating Custom Actions Within SharePointGlobal SharePoint Users Group 1/5/10 - Creating Custom Actions Within SharePoint
Global SharePoint Users Group 1/5/10 - Creating Custom Actions Within SharePoint
 
A Crash Course in Technical SEO from Patrick Stox - Beer & SEO Meetup May 2019
A Crash Course in Technical SEO from Patrick Stox - Beer & SEO Meetup May 2019A Crash Course in Technical SEO from Patrick Stox - Beer & SEO Meetup May 2019
A Crash Course in Technical SEO from Patrick Stox - Beer & SEO Meetup May 2019
 
How can a data layer help my seo
How can a data layer help my seoHow can a data layer help my seo
How can a data layer help my seo
 
BP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
BP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog TemplateBP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
BP304 - Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
 
7 steps
7 steps7 steps
7 steps
 
SharePoint Saturday Boston 2/27/10 - Whats New For Developers In SharePoint 2010
SharePoint Saturday Boston 2/27/10 - Whats New For Developers In SharePoint 2010SharePoint Saturday Boston 2/27/10 - Whats New For Developers In SharePoint 2010
SharePoint Saturday Boston 2/27/10 - Whats New For Developers In SharePoint 2010
 
Master page
Master pageMaster page
Master page
 
Advanced WordPress Optimization - iGaming Supershow 2012
Advanced WordPress Optimization - iGaming Supershow 2012Advanced WordPress Optimization - iGaming Supershow 2012
Advanced WordPress Optimization - iGaming Supershow 2012
 
SharePoint Saturday Hartford - 01/29/11 - Creating Custom Actions in SharePoi...
SharePoint Saturday Hartford - 01/29/11 - Creating Custom Actions in SharePoi...SharePoint Saturday Hartford - 01/29/11 - Creating Custom Actions in SharePoi...
SharePoint Saturday Hartford - 01/29/11 - Creating Custom Actions in SharePoi...
 
HTML Basics 2 workshop
HTML Basics 2 workshopHTML Basics 2 workshop
HTML Basics 2 workshop
 

Similaire à Font End Development + Automation with Django

Developing branding solutions for 2013
Developing branding solutions for 2013Developing branding solutions for 2013
Developing branding solutions for 2013
Thomas Daly
 
Developing branding solutions for 2013
Developing branding solutions for 2013Developing branding solutions for 2013
Developing branding solutions for 2013
Thomas Daly
 

Similaire à Font End Development + Automation with Django (20)

Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
Blog It Up, Baby! Extending the new IBM Lotus Domino Blog TemplateBlog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
Blog It Up, Baby! Extending the new IBM Lotus Domino Blog Template
 
MongoDB.local Dallas 2019: MongoDB Stitch Tutorial
MongoDB.local Dallas 2019: MongoDB Stitch TutorialMongoDB.local Dallas 2019: MongoDB Stitch Tutorial
MongoDB.local Dallas 2019: MongoDB Stitch Tutorial
 
Widgets: Making Your Site Great and Letting Others Help - WordCamp Victoria
Widgets: Making Your Site Great and Letting Others Help - WordCamp VictoriaWidgets: Making Your Site Great and Letting Others Help - WordCamp Victoria
Widgets: Making Your Site Great and Letting Others Help - WordCamp Victoria
 
The Need for Speed (5 Performance Optimization Tipps) - brightonSEO 2014
The Need for Speed (5 Performance Optimization Tipps) - brightonSEO 2014The Need for Speed (5 Performance Optimization Tipps) - brightonSEO 2014
The Need for Speed (5 Performance Optimization Tipps) - brightonSEO 2014
 
Building Web Hack Interfaces
Building Web Hack InterfacesBuilding Web Hack Interfaces
Building Web Hack Interfaces
 
The Need for Speed - SMX Sydney 2013
The Need for Speed - SMX Sydney 2013The Need for Speed - SMX Sydney 2013
The Need for Speed - SMX Sydney 2013
 
On-Page SEO EXTREME - SEOZone Istanbul 2013
On-Page SEO EXTREME - SEOZone Istanbul 2013On-Page SEO EXTREME - SEOZone Istanbul 2013
On-Page SEO EXTREME - SEOZone Istanbul 2013
 
Developing branding solutions for 2013
Developing branding solutions for 2013Developing branding solutions for 2013
Developing branding solutions for 2013
 
MongoDB.local Atlanta: MongoDB Stitch Tutorial
MongoDB.local Atlanta: MongoDB Stitch TutorialMongoDB.local Atlanta: MongoDB Stitch Tutorial
MongoDB.local Atlanta: MongoDB Stitch Tutorial
 
MongoDB.local Seattle 2019: MongoDB Stitch Tutorial
MongoDB.local Seattle 2019: MongoDB Stitch TutorialMongoDB.local Seattle 2019: MongoDB Stitch Tutorial
MongoDB.local Seattle 2019: MongoDB Stitch Tutorial
 
Web design and Development
Web design and DevelopmentWeb design and Development
Web design and Development
 
Front end performance optimization
Front end performance optimizationFront end performance optimization
Front end performance optimization
 
Developing Branding Solutions for 2013
Developing Branding Solutions for 2013Developing Branding Solutions for 2013
Developing Branding Solutions for 2013
 
WordPress 3.0 at DC PHP
WordPress 3.0 at DC PHPWordPress 3.0 at DC PHP
WordPress 3.0 at DC PHP
 
Using a CSS Framework
Using a CSS FrameworkUsing a CSS Framework
Using a CSS Framework
 
Please dont touch-3.6-jsday
Please dont touch-3.6-jsdayPlease dont touch-3.6-jsday
Please dont touch-3.6-jsday
 
Web technologies part-2
Web technologies part-2Web technologies part-2
Web technologies part-2
 
Developing branding solutions for 2013
Developing branding solutions for 2013Developing branding solutions for 2013
Developing branding solutions for 2013
 
SEO Audit Report | Analyze Website Free 2023
SEO Audit Report | Analyze Website Free 2023SEO Audit Report | Analyze Website Free 2023
SEO Audit Report | Analyze Website Free 2023
 
WordCamp Denmark Keynote
WordCamp Denmark KeynoteWordCamp Denmark Keynote
WordCamp Denmark Keynote
 

Dernier

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 

Dernier (20)

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 

Font End Development + Automation with Django

  • 1. Tips & Tricks for Front End Development Automation Evan Reiser
  • 2. 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.
  • 3. 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
  • 4. Overview Pains with Front end Development Deploying Media Files Compressing / Combine media files Generating Sprites Automate all of this
  • 5. 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
  • 6. Tools django.contrib.staticfiles django_storages boto django_compressor YUI JS/CSS Compressor django_media_bundler PIL pngcrush
  • 7. 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
  • 8. Media Files => CDN 1) Set up static files to find #settings.py STATICFILES_DIRS = ( os.path.join(os.getcwd(),"media"), ) STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ) STATIC_ROOT = os.path.join(os.getcwd(),"static")
  • 9.
  • 10. Is a python library for interacting with Amazon Web Services
  • 12.
  • 13. Media Files => CDN 4) Reference media in your templates #settings.py TEMPLATE_CONTEXT_PROCESSORS += ( 'django.core.context_processors.static', ) {# Some Template #} <link rel="stylesheet" href="{{STATIC_URL}}style.css" /> <link rel="stylesheet" href=“http://cdn.adstack.com/style.css" />
  • 14. 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
  • 15. 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" />
  • 16. 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
  • 17. 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
  • 18. 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
  • 19. 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 %}
  • 20. Compressor Settings We use a custom Storage Class to store the results on S3 from django.core.files.storage import get_storage_class from storages.backends.s3boto import S3BotoStorage   #A special Storage class that saves to S3 and Locally class CachedS3BotoStorage(S3BotoStorage):         def __init__(self, *args, **kwargs):         super(CachedS3BotoStorage, self).__init__(*args, **kwargs)         self.local_storage = get_storage_class(             "compressor.storage.CompressorFileStorage")()       def save(self, name, content):         name = super(CachedS3BotoStorage, self).save(name,content)         self.local_storage._save(name, content)         return name
  • 21. Compressor Settings Compressor settings for offline / pre-greneration import os STATICFILES_FINDERS += ( 'compressor.finders.CompressorFinder', ) COMPRESS_OFFLINE = True COMPRESS_STORAGE = "common.common_storages.CachedS3BotoStorage" COMPRESS_ROOT = os.path.join(os.path.dirname(__file__), 'media') COMPRESS_OUTPUT_DIR = "compress_cache" COMPRESS_OFFLINE_CONTEXT = {"STATIC_URL":STATIC_URL} COMPRESS_URL = STATIC_URL   #post processing filters COMPRESS_CSS_FILTERS = ['compressor.filters.yui.YUICSSFilter‘] COMPRESS_JS_FILTERS = ['compressor.filters.jsmin.JSMinFilter'] COMPRESS_YUI_BINARY = 'java -jar %s yuicompressor-2.4.6.jar'
  • 22.
  • 24. creates unique name from hash of content
  • 25.
  • 26. 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
  • 27. 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
  • 28.
  • 29. can help build the sprite automatically
  • 31. Uses python + PIL to generate the sprite
  • 32. Uses pngcrush to optimize the final image size
  • 34. We have a folder full of icons
  • 36. We want to easily put these in templates
  • 37.
  • 38. Automatic Sprites 1) Configure Media bundler settings MEDIA_BUNDLES = (     {"type": "png-sprite",      "name": "icon",      "path": os.path.join(MEDIA_ROOT,"icons"),      "url": "../icons/",      "css_file": os.path.join(MEDIA_ROOT,"css","icon_sprites.css"),      "files": [ “add.png”, “delete.png”, “user.png”, “delete.png”, “group.png”, ]     }, )
  • 39. Automatic Sprites 1) Configure Media bundler settings MEDIA_BUNDLES = (     {"type": "png-sprite",      "name": "icon",      "path": os.path.join(MEDIA_ROOT,"icons"),      "url": "../icons/",      "css_file": os.path.join(MEDIA_ROOT,"css","icon_sprites.css"),      "files": filter(lambda x: x[-4:]== '.png',                          os.listdir(os.path.join(MEDIA_ROOT,"icons")))     }, )
  • 40. Automatic Sprites 2) Bundle our media python manage.py bundle_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…
  • 41. <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 Sprites 4) We can then show icons using css Hello Evan
  • 42. Automatic Sprites 5) We can easily write template tags to make this easier #front_end_tags.py from django import template register = 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> 6) Now it’s a bit easier to develop <div> {% icon "user" %} Hello Evan</div>
  • 43. Automation Fabric Deploy Script from fabric.api import * defcdn_deploy(): run('python manage.py bundle_media') run('python manage.py collectstatic --noinput') run('python manage.py compress') fab cdn_deploy
  • 44. 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/
  • 45. Questions? Evan Reiser evan@adstack.com

Notes de l'éditeur

  1. How does this relate to Continuous Integration?
  2. I’ve worked on a broad range of startups and I’ve w
  3. We need this custom storage backend so that it writes both locally and pushes it to S3. I think its local because it will then check to see if it exists on disk and if so it will assume it exists on the CDN
  4. You can have your system compress these things on the fly, but I imagine in most cases you actually want it to compress all your media as part of your deploy process