Introducing Assetic: Asset Management for PHP 5.3
Upcoming SlideShare
Loading in...5
×
 

Introducing Assetic: Asset Management for PHP 5.3

on

  • 60,306 views

The performance of your application depends heavily on the number and size of assets on each page. Even your blazingly fastest Symfony2 application can be bogged down by bloated Javascript and CSS ...

The performance of your application depends heavily on the number and size of assets on each page. Even your blazingly fastest Symfony2 application can be bogged down by bloated Javascript and CSS files. This session will give you a basic introduction to PHP's new asset management framework, Assetic, and explore how it integrates with Symfony2 for a pleasant, common sense developer experience.

Statistics

Views

Total Views
60,306
Views on SlideShare
48,692
Embed Views
11,614

Actions

Likes
79
Downloads
434
Comments
1

67 Embeds 11,614

http://www.willdurand.fr 5558
http://willdurand.fr 2544
http://devtime.blogspot.com 1748
http://www.symfony-project.org 263
http://swik.net 212
http://symfony-gu.ru 145
http://blogdwich.fr 138
http://www.symfony.es 123
http://gpupo.com 119
http://symfony.com 102
http://www.sfexception.com 86
http://pocky.github.com 69
http://devtime.blogspot.fr 57
http://devtime.blogspot.ru 44
http://devtime.blogspot.de 35
http://test.ical.ly 32
http://devtime.blogspot.it 21
http://devtime.blogspot.co.uk 21
https://twitter.com 21
http://devtime.blogspot.in 21
http://devtime.blogspot.com.br 21
http://devtime.blogspot.ca 15
http://devtime.blogspot.com.ar 15
http://innowo.localhost 14
http://translate.googleusercontent.com 14
http://devtime.blogspot.com.es 14
http://feeds.feedburner.com 13
http://rimzy.net 11
http://static.slidesharecdn.com 11
http://paper.li 10
http://devtime.blogspot.nl 8
http://devtime.blogspot.se 7
http://pocky.github.io 7
https://si0.twimg.com 7
http://devtime.blogspot.jp 7
http://www.testically.org 7
http://devtime.blogspot.hu 6
http://devtime.blogspot.cz 6
http://devtime.blogspot.co.il 6
http://devtime.blogspot.com.au 5
http://webcache.googleusercontent.com 4
http://devtime.blogspot.be 4
http://devtime.blogspot.mx 4
http://devtime.blogspot.pt 4
http://a0.twimg.com 4
http://devtime.blogspot.co.at 3
http://devtime.blogspot.tw 2
http://twitter.com 2
http://devtime.blogspot.ch 2
http://ranksit.com 2
More...

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

