Assetic (Zendcon)
Upcoming SlideShare
Loading in...5
×
 

Assetic (Zendcon)

on

  • 2,404 views

My presentation of Assetic at Zendcon 2011.

My presentation of Assetic at Zendcon 2011.

Statistics

Views

Total Views
2,404
Slideshare-icon Views on SlideShare
2,402
Embed Views
2

Actions

Likes
4
Downloads
30
Comments
0

2 Embeds 2

http://a0.twimg.com 1
http://www.slashdocs.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Assetic (Zendcon) Assetic (Zendcon) Presentation Transcript

    • Introducing Assetic Asset Management for PHP 5.3 October 20, 2011
    • @kriswallsmith• Symfony Guru at• Symfony core team member• Doctrine contributor• Author of Assetic• 10+ years experience with PHP and web development• Open source evangelist and international speaker
    • OpenSky connects you with innovators,trendsetters and tastemakers.You choose the ones you like and each week they invite you to their private online sales.
    • opensky.com• PHP 5.3 + Symfony2• MongoDB + Doctrine MongoDB ODM• MySQL + Doctrine2 ORM• Less CSS• jQuery
    • We all want to be FAST
    • We use good open source tools that encourage best practices
    • Best practices like…• Dependency injection (DI)• Proper caching, edge side includes (ESI)• Test-driven development (TDD)• Dont repeat yourself (DRY)• Keep it simple, SVP (KISS)• Performance
    • If you haven’t optimized yourfrontend, you haven’t optimized
    • Get your assets in line.
    • A poorly optimized frontend can destroy UX
    • …and SEO!http://googlewebmastercentral.blogspot.com/2010/04/using-site-speed-in-web-search-ranking.html
    • Asset Management
    • Lots of awesome tools:• CoffeeScript • OptiPNG• Compass Framework • Packager• CSSEmbed • SASS & SCSS• Google Closure Compiler • Sprockets• jpegoptim • Stylus• JSMin • YUI Compressor• LESS
    • Integrating these tools cleanly is a difficult problem
    • Assetic makes it easy
    • as•cet•i•cismdescribes a lifestyle characterized by abstinence from various sorts of worldly pleasures often with the aim of pursuing religious and spiritual goals
    • No B.S.
    • Enough talk
    • # /path/to/web/js/core.php$core = new FileAsset(/path/to/jquery.js);$core->load();header(Content-Type: text/javascript);echo $core->dump();
    • # /path/to/web/js/core.php$core = new AssetCollection(array( new FileAsset(/path/to/jquery.js), new GlobAsset(/path/to/js/core/*.js),));$core->load();many files into one == fewer HTTP requests Mergeheader(Content-Type: text/javascript);echo $core->dump();
    • # /path/to/web/js/core.php$core = new AssetCollection(array( new FileAsset(/path/to/jquery.js), new GlobAsset(/path/to/js/core/*.js),), array( new YuiCompressorJsFilter(/path/to/yui.jar),));$core->load(); Compress the merged asset == less data over the wireheader(Content-Type: text/javascript);echo $core->dump();
    • <script src="js/core.php"></script>
    • Assetic isAssets & Filters
    • Inspired by Python’s webassets https://github.com/miracle2k/webassets
    • Assets have lazy, mutable content
    • A filter acts on an asset’s contents during “load” and “dump”
    • Assets can be gathered in collections
    • A collection is an asset
    • Load Filter Filter Asset Dump
    • Asset CollectionFilter FilterFilter FilterAsset Asset
    • Asset Collection Filter Filter Asset Collection AssetFilter FilterFilter FilterAsset Asset Filter Filter Asset
    • # /path/to/web/css/styles.php$styles = new FileAsset(/path/to/main.sass, array( new SassFilter(),));header(Content-Type: text/css);echo $styles->dump();
    • # /path/to/web/css/styles.php$styles = new AssetCollection(array( new FileAsset(/path/to/main.sass, array( new SassFilter(), )), new FileAsset(/path/to/more.css),));header(Content-Type: text/css);echo $styles->dump();
    • # /path/to/web/css/styles.php$styles = new AssetCollection(array( new FileAsset(/path/to/main.sass, array( new SassFilter(), )), new FileAsset(/path/to/more.css),), array( new YuiCompressorCss(/path/to/yui.jar),)); Lazy! The filesystem isnt touched until nowheader(Content-Type: text/css);echo $styles->dump();
    • Basic Asset Classes• AssetCollection• AssetReference• FileAsset• GlobAsset• HttpAsset• StringAsset
    • Core Filter Classes• CoffeeScriptFilter • GoogleClosureCompilerJarFilter• CompassFilter • JpegoptimFilter• CssEmbedFilter • JpegtranFilter• CssImportFilter • LessFilter• CssMinFilter • LessphpFilter• CssRewriteFilter • OptiPngFilter• GoogleClosureCompilerApiFilter • PackagerFilter
    • Core Filter Classes• PngoutFilter • More to come…• SassSassFilter• SassScssFilter• SprocketsFilter• StylusFilter• YuiCssCompressorFilter• YuiJsCompressorFilter
    • Asset Manager
    • $am = new AssetManager();$am->set(jquery, new FileAsset(/path/to/jquery.js));
    • $plugin = new AssetCollection(array( new AssetReference($am, jquery), new FileAsset(/path/to/jquery.plugin.js),));
    • jQuery will only be included once $core = new AssetCollection(array( $jquery, $plugin1, $plugin2, )); header(text/javascript); echo $core->dump();
    • Filter Manager
    • $yui = new YuiCompressorJs();$yui->setNomunge(true);$fm = new FilterManager();$fm->set(yui_js, $yui);
    • jQuery will only be compressed once $jquery = new FileAsset(/path/to/core.js); $jquery->ensureFilter($fm->get(yui_js)); $core = new AssetCollection(array( $jquery, new GlobAsset(/path/to/js/core/*.js), )); $core->ensureFilter($fm->get(yui_js));
    • Asset Factory
    • $fm = new FilterManager();$fm->set(coffee, new CoffeeScriptFilter());$fm->set(closure, new ClosureFilter());$factory = new AssetFactory(/path/to/web);$factory->setFilterManager($fm);
    • $asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, closure));header(Content-Type: text/javascript);echo $asset->dump();
    • Debug Mode
    • Debugging compressed Javascript sucks
    • Mark filters for omissionin debug mode using a “?”
    • // new AssetFactory(/path/to/web, $debug = true);$asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, closure));header(Content-Type: text/javascript);echo $asset->dump();
    • // new AssetFactory(/path/to/web, true);$asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, ?closure));header(Content-Type: text/javascript);echo $asset->dump();
    • // new AssetFactory(/path/to/web, false);$asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, ?closure), array(debug => true));header(Content-Type: text/javascript);echo $asset->dump();
    • Good: Basic Caching
    • # /path/to/web/css/styles.php$styles = new AssetCollection( array(new FileAsset(/path/to/main.sass)), array(new SassFilter()));echo $styles->dump();
    • # /path/to/web/css/styles.php$styles = new AssetCache(new AssetCollection( array(new FileAsset(/path/to/main.sass)), array(new SassFilter())), new FilesystemCache(/path/to/cache)); Run the filters once and cache the contentecho $styles->dump();
    • Better: HTTP Caching
    • // $core = new AssetCache(...$mtime = gmdate(D, d M y H:i:s GMT, $core->getLastModified());if ($mtime == $_SERVER[HTTP_IF_MODIFIED_SINCE]) { header(HTTP/1.0 304 Not Modified); exit();}header(Content-Type: text/javascript);header(Last-Modified: .$mtime);echo $core->dump();
    • Best: Static Assets
    • # /path/to/deploy/scripts/dump_assets.php$am = new AssetManager();$am->set(foo, $foo);// etc...$writer = new AssetWriter(/path/to/web);$writer->writeManagerAssets($am);
    • Best-est:Content Distribution Network
    • new AssetWriter(s3://my-bucket) A CloudFront S3 bucket
    • Custom Stream Wrappers$s3 = new Zend_Service_Amazon_S3($key, $secret);$s3->registerStreamWrapper();
    • Not Lazy Enough?
    • Asset Formulae and the Lazy Asset Manager
    • $asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, ?closure), array(output => js/all.js));
    • $formula = array( array(js/src/*.coffee), array(coffee, ?closure), array(output => js/all.js));
    • $am = new LazyAssetManager($factory);$am->setFormula(all_js, $formula);header(Content-Type: text/javascript);echo $am->get(all_js)->dump();
    • A ThoughtAssets are a part of the view layer and should be defined there.
    • <!-- header.php --><?php foreach (assetic_javascripts( array(js/core.js, js/more.js), array(?yui_js)) as $url): ?><script src="<?php echo $url ?>"></script><?php endforeach; ?>
    • An IssueAssets defined in the view layermust actually exist somewhere
    • Option Number BadLazily dump assets to the web directory
    • Option Number GoodEagerly dump assets to the web directory
    • A template is a configuration file
    • Formula Loadersextract asset formulae from templates
    • $loader = new FunctionCallsFormulaLoader();$resource = new DirectoryResource( /path/to/templates, /.php$/);$formulae = $loader->load($resource);
    • $am = new LazyAssetManager($factory);$am->setLoader(php, $loader);$am->addResource($resource, php); Expensive every time$writer = new AssetWriter(/path/to/web);$writer->writeManagerAssets($am);
    • $cache = new ConfigCache(/path/to/cache);$loader = new CachedFormulaLoader( $loader, $cache, $debug); Whether to stat each file for changes
    • Twig Integration
    • {% javascripts js/*.coffee filter=coffee %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
    • <script src="js/92429d8.js"></script>
    • {% javascripts js/*.coffee filter=coffee %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
    • {% javascripts js/*.coffee filter=coffee output=js/all.js %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
    • <script src="js/all.js"></script>
    • {% javascripts js/*.coffee filter=coffee output=js/all.js %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
    • {% javascripts js/*.coffee filter=coffee,?closure %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
    • {% javascripts js/*.coffee filter=coffee,?closure debug=true %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
    • {% javascripts js/*.coffee filter=coffee,?closure combine=false %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
    • Each “leaf” asset is referenced individually<script src="js/92429d8_1.js"></script><script src="js/92429d8_2.js"></script><script src="js/92429d8_3.js"></script>
    • AsseticBundle Symfony2 integration
    • Configuration
    • # config.ymlassetic: debug: %kernel.debug% use_controller: false filters: coffee: ~ yui_js: jar: /path/to/yuicompressor.jar
    • {# when use_controller=true (config_dev.yml) #}<script src="{{ path(assetic_foo) }}"...
    • # routing_dev.yml_assetic: resource: . type: assetic
    • {# when use_controller=false (config_prod.yml) #}<script src="{{ asset(js/core.js) }}"></script> Lots for free
    • The Symfony2 Assets Helper• Multiple asset domains• Cache buster
    • framework: templating: assets_version: 1.2.3 assets_base_urls: - http://assets1.domain.com - http://assets2.domain.com - http://assets3.domain.com - http://assets4.domain.com
    • {% stylesheets filter=scss,?yui_css output=css/all.css css/src/main.scss css/src/more.scss %}<link href="{{ asset_url }}" rel="stylesheet">{% endstylesheets %}
    • <link href="http://assets3.domain.com/css/all.css?1.2.3" ...
    • assetic:dump
    • $ php app/console assetic:dump web/
    • $ php app/console assetic:dump s3://my-bucket
    • assetic:dump --watch Dump static assets in the background as you develop
    • Roadmap• 1.1 - Asset dependencies• 1.2 - Dynamic assets
    • How can you help?• Fork me, join the team• Documentation• Assetic needs a website
    • OpenSky is hiring• Systems• Dev-ops• Help desk• Java architect
    • Questions?http://github.com/kriswallsmith/assetic