feat: implement is_critical CSS injection via CriticalCSSService

- Created CriticalCSSService (singleton) that queries BD directly in wp_head
- Service generates CSS BEFORE components render (priority 1)
- Renderers check is_critical flag and skip inline CSS if true
- Made generateCSS() public in Renderers for CriticalCSSService to use
- Removed CriticalCSSCollector pattern (timing issue with WordPress)

Flow:
1. wp_head (priority 1) → CriticalCSSService::render()
2. Service queries BD for components with visibility.is_critical=true
3. Generates CSS using Renderer->generateCSS() methods
4. Outputs: <style id="roi-critical-css">...</style>
5. When Renderers execute, they detect is_critical and omit CSS inline

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2025-11-29 10:06:38 -06:00
parent 38d7099bcd
commit ce0179a134
8 changed files with 366 additions and 179 deletions

View File

@@ -115,25 +115,26 @@ function roi_get_navbar_setting(string $group, string $attribute, $default = nul
}
// =============================================================================
// CRITICAL CSS COLLECTOR SINGLETON
// CRITICAL CSS SERVICE SINGLETON
// =============================================================================
/**
* Obtiene la instancia singleton del CriticalCSSCollector
* Obtiene la instancia singleton del CriticalCSSService
*
* Patrón Singleton implementado via función para mantener una única instancia
* que será compartida por todos los Renderers y el HooksRegistrar
* Este servicio consulta la BD para componentes con is_critical=true
* y genera su CSS en wp_head ANTES de que los componentes rendericen.
*
* @return \ROITheme\Shared\Domain\Contracts\CriticalCSSCollectorInterface
* @return \ROITheme\Shared\Infrastructure\Services\CriticalCSSService
*/
function roi_get_critical_css_collector(): \ROITheme\Shared\Domain\Contracts\CriticalCSSCollectorInterface {
static $collector = null;
function roi_get_critical_css_service(): \ROITheme\Shared\Infrastructure\Services\CriticalCSSService {
global $wpdb;
static $cssGenerator = null;
if ($collector === null) {
$collector = new \ROITheme\Shared\Infrastructure\Services\CriticalCSSCollector();
if ($cssGenerator === null) {
$cssGenerator = new \ROITheme\Shared\Infrastructure\Services\CSSGeneratorService();
}
return $collector;
return \ROITheme\Shared\Infrastructure\Services\CriticalCSSService::getInstance($wpdb, $cssGenerator);
}
// =============================================================================
@@ -205,23 +206,21 @@ function roi_render_component(string $componentName): string {
// Obtener renderer específico para el componente
$renderer = null;
// Crear instancia del CSSGeneratorService (reutilizable para todos los renderers que lo necesiten)
// Crear instancia del CSSGeneratorService (reutilizable para todos los renderers)
$cssGenerator = new \ROITheme\Shared\Infrastructure\Services\CSSGeneratorService();
// Obtener instancia singleton del CriticalCSSCollector
$criticalCollector = roi_get_critical_css_collector();
switch ($componentName) {
// Componentes con soporte de CSS Crítico (above-the-fold)
// Nota: Si is_critical=true, el CSS ya fue inyectado en <head> por CriticalCSSService
case 'top-notification-bar':
$renderer = new \ROITheme\Public\TopNotificationBar\Infrastructure\Ui\TopNotificationBarRenderer($cssGenerator, $criticalCollector);
$renderer = new \ROITheme\Public\TopNotificationBar\Infrastructure\Ui\TopNotificationBarRenderer($cssGenerator);
break;
case 'navbar':
$renderer = new \ROITheme\Public\Navbar\Infrastructure\Ui\NavbarRenderer($cssGenerator, $criticalCollector);
$renderer = new \ROITheme\Public\Navbar\Infrastructure\Ui\NavbarRenderer($cssGenerator);
break;
case 'hero':
error_log("ROI Theme DEBUG: Creating HeroRenderer");
$renderer = new \ROITheme\Public\Hero\Infrastructure\Ui\HeroRenderer($cssGenerator, $criticalCollector);
$renderer = new \ROITheme\Public\Hero\Infrastructure\Ui\HeroRenderer($cssGenerator);
error_log("ROI Theme DEBUG: HeroRenderer created successfully");
break;
@@ -283,13 +282,16 @@ function roi_render_component(string $componentName): string {
/**
* Registra el hook para inyectar CSS crítico en <head>
*
* IMPORTANTE: El HooksRegistrar usa la misma instancia singleton del collector
* que usan los Renderers, garantizando que el CSS recolectado se inyecte
* correctamente en wp_head con prioridad 1 (muy temprano).
* FLUJO:
* 1. wp_head (priority 1) → CriticalCSSService::render()
* 2. CriticalCSSService consulta BD por componentes con is_critical=true
* 3. Genera CSS usando los métodos públicos generateCSS() de los Renderers
* 4. Output: <style id="roi-critical-css">...</style>
* 5. Cuando los Renderers ejecutan, detectan is_critical y omiten CSS inline
*/
add_action('after_setup_theme', function() {
$criticalCollector = roi_get_critical_css_collector();
$hooksRegistrar = new \ROITheme\Shared\Infrastructure\Wordpress\CriticalCSSHooksRegistrar($criticalCollector);
$criticalCSSService = roi_get_critical_css_service();
$hooksRegistrar = new \ROITheme\Shared\Infrastructure\Wordpress\CriticalCSSHooksRegistrar($criticalCSSService);
$hooksRegistrar->register();
});