4

I would really like to use assetic in my symfony 2 project as it has many useful features, but I'm not sure about the best way to implement the following requirement.

I have several js files that can be included in all pages. However, some of them are related only to a subset of page templates, in which I include specific templates (or also embed specific controllers), that require those specific javascript files.

Now I have the following options:

  1. I create a block element for the javascripts in the layout and in the specific page templates (where I include the templates with javascript, e.g. templateWithComplexJs.html.twig), I overwrite this block using {{ parent() }}, as described here: Combining Assetic Resources across inherited templates.

    {# ... specific.html.twig #}  
    {% extends 'MyBundle::layout.html.twig' %}
    
    ...  
    {% include 'MyBundle:Foo:templateWithComplexJs.html.twig' %}  
    ...  
    
    {% block javascripts %}
        {{ parent() }}
        {% javascripts  
            '@MyBundle/Resources/public/js/specific/complex.js'  
        %}  
        <script src="{{ asset_url }}"></script>  
        {% endjavascripts %}  
    {% endblock %}  
    

    The disadvantages I see:
    a) When I adapt an included template (e.g. update to a new js lib), then I have to adapt all page templates, where they are included. In a complex system that can easily lead to errors.
    b) It can happen that I include a javascript twice, once in the layout's and once in the template's javascript, assetic doesn't know because they are treated separatelly.

  2. I include all js files ever needed in the layout, then I only have to change one place when I adapt the included templates and it's unlikely that I include javascripts twice.

    The disadvantage I see:
    As the js files can have significant size I would prefer to include them only in the few cases when I really need them.

In this related question ( Twig Assetic Stylesheets Among Several Templates ) it says that it's currently not possible with assetic to achieve a satisfying solution, but I guess that I'm not the only one having these requirements and wanting to use assetic anyway.

So, what's the best practice for that kind of scenario?

Community
  • 1
  • 1
stefax
  • 171
  • 1
  • 8
  • Regarding your first option, do you know about the twig embed tag:http://twig.sensiolabs.org/doc/tags/embed.html It could help you group all assets in one file and then decide inside the template which ones to use. – Sgoettschkes Jun 13 '12 at 11:20
  • Thanks, but I don't see how this could solve it; I still would have to adapt all blocks in all templates ... I would like to know how the problem is approached in complex diverse websites, where many pages have different combinations of javascript libraries, depending on their used elements (be it embedded controllers, included templates or embed tags)... – stefax Jun 22 '12 at 18:27
  • That's true. But do you really need to be so specific? Do the js scripts collide or are they very big? Minifying/combining them might be enough if we are not talking about millions of requests per second. Before getting into very complicated setups I would combine them and use some kind of CND. If the performance is really bad although the CND is working well, I would go ahead and think about more specific solutions. But we are talking top 5% of webpages out there. – Sgoettschkes Jun 28 '12 at 20:28
  • just curious, what did you end up doing? I'm facing the same problem.. especially the asset duplication – Mike Dinescu Jul 24 '14 at 18:53

1 Answers1

7

You can likely get what you are aiming for more simply. Setup your asset groups in a config file and give them names rather than doing this in all your templates. Here's a quick example.

# Assetic Configuration
assetic:
    debug:          %kernel.debug%
    use_controller:
        enabled:    false #%kernel.debug%
        profiler:   false
    java: /usr/bin/java
    node: /usr/bin/node
    assets:
        backend_css:
            inputs:
                - %kernel.root_dir%/../path/to/some/css/file.css
                - %kernel.root_dir%/../path/to/some/less/file.less
            filters:
                - less
            output: css/backend.css
        frontend_css:
            inputs:
                - %kernel.root_dir%/../path/to/some/css/file.css
                - %kernel.root_dir%/../path/to/some/less/file.less
            filters:
                - less
            output: css/frontend.css
        backend_js:
            inputs:
                - %kernel.root_dir%/../path/to/some/js/file.js
                - %kernel.root_dir%/../path/to/some/js/other.js
            filters:
                - yui_js
            output: js/backend.js
        frontend_js:
            inputs:
                - %kernel.root_dir%/../path/to/some/js/file.js
                - %kernel.root_dir%/../path/to/some/js/other.js
            filters:
                - yui_js
            output: js/frontend.js
        special_backend_js:
            inputs:
                - %kernel.root_dir%/../path/to/some/js/file.js
                - %kernel.root_dir%/../path/to/some/js/other.js
            filters:
                - yui_js
            output: js/special_backend.js
    filters:
        cssrewrite: ~
        cssembed: 
            jar: %kernel.root_dir%/Resources/java/cssembed-0.4.5.jar
        # closure:
        #     jar: %kernel.root_dir%/Resources/java/compiler.jar
        yui_css:
            jar: %kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar
        yui_js:
            jar: %kernel.root_dir%/Resources/java/yuicompressor-2.4.7.jar
        less:
            node_paths: [%kernel.root_dir%/Resources/node_modules]
            apply_to: "\.less$"

Now in your twig templates you can simply do something like the following:

{% block javascript %}
<script src="{{ asset('js/backend.js') }}"></script>
{% endblock javascript %}

and do the same for your css assets. This way, if you want to add another library to your backend.js collection or include some group of js functionality like special_backend it's a one liner in your template and when you make changes you only have to deal with your config definitions.

I hope that helps you out a bit. I'm sure there are other ways to get this done as well but this is my preferred method.

Johnny
  • 559
  • 9
  • 17