当使用 Google PageSpeed Insights 测试基于
Symfony 2.8
的网页时,我收到警告,HTML 代码未缩小。
确实如此,虽然
Assetic
负责缩小所有 CSS
文件和 JS
脚本,但 HTML 代码本身相当脏。
Google 建议使用 HTML Minifier,但由于这是一个 JavaScript 工具,因此不能用作
Twig
扩展、过滤器等,可以吗?
Twig
标签的spaceless
文档清楚地表明,该标签并不意味着缩小HTML,而且:
如果您想创建一个实际上删除所有额外空格的标签 在 HTML 字符串中,请注意,这并不像看起来那么容易 be(例如,考虑 textarea 或 pre 标签)。使用第三方 像Tidy这样的库可能是一个更好的主意。
但我还是不明白如何将
Tidy
集成到 Twig
模板等中。
那么,使用
Symfony
和 Twig
创建缩小的 HTML 输出的最佳方法是什么?
这是一个很好的问题,没有旗舰捆绑包,但经过快速搜索,您有两个捆绑包可以帮助您:
此捆绑包允许您在一个配置值中缩小所有响应(在 KernelResponse 事件上自动),或者根据需要使用 twig 扩展。
但是这个包已经很老了(3年了),还没有为 Symfony3 做好准备。
此捆绑包更新一些,并使用 htmlcompressor 库。
为了在几年后实现这一目标,我在
kernel.response
事件上创建了一个订阅者。
# 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);
}
}
我自己偶然发现了这个问题,解决这个问题最简单、最好的方法是创建一个 Twig 扩展。然而,单独使用 preg_replace 并不是一个好主意,您应该使用经过实战测试的 HTML“压缩器”库;例如:https://github.com/voku/HtmlMin
为最新的 Symfony 创建 Twig 扩展非常简单:
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use voku\helper\HtmlMin;
class MinifyExtension extends AbstractExtension
{
public function getFilters()
{
return [
new TwigFilter('minify', [$this, 'minify'], ['is_safe' => ['html']]),
];
}
public function minify(string $html): string
{
$htmlMin = new HtmlMin();
$htmlMin->doOptimizeAttributes();
$htmlMin->doRemoveComments();
$htmlMin->doRemoveWhitespaceAroundTags();
return $htmlMin->minify($html);
}
}
然后只需使用它(扩展现在会自动加载):
{# base.html.twig #}
{% block body %}
{{ parent()|minify }}
{% endblock %}
希望有帮助!