Skip to content

Commit 9d31454

Browse files
committed
[cookbook][assetic] Proofreading the assetic entry - very good, still a bit too theoretical in spots, but solid - it can evolve
This closes #326
1 parent 7d6d228 commit 9d31454

File tree

1 file changed

+208
-73
lines changed

1 file changed

+208
-73
lines changed

cookbook/assetic/asset_management.rst

Lines changed: 208 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
How to Use Assetic for Asset Management
22
=======================================
33

4-
Assetic is a powerful asset management library which is packaged with the
5-
Symfony2 Standard Edition and can be easily used in Symfony2 directly from
6-
Twig or PHP templates.
7-
84
Assetic combines two major ideas: assets and filters. The assets are files
9-
such as CSS, JavaScript and images files. The filters are things that can
5+
such as CSS, JavaScript and image files. The filters are things that can
106
be applied to these files before they are served to the browser. This allows
117
a separation between the asset files stored in the application and the files
128
actually presented to the user.
@@ -46,7 +42,8 @@ drawn from various sources such as from within a bundle:
4642
4743
.. code-block:: html+jinja
4844
49-
{% javascripts '@AcmeFooBundle/Resources/public/js/*'
45+
{% javascripts
46+
'@AcmeFooBundle/Resources/public/js/*'
5047
%}
5148
<script type="text/javascript" src="{{ asset_url }}"></script>
5249
{% endjavascripts %}
@@ -58,27 +55,62 @@ drawn from various sources such as from within a bundle:
5855
<script type="text/javascript" src="<?php echo $view->escape($url) ?>"></script>
5956
<?php endforeach; ?>
6057
58+
.. tip::
59+
60+
To bring in CSS stylesheets, you can use the same methodologies seen
61+
in this entry, except with the `stylesheets` tag:
62+
63+
.. configuration-block::
64+
65+
.. code-block:: html+jinja
66+
67+
{% stylesheets
68+
'@AcmeFooBundle/Resources/public/css/*'
69+
%}
70+
<link rel="stylesheet" href="{{ asset_url }}" />
71+
{% endstylesheets %}
72+
73+
.. code-block:: html+php
74+
75+
<?php foreach ($view['assetic']->stylesheets(
76+
array('@AcmeFooBundle/Resources/public/css/*')) as $url): ?>
77+
<link rel="stylesheet" href="<?php echo $view->escape($url) ?>" />
78+
<?php endforeach; ?>
79+
6180
In this example, all of the files in the ``Resources/public/js/`` directory
6281
of the ``AcmeFooBundle`` will be loaded and served from a different location.
6382
The actual rendered tag might simply look like:
6483

65-
<script src="/js/abcd123.js"></script>
84+
.. code-block:: html
85+
86+
<script src="/app_dev.php/js/abcd123.js"></script>
87+
88+
.. note::
89+
90+
This is a key point: once you let Assetic handle your assets, the files are
91+
served from a different location. This *can* cause problems with CSS files
92+
that reference images by their relative path. However, this can be fixed
93+
by using the ``cssrewrite`` filter, which updates paths in CSS files
94+
to reflect their new location.
95+
96+
Combining Assets
97+
~~~~~~~~~~~~~~~~
6698

6799
You can also combine several files into one. This helps to reduce the number
68-
of HTTP requests which is good for front end performance, as most browsers
69-
will only process a limited number at a time slowing down page load times.
70-
It also allows you to maintain the files more easily by splitting them into
71-
manageable parts. This can also help with re-usability as you can easily
72-
split project specific files from those which can be used in other applications
73-
but still serve them as a single file:
100+
of HTTP requests, which is great for front end performance. It also allows
101+
you to maintain the files more easily by splitting them into manageable parts.
102+
This can help with re-usability as you can easily split project-specific
103+
files from those which can be used in other applications, but still serve
104+
them as a single file:
74105

75106
.. configuration-block::
76107

77108
.. code-block:: html+jinja
78109

79-
{% javascripts '@AcmeFooBundle/Resources/public/js/*'
80-
'@AcmeBarBundle/Resources/public/js/form.js'
81-
'@AcmeBarBundle/Resources/public/js/calendar.js'
110+
{% javascripts
111+
'@AcmeFooBundle/Resources/public/js/*'
112+
'@AcmeBarBundle/Resources/public/js/form.js'
113+
'@AcmeBarBundle/Resources/public/js/calendar.js'
82114
%}
83115
<script src="{{ asset_url }}"></script>
84116
{% endjavascripts %}
@@ -92,15 +124,27 @@ but still serve them as a single file:
92124
<script src="<?php echo $view->escape($url) ?>"></script>
93125
<?php endforeach; ?>
94126
95-
This does not only apply to your own files you can also use Assetic to
96-
combine third party assets, such as jQuery with your own into a single file:
127+
In the `dev` environment, each file is still served individually, so that
128+
you can debug problems more easily. However, in the `prod` environment, this
129+
will be rendered as a single `script` tag.
130+
131+
.. tip::
132+
133+
If you're new to Assetic and try to use your application in the ``prod``
134+
environment (by using the ``app.php`` controller), you'll likely see
135+
that all of your CSS and JS breaks. Don't worry! This is on purpose.
136+
For details on using Assetic in the `prod` environment, see :ref:`cookbook-assetic-dumping`.
137+
138+
And combining files doesn't only apply to *your* files. You can also use Assetic to
139+
combine third party assets, such as jQuery, with your own into a single file:
97140

98141
.. configuration-block::
99142

100143
.. code-block:: html+jinja
101144

102-
{% javascripts '@AcmeFooBundle/Resources/public/js/thirdparty/jquery.js'
103-
'@AcmeFooBundle/Resources/public/js/*'
145+
{% javascripts
146+
'@AcmeFooBundle/Resources/public/js/thirdparty/jquery.js'
147+
'@AcmeFooBundle/Resources/public/js/*'
104148
%}
105149
<script src="{{ asset_url }}"></script>
106150
{% endjavascripts %}
@@ -116,21 +160,26 @@ combine third party assets, such as jQuery with your own into a single file:
116160
Filters
117161
-------
118162

119-
Additionally to this Assetic can apply filters to the assets before they
120-
are served. This includes tasks such as compressing the output for smaller
121-
file sizes which is another valuable front end optimisation. Other filters
122-
include compiling JavaScript file from CoffeeScript files and SASS to CSS.
163+
Once they're managed by Assetic, you can apply filters to your assets before
164+
they are served. This includes filters that compress the output of your assets
165+
for smaller file sizes (and better front-end optimization). Other filters
166+
can compile JavaScript file from CoffeeScript files and process SASS into CSS.
167+
In fact, Assetic has a long list of available filters.
168+
169+
Many of the filters do not do the work directly, but use existing third-party
170+
libraries to do the heavy-lifting. This means that you'll often need to install
171+
a third-party library to use a filter. The great advantage of using Assetic
172+
to invoke these libraries (as opposed to using them directly) is that instead
173+
of having to run them manually after you work on the files, Assetic will
174+
take care of this for you and remove this step altogether from your development
175+
and deployment processes.
123176

124-
Many of the filters do not do the work directly but use other libraries
125-
to do it, this so you will often have to install that software as well.
126-
The great advantage of using Assetic to invoke these libraries is that
127-
instead of having to run them manually when you have worked on the files,
128-
Assetic will take care of this for you and remove this step altogether
129-
from your development and deployment processes.
177+
To use a filter, you first need to specify it in the Assetic configuration.
178+
Adding a filter here doesn't mean it's being used - it just means that it's
179+
available to use (we'll use the filter below).
130180

131-
To use a filter you must specify it in the Assetic configuration
132-
as they are not enabled by default. For example to use the JavaScript YUI
133-
Compressor the following config needs to be added:
181+
For example to use the JavaScript YUI Compressor the following config should
182+
be added:
134183

135184
.. configuration-block::
136185

@@ -162,14 +211,17 @@ Compressor the following config needs to be added:
162211
),
163212
));
164213
165-
166-
You can then specify using the filter in the template:
214+
Now, to actually *use* the filter on a group of JavaScript files, add it
215+
into your template:
167216

168217
.. configuration-block::
169218

170219
.. code-block:: html+jinja
171220

172-
{% javascripts '@AcmeFooBundle/Resources/public/js/*' filter='yui_js' %}
221+
{% javascripts
222+
'@AcmeFooBundle/Resources/public/js/*'
223+
filter='yui_js'
224+
%}
173225
<script src="{{ asset_url }}"></script>
174226
{% endjavascripts %}
175227
@@ -181,22 +233,22 @@ You can then specify using the filter in the template:
181233
<script src="<?php echo $view->escape($url) ?>"></script>
182234
<?php endforeach; ?>
183235
184-
185-
A more detail guide to configuring and using Assetic filters as well as
236+
A more detailed guide abour configuring and using Assetic filters as well as
186237
details of Assetic's debug mode can be found in :doc:`/cookbook/assetic/yuicompressor`.
187238

188239
Controlling the URL used
189240
------------------------
190241

191-
If you wish to you can control the URLs which Assetic produces. This is
242+
If you wish to you can control the URLs that Assetic produces. This is
192243
done from the template and is relative to the public document root:
193244

194245
.. configuration-block::
195246

196247
.. code-block:: html+jinja
197248

198-
{% javascripts '@AcmeFooBundle/Resources/public/js/*'
199-
output='js/combined.js'
249+
{% javascripts
250+
'@AcmeFooBundle/Resources/public/js/*'
251+
output='js/compiled/main.js'
200252
%}
201253
<script src="{{ asset_url }}"></script>
202254
{% endjavascripts %}
@@ -206,48 +258,131 @@ done from the template and is relative to the public document root:
206258
<?php foreach ($view['assetic']->javascripts(
207259
array('@AcmeFooBundle/Resources/public/js/*'),
208260
array(),
209-
array('output' => 'js/combined.js')
261+
array('output' => 'js/compiled/main.js')
210262
) as $url): ?>
211263
<script src="<?php echo $view->escape($url) ?>"></script>
212264
<?php endforeach; ?>
213265
214266
.. note::
215267

216268
Symfony also contains a method for cache *busting*, where the final URL
217-
generated by Assetic in the ``prod`` environment contains a query parameter
218-
that can be incremented via configuration on each deployment. For more
219-
information, see the :ref:`ref-framework-assets-version` configuration
220-
option.
221-
222-
Caching the output
223-
------------------
224-
225-
The process of creating the files served up can be quite slow especially
226-
when using some of the filters which invoke third party software to the
227-
actual work. Even when working in the development environment the slow
228-
down in the page loads if this was to be done each time would quickly get
229-
frustrating. Fortunately in the dev environment Assetic caches the output
230-
so this will not happen, rather than having to clear the cache manually
231-
though, it monitors for changes to the assets and regenerates the files
232-
as needed. This means you can work on the asset files and see the results
233-
on page load but without having to suffer continual slow page loads.
234-
235-
For production, where you will not be making changes to the asset files,
236-
performance can be increased by avoiding the step of checking for changes.
237-
Assetic allows you to go further than this and avoid touching Symfony2
238-
and even PHP at all when serving the files. This is done by dumping all
239-
of the output files using a console command. These can then be served directly
240-
by the web server as static files, increasing performance and allowing the
241-
web server to deal with caching headers. The console command to dump the files
242-
is:
269+
generated by Assetic contains a query parameter that can be incremented
270+
via configuration on each deployment. For more information, see the
271+
:ref:`ref-framework-assets-version` configuration option.
272+
273+
.. _cookbook-assetic-dumping:
274+
275+
Dumping Asset Files
276+
-------------------
277+
278+
In the ``dev`` environment, Assetic generates paths to CSS and JavaScript
279+
files that don't physically exist on your computer. But they render nonetheless
280+
because an internal Symfony controller opens the files and serves back the
281+
content (after running any filters).
282+
283+
This kind of dynamic serving of processed assets is great because it means
284+
that you can immediately see the new state of any asset files you change.
285+
It's also bad, because it can be quite slow. If you're using a lot of filters,
286+
it might be downright frustrating.
287+
288+
Fortunately, Assetic provides a way to dump your assets to real files, instead
289+
of being generated dynamically.
290+
291+
Dumping Asset Files in the ``prod`` environment
292+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
293+
294+
In the ``prod`` environment, your JS and CSS files are represented by a single
295+
tag each. In other words, instead of seeing each JavaScript file you're including
296+
in your source, you'll likely just see something like this:
297+
298+
.. code-block:: html
299+
300+
<script src="/app_dev.php/js/abcd123.js"></script>
301+
302+
Moreover, that file does **not** actually exist, nor is it dynamically rendered
303+
by Symfony (as the asset files are in the ``dev`` environment). This is on
304+
purpose - letting Symfony generate these files dynamically in a production
305+
environment is just too slow.
306+
307+
Instead, each time you use your app in the ``prod`` environment (and therefore,
308+
each time you deploy), you should run the following task:
309+
310+
.. code-block:: bash
311+
312+
php app/console assetic:dump --env=prod --no-debug
313+
314+
This will physically generate and write each file that you need (e.g. ``/js/abcd123.js``).
315+
If you update any of your assets, you'll need to run this again to regenerate
316+
the file.
317+
318+
Dumping Asset Files in the ``dev`` environment
319+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
320+
321+
By default, each asset path generated in the ``dev`` environment is handled
322+
dynamically by Symfony. This has no disadvantage (you can see your changes
323+
immediately), except that assets can load noticeably slow. If you feel like
324+
your assets are loading too slowly, follow this guide.
325+
326+
First, tell Symfony to stop trying to process these files dynamically. Make
327+
the following change in your ``config_dev.yml`` file:
328+
329+
.. configuration-block::
330+
331+
.. code-block:: yaml
332+
333+
# app/config/config_dev.yml
334+
assetic:
335+
use_controler: false
336+
337+
.. code-block:: xml
338+
339+
<!-- app/config/config_dev.xml -->
340+
<assetic:config use-controller="false" />
341+
342+
.. code-block:: php
343+
344+
// app/config/config_dev.php
345+
$container->loadFromExtension('assetic', array(
346+
'use_controller' => false,
347+
));
348+
349+
Next, since Symfony is no longer generating these assets for you, you'll
350+
need to dump them manually. To do so, run the following:
243351

244352
.. code-block:: bash
245353
246354
php app/console assetic:dump
247355
248-
.. note::
356+
This physically writes all of the asset files you need for your ``dev``
357+
environment. The big disadvantage is that you need to run this each time
358+
you update an asset. Fortunately, by passing the ``--watch`` option, the
359+
command will automatically regenerate assets *as they change*:
360+
361+
.. code-block:: bash
362+
363+
php app/console assetic:dump --watch
364+
365+
Since running this command in the ``dev`` environment may generate a bunch
366+
of files, it's usually a good idea to point your generated assets files to
367+
some isolated directory (e.g. ``/js/compiled``), to keep things organized:
368+
369+
.. configuration-block::
370+
371+
.. code-block:: html+jinja
372+
373+
{% javascripts
374+
'@AcmeFooBundle/Resources/public/js/*'
375+
output='js/compiled/main.js'
376+
%}
377+
<script src="{{ asset_url }}"></script>
378+
{% endjavascripts %}
249379
250-
Once you have dumped the output you will need to run the console
251-
command again to see any new changes. If you run it on your development
252-
server you will need to remove the files in order to start letting Assetic
253-
process the assets on the fly again.
380+
.. code-block:: html+php
381+
382+
<?php foreach ($view['assetic']->javascripts(
383+
array('@AcmeFooBundle/Resources/public/js/*'),
384+
array(),
385+
array('output' => 'js/compiled/main.js')
386+
) as $url): ?>
387+
<script src="<?php echo $view->escape($url) ?>"></script>
388+
<?php endforeach; ?>

0 commit comments

Comments
 (0)