Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Introducing AsseticAsset Management for PHP 5.3Kris Wallsmith (OpenSky)July 29, 2011
@kriswallsmith•   Symfony Guru at•   Symfony core team member•   Doctrine contributor•   Author of Assetic•   10+ years ex...
OpenSky connects you with innovators,trendsetters and tastemakers.You choose   the ones you like and each week they  invit...
OpenSky connects you with innovators,trendsetters and tastemakers.You choose   the ones you like and each week they  invit...
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 (...
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:
Lots of awesome tools:•   CoffeeScript              •   OptiPNG•   Compass Framework         •   Packager•   CSSEmbed     ...
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 ...
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);ec...
# /path/to/web/js/core.php$core = new AssetCollection(array(    new FileAsset(/path/to/jquery.js),    new GlobAsset(/path/...
# /path/to/web/js/core.php$core = new AssetCollection(array(    new FileAsset(/path/to/jquery.js),    new GlobAsset(/path/...
# /path/to/web/js/core.php$core = new AssetCollection(array(    new FileAsset(/path/to/jquery.js),    new GlobAsset(/path/...
# /path/to/web/js/core.php$core = new AssetCollection(array(    new FileAsset(/path/to/jquery.js),    new GlobAsset(/path/...
<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
Asset
FilterAsset
FilterFilterAsset
Load   Filter   Filter   Asset
FilterFilterAsset         Dump
FilterFilterAsset
Asset CollectionFilter              FilterFilter              FilterAsset               Asset
Asset Collection   Filter                                 Filter     Asset Collection            AssetFilter              ...
# /path/to/web/css/styles.php$styles = new FileAsset(/path/to/main.sass, array(    new SassFilter(),));header(Content-Type...
# /path/to/web/css/styles.php$styles = new AssetCollection(array(    new FileAsset(/path/to/main.sass, array(        new S...
# /path/to/web/css/styles.php$styles = new AssetCollection(array(    new FileAsset(/path/to/main.sass, array(        new S...
# /path/to/web/css/styles.php$styles = new AssetCollection(array(    new FileAsset(/path/to/main.sass, array(          new...
Basic Asset Classes•   AssetCollection•   AssetReference•   FileAsset•   GlobAsset•   HttpAsset•   StringAsset
Core Filter Classes•   CoffeeScriptFilter                •   GoogleClosureCompilerJarFilter•   CompassFilter              ...
Core Filter Classes•   PngoutFilter                •   More to come…•   SassSassFilter•   SassScssFilter•   SprocketsFilte...
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),));
$core = new AssetCollection(array(    $jquery,    $plugin1,    $plugin2,));header(text/javascript);echo $core->dump();
jQuery will only be included once       $core = new AssetCollection(array(           $jquery,           $plugin1,         ...
Filter Manager
$yui = new YuiCompressorJs();$yui->setNomunge(true);$fm = new FilterManager();$fm->set(yui_js, $yui);
$jquery = new FileAsset(/path/to/core.js);$jquery->ensureFilter($fm->get(yui_js));$core = new AssetCollection(array(    $j...
jQuery will only be compressed once   $jquery = new FileAsset(/path/to/core.js);   $jquery->ensureFilter($fm->get(yui_js))...
Asset Factory
$fm = new FilterManager();$fm->set(coffee, new CoffeeScriptFilter());$fm->set(closure, new ClosureFilter());$factory = new...
$asset = $factory->createAsset(    array(js/src/*.coffee),    array(coffee, closure));header(Content-Type: text/javascript...
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(coffe...
// new AssetFactory(/path/to/web, true);$asset = $factory->createAsset(    array(js/src/*.coffee),    array(coffee, ?closu...
// new AssetFactory(/path/to/web, false);$asset = $factory->createAsset(    array(js/src/*.coffee),    array(coffee, ?clos...
Good: Basic Caching
# /path/to/web/css/styles.php$styles = new AssetCollection(    array(new FileAsset(/path/to/main.sass)),    array(new Sass...
# /path/to/web/css/styles.php$styles = new AssetCache(new AssetCollection(    array(new FileAsset(/path/to/main.sass)),   ...
# /path/to/web/css/styles.php$styles = new AssetCache(new AssetCollection(    array(new FileAsset(/path/to/main.sass)),   ...
Better: HTTP Caching
// $core = new AssetCache(...$mtime = gmdate(D, d M y H:i:s,    $core->getLastModified()). GMT;if ($mtime == $_SERVER[HTTP...
Best: Static Assets
# /path/to/deploy/scripts/dump_assets.php$am = new AssetManager();$am->set(foo, $foo);// etc...$writer = new AssetWriter(/...
Best-est:Content Distribution Network
new AssetWriter(s3://my-bucket)
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...
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): ?><s...
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...
$am = new LazyAssetManager($factory);$am->setLoader(php, $loader);$am->addResource($resource, php);$writer = new AssetWrit...
$am = new LazyAssetManager($factory);$am->setLoader(php, $loader);$am->addResource($resource, php);               Expensiv...
$cache = new ConfigCache(/path/to/cache);$loader = new CachedFormulaLoader(    $loader,    $cache,    $debug);
$cache = new ConfigCache(/path/to/cache);$loader = new CachedFormulaLoader(    $loader,    $cache,    $debug);    Whether ...
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>{% endjavascrip...
<script src="js/92429d8_1.js"></script><script src="js/92429d8_2.js"></script><script src="js/92429d8_3.js"></script>
Each “leaf” asset is referenced individually<script src="js/92429d8_1.js"></script><script src="js/92429d8_2.js"></script>...
AsseticBundle  Symfony2 integration
Configuration
# config.ymlassetic:    debug: %kernel.debug%    use_controller: false    filters:        coffee: ~        yui_js:        ...
{# 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>
{# when use_controller=false (config_prod.yml) #}<script src="{{ asset(js/core.js) }}"></script>                 Lots for ...
The Symfony2 Assets Helper•   Multiple asset domains•   Cache buster
framework:    templating:        assets_version: 1.2.3        assets_base_urls:            - http://assets1.domain.com    ...
{% stylesheets filter=scss,?yui_css output=css/all.css   css/src/main.scss css/src/more.scss %}<link href="{{ asset_url }}...
<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
How can you help?
How can you help?•   Join the team!
How can you help?•   Join the team!•   Documentation
How can you help?•   Join the team!•   Documentation•   Assetic needs a website
Questions?http://github.com/kriswallsmith/assetic
Assetic (OSCON)
Upcoming SlideShare
Loading in …5
×

Assetic (OSCON)

2,726 views

Published on

Published in: Technology
  • Be the first to comment

Assetic (OSCON)

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

×