Google Pagespeed also complains from time to time: In addition to the recommended GZIP compression, you can also remove unnecessary characters (e.g. spaces, breaks and comments) from the rendered HTML of a TYPO3 page. Although there is already a ViewHelper (f:spaceless) that helps you to compress the code a bit in the Fluid, it usually only takes care of the body area of your website. If you really want to compress everything, the use of PSR-15 middleware is recommended.
PHP package wyrihaximus/html-compress helps with compressing. Just add it to your composer.json:
{
"name": "vendor/sitepackage",
"description": "Sitepackage extension",
"type": "typo3-cms-extension",
"homepage": "https://www.in2code.de",
"require": {
"typo3/cms-core": "^10.4",
"wyrihaximus/html-compress": "^1"
},
"autoload": {
"psr-4": {
"Vendor\\Sitepackage\\": "Classes/"
}
}
}
EXT:sitepackage/Configuration/RequestMiddlewares.php:
<?php
return [
'frontend' => [
'sitepackage-compress-html' => [
'target' => \Vendor\Sitepackage\Middleware\HtmlCompress::class,
'before' => [
'typo3/cms-frontend/output-compression'
],
'after' => [
'typo3/cms-adminpanel/renderer'
]
]
]
];
EXT:sitepackage/Classes/Middleware/HtmlCompress.php:
<?php
declare(strict_types=1);
namespace Vendor\Sitepackage\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Core\Http\StreamFactory;
use WyriHaximus\HtmlCompress\Factory;
/**
* Class HtmlCompress
*/
class HtmlCompress implements MiddlewareInterface
{
/**
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$response = $handler->handle($request);
if ($this->isTypeNumSet($request) === false) {
$stream = $response->getBody();
$stream->rewind();
$content = $stream->getContents();
$newBody = (new StreamFactory())->createStream($this->compressHtml($content));
$response = $response->withBody($newBody);
}
return $response;
}
/**
* @param string $html
* @return string
*/
protected function compressHtml(string $html): string
{
$parser = Factory::construct();
$html = $parser->compress($html);
$html = $this->removeComments($html);
return $html;
}
/**
* Remove all html comments but not "<!--TYPO3SEARCH_begin-->" and "<!--TYPO3SEARCH-end-->"
* @param string $html
* @return string
*/
protected function removeComments(string $html): string
{
return preg_replace('/<!--((?!TYPO3SEARCH)[\s\S])*?-->/', '', $html);
}
/**
* @param ServerRequestInterface $request
* @return bool
*/
protected function isTypeNumSet(ServerRequestInterface $request): bool
{
return $request->getAttribute('routing')->getPageType() > 0;
}
}
Note: If you remove HTML comments, please note that you need the comments "TYPO3SEARCH _..." for Solr or the index search! The code above already takes this into account.