Introducing Assetic: Asset Management for PHP 5.3 Introducing Assetic: Asset Management for PHP 5.3 Presentation Transcript

  • Introducing Assetic Asset Management for PHP 5.3 Kris Wallsmith February 9, 2011
  • @kriswallsmith• Symfony core team member• Doctrine contributor• Symfony Guru at• 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.
  • ShopOpenSky.com• PHP 5.3 + Symfony2• MongoDB + Doctrine MongoDB ODM• MySQL + Doctrine2 ORM• Less CSS• jQuery
  • Agenda• Strawman• The code• Twig Integration• Symfony2 Integration
  • Symfony2 is FAST
  • But you can still f*** that up
  • We build tools thatencourage 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 • LESS• Compass Framework • Packer• CSSEmbed • SASS• Google Closure Compiler • Sprockets• JSMin • YUI Compressor
  • The ones written in PHP…
  • This is a difficult problem
  • Assetic makes it easy
  • Are you ready tokick some Assetic!?!
  • # /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();merged asset: less data over the wire Compress theheader(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
  • Filters act on asset 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 AssetCollection( array(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 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 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• StringAsset
  • Core Filter Classes• CallablesFilter • SassSassFilter• CoffeeScriptFilter • SassScssFilter• CssRewriteFilter • SprocketsFilter• GoogleClosureCompilerApiFilter • YuiCssCompressorFilter• GoogleClosureCompilerJarFilter • YuiJsCompressorFilter• LessFilter • More to come…
  • 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
  • # /path/to/asset_factory.php$fm = new FilterManager();$fm->set(coffee, new CoffeeScriptFilter());$fm->set(closure, new GoogleClosureCompilerApi());$factory = new AssetFactory(/path/to/web);$factory->setAssetManager($am);$factory->setFilterManager($fm);
  • include /path/to/asset_factory.php;$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 omission in debug mode
  • // new AssetFactory(/path/to/web, true);include /path/to/asset_factory.php;$asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, closure));header(Content-Type: text/javascript);echo $asset->dump();
  • // new AssetFactory(/path/to/web, true);include /path/to/asset_factory.php;$asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, ?closure));header(Content-Type: text/javascript);echo $asset->dump();
  • // new AssetFactory(/path/to/web, false);include /path/to/asset_factory.php;$asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, ?closure), array(debug => true));header(Content-Type: text/javascript);echo $asset->dump();
  • Factory Workers
  • Everything passes through the workers’ hands
  • $worker = new EnsureFilterWorker( /.css$/, // the output pattern $fm->get(yui_css), // the filter false // the debug mode);$factory = new AssetFactory(/path/to/web);$factory->addWorker($worker);// compressed$factory->createAsset(css/sass/*, sass, array( output => css,));
  • $worker = new EnsureFilterWorker( /.css$/, // the output pattern $fm->get(yui_css), // the filter false // the debug mode);$factory = new AssetFactory(/path/to/web);$factory->addWorker($worker);// uncompressed$factory->createAsset(css/sass/*, sass, array( output => css, debug => true,));
  • Not Lazy Enough?
  • Asset Formulae and the Lazy Asset Manager
  • $asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, ?closure), array(output => js));
  • $formula = array( array(js/src/*.coffee), array(coffee, ?closure), array(output => js));
  • $am = new LazyAssetManager($factory);$am->setFormula(core_js, $formula);header(Content-Type: text/javascript);echo $am->get(core_js)->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
  • # /path/to/web/js/core.php$mtime = gmdate($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/scripts/dump_assets.php$am = new AssetManager();$am->set(foo, $foo);// etc...$writer = new AssetWriter(/path/to/web);$writer->writeManagerAssets($am);
  • # /path/to/scripts/dump_assets.php$am = new AssetManager();$am->set(foo, $foo);// etc...$writer = new AssetWriter(/path/to/web);foreach (array_slice($argv, 1) as $name) { $writer->writeAsset($am->get($name));}
  • Best-est:Content Distribution Network
  • new AssetWriter(s3://my-bucket) A CloudFront S3 bucket
  • Twig Integration
  • $twig->addExtension(new AsseticExtension($factory));
  • {% assetic js/*.coffee, filter=coffee %}<script src="{{ asset_url }}"></script>{% endassetic %}
  • <script src="assets/92429d8"></script>
  • {% assetic js/*.coffee, filter=coffee %}<script src="{{ asset_url }}"></script>{% endassetic %}
  • {% assetic js/*.coffee, filter=coffee, output=js %}<script src="{{ asset_url }}"></script>{% endassetic %}
  • <script src="js/92429d8.js"></script>
  • {% assetic js/*.coffee, filter=coffee, output=js %}<script src="{{ asset_url }}"></script>{% endassetic %}
  • {% assetic js/*.coffee, filter=coffee,?closure, output=js, name=core_js %}<script src="{{ asset_url }}"></script>{% endassetic %}
  • Formula LoaderUses the Twig parser to extract asset formulae from templates
  • $loader = new FormulaLoader($twig);// loop through your templates$formulae = array();foreach ($templates as $template) { $formulae += $loader->load($template);}$am = new LazyAssetManager($factory);$am->addFormulae($formulae);
  • if (!file_exists($cache = /path/to/formulae.php)) { $loader = new FormulaLoader($twig); // loop through your templates $formulae = array(); foreach ($templates as $template) { $formulae += $loader->load($template); } file_put_contents($cache, <?php return .var_export($formulae, true));}$am = new LazyAssetManager($factory);$am->addFormulae(require $cache);
  • AsseticBundle
  • {% assetic filter=scss,?yui_css, output=css/all.css, @MainBundle/Resources/sass/main.scss, @AnotherBundle/Resources/sass/more.scss %}<link href="{{ asset_url }}" rel="stylesheet" />{% endassetic %}
  • <link href="css/all.css" rel="stylesheet" />
  • {% assetic filter=scss,?yui_css, output=css/all.css, @MainBundle/Resources/sass/main.scss, @AnotherBundle/Resources/sass/more.scss %}<link href="{{ asset_url }}" rel="stylesheet" />{% endassetic %}
  • {% assetic filter=scss,?yui_css, output=css/all.css, @MainBundle/Resources/sass/main.scss, debug=true, @AnotherBundle/Resources/sass/more.scss %}<link href="{{ asset_url }}" rel="stylesheet" />{% endassetic %}
  • Each "leaf" asset is referenced individually<link href="css/all_part1.css" rel="stylesheet" /><link href="css/all_part2.css" rel="stylesheet" />
  • Configuration
  • assetic.config: debug: %kernel.debug% use_controller: %kernel.debug% document_root: %kernel.root_dir%/../web
  • {# when use_controller=true #}<script src="{{ path(route, { name: core_js }) }}"...
  • # routing_dev.yml_assetic: resource: . type: assetic
  • {# when use_controller=false #}<script src="{{ asset(js/core.js) }}"></script> Lots for free
  • The Symfony2 Assets Helper• Multiple asset domains• Cache buster
  • app.config: 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
  • {% assetic filter=scss,?yui_css, output=css/all.css, @MainBundle/Resources/sass/main.scss, @AnotherBundle/Resources/sass/more.scss %}<link href="{{ asset_url }}" rel="stylesheet" />{% endassetic %}
  • <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 Register a stream wrapper in boot()
  • PHP templates Coming soon…
  • <?php foreach ($view[assetic]->urls( array(@MainBundle/Resources/sass/main.scss, @AnotherBundle/Resources/sass/more.scss), array(scss, ?yui_css), array(output => css/all.css)) as $url): ?> <link href="<?php echo $url ?>" rel="stylesheet" /><?php endforeach; ?>
  • Fork me!http://github.com/kriswallsmith/symfony-sandbox
  • What’s Next?• Finish Symfony2 helpers for PHP templates• Filter configuration• Image sprites, embedded image data• --watch commands• Client-aware optimizations?• Better CDN integration
  • Assetic is a killer feature of Symfony2…
  • …but is only one month old, so be nice :)
  • Questions?
  • Assetichttp://github.com/kriswallsmith/assetic