Introducing Assetic  Asset Management for PHP 5.3         March 1, 2011
@kriswallsmith•   Symfony Guru at•   Symfony core team member•   Doctrine contributor•   10+ years experience with PHP and...
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...
ShopOpenSky.com•   PHP 5.3 + Symfony2•   MongoDB + Doctrine MongoDB ODM•   MySQL + Doctrine2 ORM•   Less CSS•   jQuery
Agenda•   !(straw man)•   Assetic•   Twig, Symfony2 integration
If you haven’t optimized yourfrontend, you haven’t optimized
A poorly optimized frontend     can destroy UX
…and SEOhttp://googlewebmastercentral.blogspot.com/2010/04/using-site-speed-in-web-search-ranking.html
Get your assets in line.
Asset Management
Lots of awesome tools:
Lots of awesome tools:•   CoffeeScript              •   Packer•   Compass Framework         •   SASS•   CSSEmbed          ...
The ones written in PHP…
The ones written in PHP…
This is a difficult problem
Assetic makes it easy
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
Filters act on asset 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 AssetCollection(    array(new FileAsset(/path/to/main.sass)),    array(new Sass...
# /path/to/web/css/styles.php$styles = new AssetCollection(array(    new AssetCollection(        array(new FileAsset(/path...
# /path/to/web/css/styles.php$styles = new AssetCollection(array(    new AssetCollection(        array(new FileAsset(/path...
# /path/to/web/css/styles.php$styles = new AssetCollection(array(    new AssetCollection(          array(new FileAsset(/pa...
Basic Asset Classes•   AssetCollection•   AssetReference•   FileAsset•   GlobAsset•   StringAsset
Core Filter Classes•   CallablesFilter                   •   SassScssFilter•   CoffeeScriptFilter                •   Sproc...
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
# /path/to/asset_factory.php$fm = new FilterManager();$fm->set(coffee, new CoffeeScriptFilter());$fm->set(closure, new Goo...
include /path/to/asset_factory.php;$asset = $factory->createAsset(    array(js/src/*.coffee),    array(coffee, closure));h...
Debug Mode
Debugging compressed   Javascript sucks
Mark filters for omissionin debug mode using a “?”
// new AssetFactory(/path/to/web, true);include /path/to/asset_factory.php;$asset = $factory->createAsset(    array(js/src...
// new AssetFactory(/path/to/web, true);include /path/to/asset_factory.php;$asset = $factory->createAsset(    array(js/src...
// new AssetFactory(/path/to/web, false);include /path/to/asset_factory.php;$asset = $factory->createAsset(    array(js/sr...
Factory Workers
Everything passes through the       workers’ hands
$worker = new EnsureFilterWorker(    /.css$/,         // the output pattern    $fm->get(yui_css) // the filter);$factory =...
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/scripts/dump_assets.php$am = new AssetManager();$am->set(foo, $foo);// etc...$writer = new AssetWriter(/path/to...
Best-est:Content Distribution Network
new AssetWriter(s3://my-bucket)
new AssetWriter(s3://my-bucket)                 A CloudFront S3 bucket
Not Lazy Enough?
Asset Formulae and the Lazy Asset Manager
$asset = $factory->createAsset(    array(js/src/*.coffee),    array(coffee, ?closure),    array(output => js/*.js));
$formula = array(    array(js/src/*.coffee),    array(coffee, ?closure),    array(output => js/*.js));
$am = new LazyAssetManager($factory);$am->setFormula(core_js, $formula);header(Content-Type: text/javascript);echo $am->ge...
This will make more sense    in a few minutes…
Thought…Assets 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...
# config/assetic.phprequire_once /path/to/assetic/functions.php;assetic_init($factory);
Issue…Assets defined in the view layermust actually exist somewhere
Option Bad...Lazily dump assets to the      web directory
Option Good…Eagerly dump assets to the      web directory
Formula Loaders
$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);
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/*.js %}<script src="{{ asset_url }}"></script>{% endassetic %}
<script src="js/92429d8.js"></script>
{% assetic js/*.coffee, filter=coffee,   output=js/*.js %}<script src="{{ asset_url }}"></script>{% endassetic %}
{% assetic js/*.coffee, filter=coffee,?closure,   output=js/*.js, name=core_js %}<script src="{{ asset_url }}"></script>{%...
AsseticBundle  Symfony2 integration
{% assetic filter=scss,?yui_css, output=css/all.css,   @MainBundle/Resources/sass/main.scss,   @AnotherBundle/Resources/sa...
<link href="css/all.css" rel="stylesheet" />
{% assetic filter=scss,?yui_css, output=css/all.css,   @MainBundle/Resources/sass/main.scss,   @AnotherBundle/Resources/sa...
{% assetic filter=scss,?yui_css, output=css/all.css,   @MainBundle/Resources/sass/main.scss, debug=true,   @AnotherBundle/...
<link href="css/all_part1.css" rel="stylesheet" /><link href="css/all_part2.css" rel="stylesheet" />
Each "leaf" asset is referenced individually<link href="css/all_part1.css" rel="stylesheet" /><link href="css/all_part2.cs...
Configuration
assetic:    debug:            %kernel.debug%    use_controller:   %kernel.debug%    read_from:        %kernel.root_dir%/.....
{# when use_controller=true #}<script src="{{ path(assetic_foo) }}"...
# routing_dev.yml_assetic:    resource: .    type:     assetic
{# when use_controller=false #}<script src="{{ asset(js/core.js) }}"></script>
{# when use_controller=false #}<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    ...
{% assetic filter=scss,?yui_css, output=css/all.css,   @MainBundle/Resources/sass/main.scss,   @AnotherBundle/Resources/sa...
<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
Questions?http://github.com/kriswallsmith/assetic
Introducing Assetic (NYPHP)
Upcoming SlideShare
Loading in...5
×

Introducing Assetic (NYPHP)

7,076

Published on

Published in: Technology

Introducing Assetic (NYPHP)

  1. 1. Introducing Assetic Asset Management for PHP 5.3 March 1, 2011
  2. 2. @kriswallsmith• Symfony Guru at• Symfony core team member• Doctrine contributor• 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. ShopOpenSky.com• PHP 5.3 + Symfony2• MongoDB + Doctrine MongoDB ODM• MySQL + Doctrine2 ORM• Less CSS• jQuery
  6. 6. Agenda• !(straw man)• Assetic• Twig, Symfony2 integration
  7. 7. If you haven’t optimized yourfrontend, you haven’t optimized
  8. 8. A poorly optimized frontend can destroy UX
  9. 9. …and SEOhttp://googlewebmastercentral.blogspot.com/2010/04/using-site-speed-in-web-search-ranking.html
  10. 10. Get your assets in line.
  11. 11. Asset Management
  12. 12. Lots of awesome tools:
  13. 13. Lots of awesome tools:• CoffeeScript • Packer• Compass Framework • SASS• CSSEmbed • Sprockets• Google Closure Compiler • Stylus• JSMin • YUI Compressor• LESS
  14. 14. The ones written in PHP…
  15. 15. The ones written in PHP…
  16. 16. This is a difficult problem
  17. 17. Assetic makes it easy
  18. 18. Enough talk
  19. 19. # /path/to/web/js/core.php$core = new FileAsset(/path/to/jquery.js);$core->load();header(Content-Type: text/javascript);echo $core->dump();
  20. 20. # /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();
  21. 21. # /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();
  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),), array( new YuiCompressorJsFilter(/path/to/yui.jar),));$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),), 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();
  24. 24. <script src="js/core.php"></script>
  25. 25. Assetic isAssets & Filters
  26. 26. Inspired by Python’s webassets https://github.com/miracle2k/webassets
  27. 27. Assets have lazy, mutable content
  28. 28. Filters act on asset contents during “load” and “dump”
  29. 29. Assets can be gathered in collections
  30. 30. A collection is an asset
  31. 31. Asset
  32. 32. FilterAsset
  33. 33. FilterFilterAsset
  34. 34. Load Filter Filter Asset
  35. 35. FilterFilterAsset Dump
  36. 36. FilterFilterAsset
  37. 37. Asset CollectionFilter FilterFilter FilterAsset Asset
  38. 38. Asset Collection Filter Filter Asset Collection AssetFilter FilterFilter FilterAsset Asset Filter Filter Asset
  39. 39. # /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();
  40. 40. # /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();
  41. 41. # /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),));header(Content-Type: text/css);echo $styles->dump();
  42. 42. # /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();
  43. 43. Basic Asset Classes• AssetCollection• AssetReference• FileAsset• GlobAsset• StringAsset
  44. 44. Core Filter Classes• CallablesFilter • SassScssFilter• CoffeeScriptFilter • SprocketsFilter• CssRewriteFilter • StylusFilter• GoogleClosureCompilerApiFilter • YuiCssCompressorFilter• GoogleClosureCompilerJarFilter • YuiJsCompressorFilter• LessFilter • More to come…• SassSassFilter
  45. 45. Asset Manager
  46. 46. $am = new AssetManager();$am->set(jquery, new FileAsset(/path/to/jquery.js));
  47. 47. $plugin = new AssetCollection(array( new AssetReference($am, jquery), new FileAsset(/path/to/jquery.plugin.js),));
  48. 48. $core = new AssetCollection(array( $jquery, $plugin1, $plugin2,));header(text/javascript);echo $core->dump();
  49. 49. jQuery will only be included once $core = new AssetCollection(array( $jquery, $plugin1, $plugin2, )); header(text/javascript); echo $core->dump();
  50. 50. Filter Manager
  51. 51. $yui = new YuiCompressorJs();$yui->setNomunge(true);$fm = new FilterManager();$fm->set(yui_js, $yui);
  52. 52. $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));
  53. 53. 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));
  54. 54. Asset Factory
  55. 55. # /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->setFilterManager($fm);
  56. 56. include /path/to/asset_factory.php;$asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, closure));header(Content-Type: text/javascript);echo $asset->dump();
  57. 57. Debug Mode
  58. 58. Debugging compressed Javascript sucks
  59. 59. Mark filters for omissionin debug mode using a “?”
  60. 60. // 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();
  61. 61. // 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();
  62. 62. // 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();
  63. 63. Factory Workers
  64. 64. Everything passes through the workers’ hands
  65. 65. $worker = new EnsureFilterWorker( /.css$/, // the output pattern $fm->get(yui_css) // the filter);$factory = new AssetFactory(/path/to/web);$factory->addWorker($worker);// compressed$factory->createAsset(css/sass/*, sass, array( output => css/*.css,));
  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/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. Not Lazy Enough?
  78. 78. Asset Formulae and the Lazy Asset Manager
  79. 79. $asset = $factory->createAsset( array(js/src/*.coffee), array(coffee, ?closure), array(output => js/*.js));
  80. 80. $formula = array( array(js/src/*.coffee), array(coffee, ?closure), array(output => js/*.js));
  81. 81. $am = new LazyAssetManager($factory);$am->setFormula(core_js, $formula);header(Content-Type: text/javascript);echo $am->get(core_js)->dump();
  82. 82. This will make more sense in a few minutes…
  83. 83. Thought…Assets 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. # config/assetic.phprequire_once /path/to/assetic/functions.php;assetic_init($factory);
  86. 86. Issue…Assets defined in the view layermust actually exist somewhere
  87. 87. Option Bad...Lazily dump assets to the web directory
  88. 88. Option Good…Eagerly dump assets to the web directory
  89. 89. Formula Loaders
  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. Twig Integration
  95. 95. $twig->addExtension(new AsseticExtension($factory));
  96. 96. {% assetic js/*.coffee, filter=coffee %}<script src="{{ asset_url }}"></script>{% endassetic %}
  97. 97. <script src="assets/92429d8"></script>
  98. 98. {% assetic js/*.coffee, filter=coffee %}<script src="{{ asset_url }}"></script>{% endassetic %}
  99. 99. {% assetic js/*.coffee, filter=coffee, output=js/*.js %}<script src="{{ asset_url }}"></script>{% endassetic %}
  100. 100. <script src="js/92429d8.js"></script>
  101. 101. {% assetic js/*.coffee, filter=coffee, output=js/*.js %}<script src="{{ asset_url }}"></script>{% endassetic %}
  102. 102. {% assetic js/*.coffee, filter=coffee,?closure, output=js/*.js, name=core_js %}<script src="{{ asset_url }}"></script>{% endassetic %}
  103. 103. AsseticBundle Symfony2 integration
  104. 104. {% 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 %}
  105. 105. <link href="css/all.css" rel="stylesheet" />
  106. 106. {% 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 %}
  107. 107. {% 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 %}
  108. 108. <link href="css/all_part1.css" rel="stylesheet" /><link href="css/all_part2.css" rel="stylesheet" />
  109. 109. Each "leaf" asset is referenced individually<link href="css/all_part1.css" rel="stylesheet" /><link href="css/all_part2.css" rel="stylesheet" />
  110. 110. Configuration
  111. 111. assetic: debug: %kernel.debug% use_controller: %kernel.debug% read_from: %kernel.root_dir%/../web write_to: s3://mybucket
  112. 112. {# when use_controller=true #}<script src="{{ path(assetic_foo) }}"...
  113. 113. # routing_dev.yml_assetic: resource: . type: assetic
  114. 114. {# when use_controller=false #}<script src="{{ asset(js/core.js) }}"></script>
  115. 115. {# when use_controller=false #}<script src="{{ asset(js/core.js) }}"></script> Lots for free
  116. 116. The Symfony2 Assets Helper• Multiple asset domains• Cache buster
  117. 117. 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
  118. 118. {% 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 %}
  119. 119. <link href="http://assets3.domain.com/css/all.css?1.2.3" ...
  120. 120. assetic:dump
  121. 121. $ php app/console assetic:dump web/
  122. 122. $ php app/console assetic:dump s3://my-bucket
  123. 123. assetic:dump --watch Dump static assets in the background as you develop
  124. 124. Questions?http://github.com/kriswallsmith/assetic
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×