Blazing fast Symfony with Lazy Twig Extensions
Ever wondered why your Symfony app is so slow? One of the factors is going to be the initialization time of the Twig templating system.
index.html.twig file is rendered, lots of things happen under the hood. Twig won’t render any template until every extension has been instantiated and loaded. As a result, Symfony goes through every service tagged with the
twig.extensiontag and instantiates it. However, before any service is created, its dependencies have to be instantiated too.
Let’s take an average Sylius application, an e-commerce solution written in Symfony — 33 additional Twig extensions. Add Symfony extensions, 3rd party extensions, your application-specific extensions and you end up having at least 70 in total. Even if none is used when rendering a simple template, Symfony still needs to load every single one to boot Twig’s environment. Things get worse if the initialization requires access to the infrastructure like a database or any other external source.
The solution is simple – meet Runtime Extensions. Available since Twig v1.35 and v2.4.4, still not widely used nor known.
Let’s consider an imaginary Twig extension which loads a list of popular article tags:
<?php namespace App\Twig\Extension;use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;class ArticleTagExtension extends AbstractExtension
private ArticleRepository $articleRepository; public function __construct(ArticleRepository $repository)
$this->articleRepository = $repository;
} public function getFunctions(): array
new TwigFunction('get_tags', [$this, 'getTags']),
} public function getTags(int $count): array
We can rewrite this extension by extracting its dependencies to a Runtime Extension leaving the extension itself without any dependency. The Runtime Extension has to be tagged with the
twig.runtime_extension tag (if not using the autoconfiguration…