dev-resources.site
for different kinds of informations.
Handle your Symfony assets without WebpackEncoreBundle, ViteBundle or AssetMapper
A little context
You actually need to handle assets in your Symfony application and you don't know how to do this ?
I'm gonna show you here one way, without using WebpackEncoreBundle, ViteBundle or AssetMapper.
However, this is not the best way to handle assets with Symfony, but maybe it's the easiest one.
So, why are you showing us this way ? 🤔
Because... sometimes, you can need to handle assets this way, for example:
- you don't have many time and can't wait to learn AssetMapper
- you are a young symfony developer and you don't want to spend too much time learning frontend tools like Webpack or Vite
- you have a wonderful legacy project and need to migrate it step by step
- you just have a few frontend assets and don't want to use a more robust solution
Create a Symfony project
Let's start by creating a fresh new Symfony project executing this command:
symfony new --webapp symfony-handle-assets
If you don't have the Symfony CLI binary, you can install it from here.
But if you don't want, you can also create a Symfony project by using Composer.
Remove Symfony AssetMapper files
We're gonna start by... removing some files.
Yeah, actually we don't need the files installed for AssetMapper, so we're gonna delete them.
But before, start by removing these libraries:
composer remove symfony/asset-mapper symfony/ux-turbo symfony/stimulus-bundle
Delete also the assets
directory.
Congrats, you did it 🎉
Now, get back on our subject.💪
Our first Controller
Start the Symfony webserver by running:
symfony serve -d
Create now a new Symfony Controller by using the Symfony MakerBundle with this shiny command:
./bin/console make:controller
I named this controller FrontController
, but you can name it whatever you want. I choose to not generate tests.
Thanks to the MakerBundle, we have this content:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
final class FrontController extends AbstractController{
#[Route('/front', name: 'app_front')]
public function index(): Response
{
return $this->render('front/index.html.twig', [
'controller_name' => 'FrontController',
]);
}
}
We also have the associated file front/index.html.twig
, in templates
directory, with this content:
{% extends 'base.html.twig' %}
{% block title %}Hello FrontController!{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello {{ controller_name }}! ✅</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/src/Controller/FrontController.php</code></li>
<li>Your template at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/templates/front/index.html.twig</code></li>
</ul>
</div>
{% endblock %}
Start by updating our FrontController
to go on /
and remove the controller_name
variable, we are not gonna use it:
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
final class FrontController extends AbstractController{
#[Route('/', name: 'app_front')]
public function index(): Response
{
return $this->render('front/index.html.twig');
}
}
Update also the associated template content, here front/index.html.twig
:
{% extends 'base.html.twig' %}
{% block title %}Hello FrontController!{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello from Symfony without WebpackEncoreBundle, ViteBundle or AssetMapper ! 👋</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/src/Controller/FrontController.php</code></li>
<li>Your template at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/templates/front/index.html.twig</code></li>
</ul>
</div>
{% endblock %}
The controller_name
variable has been removed and the h1
tag has been updated.
Handle our assets
Get back to work, create now a app.css
file in the css
directory (create also this directory in the public
existing one) with this content:
body{
color: #F5F5F5;
background-color: #999999;
}
I also added the link to this previous file on our base.html.twig
template:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
{% block stylesheets %}
<link href="{{ asset('css/app.css') }}" type="text/css">
{% endblock %}
{% block javascripts %}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
Do the same by creating a JavaScript file, I called it app.js
and add it in a js
directory in public
with this wonderful content:
console.log('Hello Symfony from our JavaScript file!🚀');
Here, a simple console.log
, but you can put here what you want. Don't forget to add the link in the base.html.twig
template:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('css/app.css') }}" type="text/css">
{% endblock %}
{% block javascripts %}
<script src="{{ asset('js/app.js') }}"></script>
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
If you try to access to your homepage, you should have a wonderful ugly design 🤮
Here, we just add CSS
and JavaScript
files on our base.html.twig
template. It means that these files are gonna be used in all of our application, you can put in here all of your common application code.
Yeah, but if I want to have CSS
and JavaScript
files which contains only code used in specific page, how can I do this ?
Follow the guide 😅
Start by creating a new index.css
file, in our css
directory(in public
) :
ul{
list-style-type: none;
}
code{
color: #FFFFFF;
background-color: #000000 !important;
}
Nothing special here, just a boring CSS
code, free to you to add your own code.
Open now your index.html.twig
template, and override the stylesheets
block and add a link to our fresh CSS
file:
{% extends 'base.html.twig' %}
{% block title %}Hello FrontController!{% endblock %}
{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('css/index.css') }}" type="text/css">
{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello from Symfony without WebpackEncoreBundle, ViteBundle or AssetMapper!👋</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/src/Controller/FrontController.php</code></li>
<li>Your template at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/templates/front/index.html.twig</code></li>
</ul>
</div>
{% endblock %}
Refresh your browser page, and... we broke our wonderful design 😭.
How can we do now, we lost the previous style ? Are you kidding us ? 😠
Don't panic, there is a simple way to get back the parent style, you just have to use the {{ parent() }}
function:
{% extends 'base.html.twig' %}
{% block title %}Hello FrontController!{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" href="{{ asset('css/index.css') }}" type="text/css">
{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello from Symfony without WebpackEncoreBundle, ViteBundle or AssetMapper!👋</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/src/Controller/FrontController.php</code></li>
<li>Your template at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/templates/front/index.html.twig</code></li>
</ul>
</div>
{% endblock %}
Try again to refresh your browser page, the design must be almost the same as before, but don't dream, it's still wonderfully ugly.😅
Do the same for JavaScript
now, create an index.js
file in the js
directory(in public
):
console.log('Hello Symfony from our index.js file!🚀');
Don't forget to add the link in the index.html.twig
template:
{% extends 'base.html.twig' %}
{% block title %}Hello FrontController!{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" href="{{ asset('css/index.css') }}" type="text/css">
{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello from Symfony without WebpackEncoreBundle, ViteBundle or AssetMapper!👋</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/src/Controller/FrontController.php</code></li>
<li>Your template at <code>/Users/abdounikarim/Web/poc/poc-symfony-handle-assets/templates/front/index.html.twig</code></li>
</ul>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="{{ asset('js/index.js') }}"></script>
{% endblock %}
You see, we can handle assets easily with our Symfony application 😉
Again, it's not the best way to do this, but... you now the drill.
And... please, don't ever deliver a project with a terrible design like this. And if you do it, whatever is the situation, never talk about this article 🤐
Happy coding 😀
Featured ones: