Your SlideShare is downloading. ×
0
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Assetic (OSCON)
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Assetic (OSCON)

2,133

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,133
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
19
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  1. Introducing AsseticAsset Management for PHP 5.3Kris Wallsmith (OpenSky)July 29, 2011
  2. @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
  3. 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.
  4. 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.
  5. opensky.com• PHP 5.3 + Symfony2• MongoDB + Doctrine MongoDB ODM• MySQL + Doctrine2 ORM• Less CSS• jQuery
  6. We all want to be FAST
  7. We use good open source tools that encourage best practices
  8. 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
  9. If you haven’t optimized yourfrontend, you haven’t optimized
  10. Get your assets in line.
  11. A poorly optimized frontend can destroy UX
  12. …and SEO!http://googlewebmastercentral.blogspot.com/2010/04/using-site-speed-in-web-search-ranking.html
  13. Asset Management
  14. Lots of awesome tools:
  15. Lots of awesome tools:• CoffeeScript • OptiPNG• Compass Framework • Packager• CSSEmbed • SASS & SCSS• Google Closure Compiler • Sprockets• jpegoptim • Stylus• JSMin • YUI Compressor• LESS
  16. Integrating these tools cleanly is a difficult problem
  17. Assetic makes it easy
  18. 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
  19. No B.S.
  20. Enough talk
  21. # /path/to/web/js/core.php$core = new FileAsset(/path/to/jquery.js);$core->load();header(Content-Type: text/javascript);echo $core->dump();
  22. # /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();header(Content-Type: text/javascript);echo $core->dump();
  23. # /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();
  24. # /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();header(Content-Type: text/javascript);echo $core->dump();
  25. # /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();
  26. <script src="js/core.php"></script>
  27. Assetic isAssets & Filters
  28. Inspired by Python’s webassets https://github.com/miracle2k/webassets
  29. Assets have lazy, mutable content
  30. A filter acts on an asset’s contents during “load” and “dump”
  31. Assets can be gathered in collections
  32. A collection is an asset
  33. Asset
  34. FilterAsset
  35. FilterFilterAsset
  36. Load Filter Filter Asset
  37. FilterFilterAsset Dump
  38. FilterFilterAsset
  39. Asset CollectionFilter FilterFilter FilterAsset Asset
  40. Asset Collection Filter Filter Asset Collection AssetFilter FilterFilter FilterAsset Asset Filter Filter Asset
  41. # /path/to/web/css/styles.php$styles = new FileAsset(/path/to/main.sass, array( new SassFilter(),));header(Content-Type: text/css);echo $styles->dump();
  42. # /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();
  43. # /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),));header(Content-Type: text/css);echo $styles->dump();
  44. # /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();
  45. Basic Asset Classes• AssetCollection• AssetReference• FileAsset• GlobAsset• HttpAsset• StringAsset
  46. Core Filter Classes• CoffeeScriptFilter • GoogleClosureCompilerJarFilter• CompassFilter • JpegoptimFilter• CssEmbedFilter • JpegtranFilter• CssImportFilter • LessFilter• CssMinFilter • LessphpFilter• CssRewriteFilter • OptiPngFilter• GoogleClosureCompilerApiFilter • PackagerFilter
  47. Core Filter Classes• PngoutFilter • More to come…• SassSassFilter• SassScssFilter• SprocketsFilter• StylusFilter• YuiCssCompressorFilter• YuiJsCompressorFilter
  48. Asset Manager
  49. $am = new AssetManager();$am->set(jquery, new FileAsset(/path/to/jquery.js));
  50. $plugin = new AssetCollection(array( new AssetReference($am, jquery), new FileAsset(/path/to/jquery.plugin.js),));
  51. $core = new AssetCollection(array( $jquery, $plugin1, $plugin2,));header(text/javascript);echo $core->dump();
  52. jQuery will only be included once $core = new AssetCollection(array( $jquery, $plugin1, $plugin2, )); header(text/javascript); echo $core->dump();
  53. Filter Manager
  54. $yui = new YuiCompressorJs();$yui->setNomunge(true);$fm = new FilterManager();$fm->set(yui_js, $yui);
  55. $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));
  56. 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));
  57. Asset Factory
  58. $fm = new FilterManager();$fm->set(coffee, new CoffeeScriptFilter());$fm->set(closure, new ClosureFilter());$factory = new AssetFactory(/path/to/web);$factory->setFilterManager($fm);
  59. $asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, closure));header(Content-Type: text/javascript);echo $asset->dump();
  60. Debug Mode
  61. Debugging compressed Javascript sucks
  62. Mark filters for omissionin debug mode using a “?”
  63. // 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();
  64. // new AssetFactory(/path/to/web, true);$asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, ?closure));header(Content-Type: text/javascript);echo $asset->dump();
  65. // 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();
  66. Good: Basic Caching
  67. # /path/to/web/css/styles.php$styles = new AssetCollection( array(new FileAsset(/path/to/main.sass)), array(new SassFilter()));echo $styles->dump();
  68. # /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));echo $styles->dump();
  69. # /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();
  70. Better: HTTP Caching
  71. // $core = new AssetCache(...$mtime = gmdate(D, d M y H:i:s, $core->getLastModified()). GMT;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();
  72. Best: Static Assets
  73. # /path/to/deploy/scripts/dump_assets.php$am = new AssetManager();$am->set(foo, $foo);// etc...$writer = new AssetWriter(/path/to/web);$writer->writeManagerAssets($am);
  74. Best-est:Content Distribution Network
  75. new AssetWriter(s3://my-bucket)
  76. new AssetWriter(s3://my-bucket) A CloudFront S3 bucket
  77. Custom Stream Wrappers$s3 = new Zend_Service_Amazon_S3($key, $secret);$s3->registerStreamWrapper();
  78. Not Lazy Enough?
  79. Asset Formulae and the Lazy Asset Manager
  80. $asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, ?closure), array(output => js/all.js));
  81. $formula = array( array(js/src/*.coffee), array(coffee, ?closure), array(output => js/all.js));
  82. $am = new LazyAssetManager($factory);$am->setFormula(all_js, $formula);header(Content-Type: text/javascript);echo $am->get(all_js)->dump();
  83. A ThoughtAssets are a part of the view layer and should be defined there.
  84. <!-- 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; ?>
  85. An IssueAssets defined in the view layermust actually exist somewhere
  86. Option Number BadLazily dump assets to the web directory
  87. Option Number GoodEagerly dump assets to the web directory
  88. A template is a configuration file
  89. Formula Loadersextract asset formulae from templates
  90. $loader = new FunctionCallsFormulaLoader();$resource = new DirectoryResource( /path/to/templates, /.php$/);$formulae = $loader->load($resource);
  91. $am = new LazyAssetManager($factory);$am->setLoader(php, $loader);$am->addResource($resource, php);$writer = new AssetWriter(/path/to/web);$writer->writeManagerAssets($am);
  92. $am = new LazyAssetManager($factory);$am->setLoader(php, $loader);$am->addResource($resource, php); Expensive every time$writer = new AssetWriter(/path/to/web);$writer->writeManagerAssets($am);
  93. $cache = new ConfigCache(/path/to/cache);$loader = new CachedFormulaLoader( $loader, $cache, $debug);
  94. $cache = new ConfigCache(/path/to/cache);$loader = new CachedFormulaLoader( $loader, $cache, $debug); Whether to stat each file for changes
  95. Twig Integration
  96. {% javascripts js/*.coffee filter=coffee %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
  97. <script src="js/92429d8.js"></script>
  98. {% javascripts js/*.coffee filter=coffee %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
  99. {% javascripts js/*.coffee filter=coffee output=js/all.js %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
  100. <script src="js/all.js"></script>
  101. {% javascripts js/*.coffee filter=coffee output=js/all.js %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
  102. {% javascripts js/*.coffee filter=coffee,?closure %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
  103. {% javascripts js/*.coffee filter=coffee,?closure debug=true %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
  104. {% javascripts js/*.coffee filter=coffee,?closure combine=false %}<script src="{{ asset_url }}"></script>{% endjavascripts %}
  105. <script src="js/92429d8_1.js"></script><script src="js/92429d8_2.js"></script><script src="js/92429d8_3.js"></script>
  106. 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>
  107. AsseticBundle Symfony2 integration
  108. Configuration
  109. # config.ymlassetic: debug: %kernel.debug% use_controller: false filters: coffee: ~ yui_js: jar: /path/to/yuicompressor.jar
  110. {# when use_controller=true (config_dev.yml) #}<script src="{{ path(assetic_foo) }}"...
  111. # routing_dev.yml_assetic: resource: . type: assetic
  112. {# when use_controller=false (config_prod.yml) #}<script src="{{ asset(js/core.js) }}"></script>
  113. {# when use_controller=false (config_prod.yml) #}<script src="{{ asset(js/core.js) }}"></script> Lots for free
  114. The Symfony2 Assets Helper• Multiple asset domains• Cache buster
  115. 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
  116. {% stylesheets filter=scss,?yui_css output=css/all.css css/src/main.scss css/src/more.scss %}<link href="{{ asset_url }}" rel="stylesheet">{% endstylesheets %}
  117. <link href="http://assets3.domain.com/css/all.css?1.2.3" ...
  118. assetic:dump
  119. $ php app/console assetic:dump web/
  120. $ php app/console assetic:dump s3://my-bucket
  121. assetic:dump --watch Dump static assets in the background as you develop
  122. How can you help?
  123. How can you help?• Join the team!
  124. How can you help?• Join the team!• Documentation
  125. How can you help?• Join the team!• Documentation• Assetic needs a website
  126. Questions?http://github.com/kriswallsmith/assetic

×