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

Like this? Share it with your network

Share

Assetic (OSCON)

on

  • 2,482 views

 

Statistics

Views

Total Views
2,482
Views on SlideShare
2,432
Embed Views
50

Actions

Likes
3
Downloads
12
Comments
0

4 Embeds 50

http://lanyrd.com 33
http://twitter.com 7
https://twitter.com 6
http://tweetedtimes.com 4

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 (OSCON) Presentation 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