Embedding contents of css and javascript assets into the view in Symfony - symfony

I have a one-page webapp written with Symfony 2 where all css and javascript assets sit in web/static/all.js and web/static/all.js. These a linked from the intex.html.twig template in a standard way:
{% javascripts output='static/all.js' filter="?closure"
'#MyBundle/Resources/assets/vendor/jquery/jquery.js'
'#MyBundle/Resources/assets/...'
'#MyBundle/Resources/assets/...'
%}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
{% stylesheets output='staic/all.css' filter="?yui_css" combine=true
'#MyBundle/Resources/assets/css/reset.css'
'#MyBundle/Resources/assets/css/...'
'#MyBundle/Resources/assets/css/...'
%}
<link rel="stylesheet" href="{{ asset_url }}" type="text/css" media="all" />
{% endstylesheets %}
This is pretty cool already, because the browser only has to do 3 requests during the first launch and 1 or 0 requests later (all.css and all.js are cached using .htaccess).
But I want to go further and just dump all css and js into index.html similar to what google does on their homepage. This will result only one http request during the first run, which will speed up the app a little. It would be ideal to have a flag that I pass to the template or keep in twig globals that will enable switching between two modes on demand.
{%if dumpAssetsIntoTemplate %}
{# all js and css here #}
{% else %}
{# asset urls #}
{% endif %}
How could this be done with minimum pain?

If you look at Twig reference about Twig extensions you can see that the render function takes a path or a URL.
{{ render(path('route', {params})) }}
{{ render(url('route', {params})) }}
Quoting the usage from the doc "This will render the fragment for the given controller or URL".
So I would try that:
<style type="text/css">
{% stylesheets output='static/all.css' filter="?yui_css" combine=true
'#MyBundle/Resources/assets/css/reset.css'
'#MyBundle/Resources/assets/css/...'
'#MyBundle/Resources/assets/css/...'
%}
{{ render(asset_url) }}"
{% endstylesheets %}
</style>
Same approach with your Javascript files.
If it doesn't work, you'll probably want to tweak the settings of the Assetic bundle in particular the setting named use_controller.

Related

Why are the CSS styles not being applied to the page?

I am working on a Symfony2 application. I am customising the layout.html.twig file from the FOSUserBundle.
Any HTML changes I make within the file are immediately obvious when I reload the page in the browser.
I am using assetic to link to my CSS and JS files. They appear to have linked successfully, the files contents load when I click on their paths from within the source of the web page.
However the CSS classes I have specified on the elements of the page don't seem to be appearing with their styles applied. I can't figure out why this is.
Here is the syntax I've used to link to the JS and CSS:
{% javascripts
'bundles/sysdevpunctuality/js/jquery-2.1.1.min.js'
'bundles/sysdevpunctuality/bootstrap-3.2.0-dist/js/bootstrap.min.js'
%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
<!-- Bootstrap -->
{% stylesheets 'bundles/sysdevpunctuality/bootstrap-3.2.0-dist/css/bootstrap.css' filter='cssrewrite' %}
<link rel="stylesheets" href="{{ asset_url }}" media="screen" />
{% endstylesheets %}
Appreciate any tips on how I can go about debugging this issue.
I had the same problem, try this syntax:
{% block stylesheets %}
<link href="{{ asset('bundles/sysdevpunctuality/bootstrap-3.2.0-dist/css/bootstrap.css') }}" type="text/css" rel="stylesheet" />
{% endblock %}
Of course don't forget to install assets:
php app/console assets:install web --symlink
i cant comment but my suggestion is check the page source of the generated webpage, then you can check the directory where symfony is looking for the resources.

Symfony2 asset managment with assetic

In one of my Symfony projects I am using assetic for asset managment.
All my twig files extend a base file called base.html.twig. I This file (base) I have:
{% stylesheets output="css/compiled/main.css" filter='cssrewrite'
'../vendor/bootstrap/css/bootstrap.css'
'css/general.css'
'css/navigation.css'
%}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
In the other files that extend the base file I override the stylesheets block so that I can add other css files. This is what I do:
{% block stylesheets %}
{{ parent() }}
{% stylesheets output="css/compiled/main.css" filter='cssrewrite'
'bundles/account/css/signup.css'
%}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
Now the problem is that signup.css is never added in main.css and so are all the other files that are not in the stylesheet block in the base file.
I don't know why but this started happening when I swtiched to prod environment (it was working fine in dev). I've done, as recommending on Symfony's website:
php app/console assetic:dump --env=prod --no-debug
One other thing, it seems that I can't swtich back to dev mode even when I'm using app_dev.php
Do you guys have any idea of where these errors could come from ?
Thank you in advance for you help,
kimimsc
Your have a conflict with your 'option' attribute. So in prod environnement, the second stylesheet overwrite the first.
You must use another output value for signup.css (or don't use this option)

Load one js file using assetic inside Symfony2

I am new to Symfony 2. Previously I worked a lot with Codeigniter. Now that I am exploring assetic, I am not able to understand how I can add a single file to the stack of JS files which are already being loaded.
I have a main page twig file which has something like this:
{% javascripts '#BlogBlogBundle/Resources/public/js/vendor/*' output='js/combined.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
Now this works fine if all the JS files are inside the vendor folder. But what if I have a JS file contact.js inside a folder called contact and I want that to be visible only on contact page. So, when I added such a code inside block body of contact page twig file
{% javascripts '#BlogBlogBundle/Resources/public/js/home/*' output='js/home_combined.js' %}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
the contact.js is coming before all other js files which are being loaded before the body ends.
In codeigniter, using the Carabiner library I could set up the default files which I want to load on all pages like jQuery. And if there are any specific file for a page, I can do that inside that particular controller.
Please let me know how I can do this inside Symfony also.
You can add a file to your assets like this:
{% javascripts
'#YourBundle/Resources/public/js/*'
'#AnotherBundle/Resources/public/js/some.js'
'#YourBundle/Resources/public/vendor/someother.js'
output="filename.js"
%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
In order to have pre-defined asset collections which you can then use as for example '#js_default' you can add these in your assetic.assets configuration as suggested in my answer here.
To add the contact.js after the main file js files you can do something like this.
{% block javascripts %}
{{- parent() -}}
{% javascripts "#AcmeBundle/Resources/public/js/contact.js" %}
<script type="text/javascript" src="{{ asset_url }}" ></script>
{% endjavascripts %}
{% endblock %}

Learning Symfony2, having trouble using assets

I'm using KnPUniversity's video tutorial on Getting Started with Symfony2, and everthing's been going good except the video is teaching based off of version 2.0.3 and I am using 2.1.x-dev. When I get to a certain point in the video, it directs me to write code block #1 then modify it to more efficiently use code block #2, except code block #2 doesn't work. It doesn't throw any errors, it just fails to actually detect the stylesheets. In the source code of the page, there are zero references to any css style sheets using code block #2. Any idea what I'm doing wrong?
{# this causes the page to be styled and works fine #}
{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('bundles/event/css/event.css') }}">
<link rel="stylesheet" href="{{ asset('bundles/event/css/events.css') }}">
<link rel="stylesheet" href="{{ asset('bundles/event/css/main.css') }}">
{% endblock %}
.
{# this causes the page to be unstyled. Missing stylesheet links in page source #}
{% block stylesheets %}
{% stylesheets
'bundes/event/css/*'
filter='cssrewrite'
%}
<link rel="stylesheet" href="{{ asset_url }}">
{% endstylesheets %}
{% endblock %}
Well, I had a typo. It's not "bundes" it's "bundles". Problem solved and I'm an idiot.
When you use {{ asset() }} it creates a link to your web (public) directory.
But for the second part Assetic manages the css files - so it looks for the file inside your application and then writes it out into your web directory.
To fix your problem you can change your stylesheets like this:
{% stylesheets
'%kernel.root_dir%/../web/bundes/event/css/*'
filter='cssrewrite'
%}
But I suggest reading more about assetic to understand how you should be managing your css files Symfony 2 Assetic

Where do Symfony2 shared CSS and JS assets go, best practice wise?

I normally place my JS and CSS Assetic assets inside a DefaultBundle, but I suppose the best place to put them would be in the app/Resources/public/(js|css) folders.
Also, to reference assets we use:
{% javascripts filter="" output="js/core.js" debug=true
"#DefaultBundle/Resources/public/js/jquery-1.6.2.js" %}
<script src="{{ asset_url }}" type="text/javascript"></script>
{% endjavascripts %}
How do I go about referencing shared assets like jQuery and my CSS reset stylesheets in app/Resources/public/...?
You could also use this:
{% stylesheets '../app/Resources/public/css/*' %}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
{% endstylesheets %}
Yes it's a good choice to not put libraries inside a Bundle
see here : http://symfony.com/doc/current/cookbook/bundles/best_practices.html#vendors
A bundle should not embed third-party libraries written in JavaScript, CSS, or any other language.
What i suggest you, is to put you jquery and reset files under something like: app/Resources/public/js/jquery.min.js and to change your code with something like:
{% javascripts filter="" output="js/core.js" debug=true
"../app/Resources/public/js/jquery-1.6.2.js" %}
<script src="{{ asset_url }}" type="text/javascript"></script>
{% endjavascripts %}
I hope this will work for you.
EDIT: Edited answer to be like https://stackoverflow.com/a/9237004/505836, thanks David.
My solution is almost the same as David's, but using %kernel.root_dir% instead of hard-coding the app folder (although, I doubt many change this folder's name), e.g.:
{%- javascripts output='compiled/main.js'
'%kernel.root_dir%/Resources/public/js/jquery-1.10.2.min.js'
'%kernel.root_dir%/Resources/public/js/underscore-1.5.2.min.js'
'#MyOwnBundle/Resources/public/js/default.js'
-%}
<script src='{{ asset_url }}'></script>
{%- endjavascripts %}
If the third party libraries reference their own assets (e.g. typically images in a img sub-folder, referenced from .css files), it's usually sufficient to create the corresponding symlinks on the server, e.g. ln -s .../app/Resources/public/img .../web/img or something similar. Or use the cssrewrite filter, of course - but beware of its caveats.
(Also, note that I don't use the type="<mime-type>" attribute, as the files' content-type is supplied in the HTTP headers anyway.)
You can replace ../app/Resources/public/css/ by public/css/. The same for Javascript folder.
{% stylesheets filter='less' output='css/core' 'public/css/*' %}
<link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
{% endstylesheets %}
{% javascripts "public/js/*" %}
<script src="{{ asset_url }}" type="text/javascript"></script>
{% endjavascripts %}
Here all the files of /web/public folder are automatically loaded.

Resources