Fanstatic
Was es kann (und können sollte?)
Ich

• Daniel Havlik
• Mitinhaber und Entwickler bei gocept gmbh
  & co. kg
• Python seit 2002, hauptsächlich im Web-
  Umfeld
Fanstatic

• https://bitbucket.org/fanstatic
• hurry.resource; zc.resourcelibrary
• Martijn Faassen, Jan-Jaap Driessen
Inhalt

• Einführung
• Features
• Zukunft
Um was geht es?

• Einbinden statischer Ressourcen in
  Webapplikationen
• JS
• CSS
Welche Möglichkeiten
      gibt es?

• Ins Template schreiben
• Plone…
• an der *richtigen* Stelle!
zum Beispiel
class DateTimeWidgetView(object):
    def render(self):
        my.datetimewidget.resource.widget_js.need()
        return self.template()



• need()
• Wie kommt das jetzt ins HTML?
• „Injector“:
 • Einsammeln aller „needed Resources“
 • Injizieren in HTML
 • WSGI-Middleware, diverse
    Konfigurationsoptionen
Libraries
lib = fanstatic.Library('my.dtw', 'resources')




• -> http://host/static/my.dtw/foo.js
• -> my.dtw/src/my/dtw/resources/foo.js
Ressourcen
• resource.py
    widget_js = fanstatic.Resource(
        lib,
        'foo.js',
        minified='foo.min.js',
        depends=[js.jquery, widget_css])
Features
• Bundling
• Gruppierung
• Renderer
• Versioning
• Slots
• minifizierte Resourcen
Bundling


• Ausliefern mehrerer Resourcen in einem
  Request
• Ein Bundle pro Library & Verzeichnis
Gruppierung

jquery = fanstatic.Group([
    js.jquery,
    js.jquery.jqueryui,
    my_magic_jquery_patch])
Renderer
   <script src="/static/my.lib/script.js" type="text/javascript" />



<link href="/static/my.lib/style.css" rel="stylesheet" type="text/css" />
custom Renderer
def lte_ie8_renderer(url):
    inner = fanstatic.core.render_css(url)
    return "<!--[if lte IE 8]>%s<![endif]-->" % inner


iehacks_css = fanstatic.Resource(
    lib, 'css/iehacks.css',
    renderer=lte_ie8_renderer)
custom Renderer 2
 def media_print(url):
     return ('<link href="%s" rel="stylesheet"'
             '      type="text/css" media="print"/>') % url


 print_styles = fanstatic.Resource(
     lib, 'css/print.css',
     renderer=media_print)




(…oder einfach @media print {})
Versioning
• Problem: Auf (Browser)cache ist kein
  Verlass.
• Versions-Identifier in der URL
• „Cache forever“
<script src="/static/my.lib:version:<HASH>/script.js"
        type="text/javascript" />
Slots
• Resource, die zur Laufzeit / in der
  Applikationslogik befüllt wird.

      templating = fanstatic.Slot(
          lib, '.js', required=True)

      framework = fanstatic.Resource(
          lib, 'fancy_framework.js',
          depends=[templating])
Slots
framework.need(dict(templating=js.pure))

framework.need(dict(templating=js.ejs))

framework.need()

"SlotError: slot <fanstatic.core.Slot object at …> was
required but not filled in"
minifizierte Resourcen

• müssen angegeben werden
• Fallstrick: jsmin vergessen
• Test hilft (manchmal)!
Zukunft

• Preprocessing
• Slot mit default
• (Python 3)
Preprocessing

• Anwendungsideen
 • CoffeeScript
 • SCSS/LessCSS
 • jsmin
Preprocessing

• Wo soll das Processing stattfinden?
 • Release
 • Build
 • Laufzeit
Preprocessing

• Release:
 • + Konverter nicht notwendig für
    „Anwender“
 • - Für Entwickler nicht machbar
Preprocessing

• Build
 • - „Anwender“ braucht Konverter (pip)
 • +/-0 Code-Änderungen erst nach rebuild
    nutzbar.
Preprocessing

• Laufzeit
 • + Änderungen werden sofort wirksam
 • - Caching, Last
Slot mit default


• Für required slots, wenn beim need keine
  Resource angegeben wird.
Python 3

• noch warm
Vielen Dank!


• Sprint, Freitag und Samstag vormittag.
• Fragen?

Fanstatic pycon.de 2012