How to minify Symfony / Twig generated HTML code to satisfy Google PageSpeed Insight?

Viewed 5443

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?

2 Answers

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.

Related