'How to minify Symfony / Twig generated HTML code to satisfy Google PageSpeed Insight?
When testing my Symfony 2.8
based webpage with Google PageSpeed Insights I am getting warned, that the HTML code is not minified.
This is true, while Assetic
takes care of minifying all CSS
files and JS
scripts, the HTML code itself is quite dirty.
Google recommends to use HTML Minifier, but since this a JavaScript tools it cannot be used as Twig
extension, filter, etc., can it?
The Twig
docu of the spaceless
tag makes clear, that this tag is not meant to minify HTML and furthmore:
If you want to create a tag that actually removes all extra whitespace in an HTML string, be warned that this is not as easy as it seems to be (think of textarea or pre tags for instance). Using a third-party library like Tidy is probably a better idea.
But again I don't see how Tidy
could be integrated into the Twig
templates, etc.
So, what is the best way, to create minified HTML output with Symfony
and Twig
?
Solution 1:[1]
This is a good question and there isn't a flagship bundle but after a quick search, you have two bundle which could help you:
SemaMinifierBundle
This bundle allows you to minify in one config value all your responses (automatically on KernelResponse event) or, on demand, with a twig extension.
But this bundle is pretty old (3 years) and is not ready for Symfony3.
HtmlCompressorBundle
This bundle is a bit more recent and use the htmlcompressor library.
Solution 2:[2]
To achieve this several years later, i created a Subscriber on kernel.response
event.
# src/Event/MinificationSubscriber.php
<?php
namespace App\Event;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class MinificationSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
KernelEvents::RESPONSE => ['onKernelResponse', -256]
];
}
public function onKernelResponse($event)
{
if (
$event->getRequestType() != HttpKernelInterface::MAIN_REQUEST
|| $event->getRequest()->get('_route') === 'admin' // don't apply on admin pages
) {
return;
}
$response = $event->getResponse();
$buffer = $response->getContent();
$replace = [
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\n([\S])/" => '$1',
"/\r/" => '',
"/\n/" => '',
"/\t/" => '',
'/ +/' => ' ',
];
if (false !== strpos($buffer, '<pre>')) {
$replace = [
'/<!--[^\[](.*?)[^\]]-->/s' => '',
"/<\?php/" => '<?php ',
"/\r/" => '',
"/>\n</" => '><',
"/>\s+\n</" => '><',
"/>\n\s+</" => '><',
];
}
$buffer = preg_replace(array_keys($replace), array_values($replace), $buffer);
$response->setContent($buffer);
}
}
Based on this post, this other one and this gist.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | lenybernard |
Solution 2 |