src/EventSubscriber/DeferReadmoreScriptSubscriber.php line 41

Open in your IDE?
  1. <?php
  2. namespace App\EventSubscriber;
  3. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  4. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  5. use Symfony\Component\HttpKernel\KernelEvents;
  6. /**
  7. * EventSubscriber para optimizar la carga de readmore.js
  8. *
  9. * Este subscriber:
  10. * 1. Intercepta la respuesta HTML antes de enviarla al navegador
  11. * 2. Encuentra el script readmore.min.js en el head
  12. * 3. Lo mueve al final del body o añade atributo defer
  13. * 4. Mejora el rendimiento de carga de la página
  14. *
  15. * @package App\EventSubscriber
  16. */
  17. class DeferReadmoreScriptSubscriber implements EventSubscriberInterface
  18. {
  19. /**
  20. * Registrar los eventos a los que se suscribe
  21. *
  22. * @return array
  23. */
  24. public static function getSubscribedEvents(): array
  25. {
  26. return [
  27. // Ejecutar justo antes de enviar la respuesta al navegador
  28. // Prioridad baja (-100) para ejecutar después de otros listeners
  29. KernelEvents::RESPONSE => ['onKernelResponse', -100],
  30. ];
  31. }
  32. /**
  33. * Manipular la respuesta para optimizar readmore.js
  34. *
  35. * @param ResponseEvent $event
  36. */
  37. public function onKernelResponse(ResponseEvent $event): void
  38. {
  39. // Solo procesar la respuesta principal, no sub-requests
  40. if (!$event->isMainRequest()) {
  41. return;
  42. }
  43. $response = $event->getResponse();
  44. $contentType = $response->headers->get('Content-Type');
  45. // Solo procesar respuestas HTML
  46. if (!$contentType || strpos($contentType, 'text/html') === false) {
  47. return;
  48. }
  49. $content = $response->getContent();
  50. // Verificar si el contenido contiene readmore
  51. if (strpos($content, 'readmore') === false) {
  52. return;
  53. }
  54. // ============================================
  55. // OPCIÓN 1: Añadir atributo defer (recomendado)
  56. // ============================================
  57. // Buscar todos los scripts que incluyan "readmore" y añadir defer
  58. $content = preg_replace_callback(
  59. '/<script\s+([^>]*src=["\'][^"\']*readmore[^"\']*["\'][^>]*)>/i',
  60. function ($matches) {
  61. $scriptTag = $matches[0];
  62. // Si ya tiene defer o async, no hacer nada
  63. if (preg_match('/\s(defer|async)\s/i', $scriptTag)) {
  64. return $scriptTag;
  65. }
  66. // Añadir defer antes del cierre >
  67. return str_replace('>', ' defer>', $scriptTag);
  68. },
  69. $content
  70. );
  71. // ============================================
  72. // OPCIÓN 2: Mover scripts al final del body (alternativa)
  73. // ============================================
  74. // Descomentar este bloque si prefieres mover el script al final
  75. /*
  76. $readmoreScripts = [];
  77. // Extraer scripts de readmore del head
  78. $content = preg_replace_callback(
  79. '/<script\s+[^>]*src=["\'][^"\']*readmore[^"\']*["\'][^>]*>.*?<\/script>/is',
  80. function ($matches) use (&$readmoreScripts) {
  81. // Guardar el script para insertarlo después
  82. $readmoreScripts[] = $matches[0];
  83. // Remover del head
  84. return '';
  85. },
  86. $content
  87. );
  88. // Insertar los scripts justo antes de </body>
  89. if (!empty($readmoreScripts)) {
  90. $scriptsHtml = "\n <!-- Readmore scripts movidos al final para mejor rendimiento -->\n ";
  91. $scriptsHtml .= implode("\n ", $readmoreScripts);
  92. $scriptsHtml .= "\n";
  93. $content = str_replace('</body>', $scriptsHtml . '</body>', $content);
  94. }
  95. */
  96. // ============================================
  97. // OPCIÓN 3: Preload para mejorar aún más (opcional)
  98. // ============================================
  99. // Añadir preload en el head para que el navegador descargue el script
  100. // pero sin bloquear el renderizado
  101. /*
  102. if (preg_match('/<head[^>]*>/i', $content)) {
  103. $preloadLinks = [];
  104. // Extraer todas las URLs de scripts readmore
  105. preg_match_all('/<script\s+[^>]*src=["\']([^"\']*readmore[^"\']*)["\'][^>]*>/i', $content, $matches);
  106. foreach ($matches[1] as $scriptUrl) {
  107. $preloadLinks[] = sprintf(
  108. '<link rel="preload" href="%s" as="script">',
  109. htmlspecialchars($scriptUrl, ENT_QUOTES, 'UTF-8')
  110. );
  111. }
  112. if (!empty($preloadLinks)) {
  113. $preloadHtml = "\n " . implode("\n ", $preloadLinks) . "\n";
  114. $content = preg_replace(
  115. '/(<head[^>]*>)/i',
  116. '$1' . $preloadHtml,
  117. $content,
  118. 1
  119. );
  120. }
  121. }
  122. */
  123. // Actualizar el contenido de la respuesta
  124. $response->setContent($content);
  125. }
  126. }