I work on huge web apps and I basically use the same structure as you where I only include JS and CSS files in twig files that need them. Sometimes you find that a certain JS plugin is only needed on a certain page and not on others, as such it only makes sense to insert it only on the page that requires it.
This is what I do.
Depending on how big, in terms of features and pages, the app is; I can have a single base.html.twig file and multilple layout.html.twig files that extends base.html.twig file. This way, base.html.twig only has the css and js files that are required by all layout.html.twig files. Then each layout.html.twig file includes JS and CSS files required by all files that will extend it. Say you have three pages that extend a certain layout.html.twig file, they will all have the JS and CSS of that layout.html.twig file and each can add extra JS and CSS required.
Here is how I do it:
base.html.twig would look something like this:
<!DOCTYPE html>
<!--[if IE 8]> <html lang="en" class="ie8 no-js"> <![endif]-->
<!--[if IE 9]> <html lang="en" class="ie9 no-js"> <![endif]-->
<!--[if !IE]><!-->
<html lang="en" class="no-js">
<!--<![endif]-->
<!-- BEGIN HEAD -->
<head>
<meta charset="utf-8">
{% block mainPageTitle %}
<title>Snappic | Photobooth Software</title>
{% endblock %}
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="width=device-width, initial-scale=1" name="viewport">
<meta content="" name="description">
<meta content="" name="author">
<!-- BEGIN GLOBAL MANDATORY STYLES -->
{% stylesheets
"bundles/snappicadmin/css/layout/components-md.css"
"bundles/snappicadmin/plugins/bootstrap/css/bootstrap.css"
"bundles/snappicadmin/plugins/web-icons/web-icons.min.css"
"bundles/snappicadmin/css/layout/layout.css"%}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
<!-- END GLOBAL MANDATORY STYLES -->
<!-- BEGIN PAGE SPECIFIC STYLES -->
{% block pageCSS %}
{% endblock %}
<!-- END PAGE STYLES -->
<link rel="icon" href="{{ asset('bundles/snappicadmin/images/icon/plain_logo-32x32.png') }}" sizes="32x32" />
</head>
<!-- END HEAD -->
<!-- BEGIN BODY -->
<body class="page-md">
<!-- GENERAL LAYOUT CONTENT HERE e.g Main menu -->
{% block content %}
{% endblock %}
<!-- BEGIN JAVASCRIPTS -->
<!-- BEGIN CORE PLUGINS -->
<!--[if lt IE 9]>
{% javascripts
"@SnappicAdminBundle/Resources/public/plugins/respond.min.js"
"@SnappicAdminBundle/Resources/public/plugins/excanvas.min.js"%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
<![endif]-->
{% javascripts
"@SnappicAdminBundle/Resources/public/plugins/fullcalendar/lib/moment.min.js"
"@SnappicAdminBundle/Resources/public/plugins/jquery.browser.min.js"
"@SnappicAdminBundle/Resources/public/js/utilities/utilities.js"
"@SnappicAdminBundle/Resources/public/plugins/jquery.min.js"%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% block pagescript %}
{% endblock %}
<script>
jQuery(document).ready(function() {
App.init();
Layout.init();
initSlideOut();
});
</script>
<!-- END JAVASCRIPT -->
</body>
<!-- END BODY -->
</html>
Notice the {% block pageCSS %}
, this is where your page specific CSS will go and same for JS in {% block pagescript %}
.
Here is how a page that extends base.html.twig would look like:
{% extends "@SnappicAdmin/Layout/base.html.twig" %}
{% block mainPageTitle %}<title>Snappic - Dashboard</title>{% endblock %}
{% block pageCSS %}
{% stylesheets
"bundles/snappicadmin/css/layout/plugins.min.css"
"@SnappicAdminBundle/Resources/public/css/dashboard/dashboard.css"%}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
{% endblock %}
{% block content %}
<!-- BEGIN PAGE CONTENT INNER -->
This is where your page content goes
<!-- END PAGE CONTENT INNER -->
{% endblock %}
{% block pagescript %}
{% javascripts
"bundles/snappicadmin/plugins/fullcalendar/lib/moment.min.js"
"@SnappicAdminBundle/Resources/public/js/dashboard/dashboard.js"
%}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
The key here is to use [Template Inheritance (Twig inheritance)][1] by defining blocks. It will make your code much more manageable, not to mention better rendering.
I believe this is much easier and cleaner than injecting the files via the controller.
PS. Sorry for including so many files, I wanted to make it as clearer as possible, if anything is unclear, give me a shout.
Happy clean coding!