feat(pagespeed): implementar campo is_critical para CSS crítico dinámico (Phase 4.2)
Implementación completa del sistema de Critical CSS dinámico según plan 13.01: Domain Layer: - Crear CriticalCSSCollectorInterface para DIP compliance Infrastructure Layer: - Implementar CriticalCSSCollector (singleton via DIContainer) - Crear CriticalCSSHooksRegistrar para inyección en wp_head - Actualizar DIContainer con getCriticalCSSCollector() Schemas: - Agregar campo is_critical a navbar, top-notification-bar, hero - Sincronizar con BD (18+39+31 campos) Renderers (navbar, top-notification-bar, hero): - Inyectar CriticalCSSCollectorInterface via constructor - Lógica condicional: si is_critical=true → CSS a <head> Admin (FormBuilders + FieldMappers): - Toggle "CSS Crítico" en sección visibility - Mapeo AJAX para persistencia Beneficios: - LCP optimizado: CSS crítico inline en <head> - Above-the-fold rendering sin FOUC - Componentes configurables desde admin panel 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,7 @@ final class HeroFieldMapper implements FieldMapperInterface
|
||||
'heroShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
|
||||
'heroShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
|
||||
'heroShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
|
||||
'heroIsCritical' => ['group' => 'visibility', 'attribute' => 'is_critical'],
|
||||
|
||||
// Content
|
||||
'heroShowCategories' => ['group' => 'content', 'attribute' => 'show_categories'],
|
||||
|
||||
@@ -103,7 +103,7 @@ final class HeroFormBuilder
|
||||
$html .= ' </div>';
|
||||
|
||||
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'posts');
|
||||
$html .= ' <div class="mb-0 mt-3">';
|
||||
$html .= ' <div class="mb-2 mt-3">';
|
||||
$html .= ' <label for="heroShowOnPages" class="form-label small mb-1 fw-semibold">';
|
||||
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
|
||||
$html .= ' Mostrar en';
|
||||
@@ -116,6 +116,20 @@ final class HeroFormBuilder
|
||||
$html .= ' </select>';
|
||||
$html .= ' </div>';
|
||||
|
||||
// Switch: CSS Crítico
|
||||
$isCritical = $this->renderer->getFieldValue($componentId, 'visibility', 'is_critical', true);
|
||||
$html .= ' <div class="mb-0 mt-3">';
|
||||
$html .= ' <div class="form-check form-switch">';
|
||||
$html .= ' <input class="form-check-input" type="checkbox" id="heroIsCritical" ';
|
||||
$html .= checked($isCritical, true, false) . '>';
|
||||
$html .= ' <label class="form-check-label small" for="heroIsCritical">';
|
||||
$html .= ' <i class="bi bi-lightning-charge me-1" style="color: #FF8600;"></i>';
|
||||
$html .= ' <strong>CSS Crítico</strong>';
|
||||
$html .= ' <small class="text-muted d-block">Inyectar CSS en <head> para optimizar LCP</small>';
|
||||
$html .= ' </label>';
|
||||
$html .= ' </div>';
|
||||
$html .= ' </div>';
|
||||
|
||||
$html .= ' </div>';
|
||||
$html .= '</div>';
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ final class NavbarFieldMapper implements FieldMapperInterface
|
||||
'navbarShowDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
|
||||
'navbarShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
|
||||
'navbarSticky' => ['group' => 'visibility', 'attribute' => 'sticky_enabled'],
|
||||
'navbarIsCritical' => ['group' => 'visibility', 'attribute' => 'is_critical'],
|
||||
|
||||
// Layout
|
||||
'navbarContainerType' => ['group' => 'layout', 'attribute' => 'container_type'],
|
||||
|
||||
@@ -119,7 +119,7 @@ final class NavbarFormBuilder
|
||||
|
||||
// Switch: Sticky
|
||||
$sticky = $this->renderer->getFieldValue($componentId, 'visibility', 'sticky_enabled', true);
|
||||
$html .= ' <div class="mb-0">';
|
||||
$html .= ' <div class="mb-2">';
|
||||
$html .= ' <div class="form-check form-switch">';
|
||||
$html .= ' <input class="form-check-input" type="checkbox" id="navbarSticky" name="visibility[sticky_enabled]" ';
|
||||
$html .= checked($sticky, true, false) . '>';
|
||||
@@ -129,6 +129,19 @@ final class NavbarFormBuilder
|
||||
$html .= ' </div>';
|
||||
$html .= ' </div>';
|
||||
|
||||
// Switch: CSS Crítico
|
||||
$isCritical = $this->renderer->getFieldValue($componentId, 'visibility', 'is_critical', true);
|
||||
$html .= ' <div class="mb-0">';
|
||||
$html .= ' <div class="form-check form-switch">';
|
||||
$html .= ' <input class="form-check-input" type="checkbox" id="navbarIsCritical" name="visibility[is_critical]" ';
|
||||
$html .= checked($isCritical, true, false) . '>';
|
||||
$html .= ' <label class="form-check-label small" for="navbarIsCritical">';
|
||||
$html .= ' <strong>CSS Crítico</strong>';
|
||||
$html .= ' <small class="text-muted d-block">Inyectar CSS en <head> para optimizar LCP</small>';
|
||||
$html .= ' </label>';
|
||||
$html .= ' </div>';
|
||||
$html .= ' </div>';
|
||||
|
||||
$html .= ' </div>';
|
||||
$html .= '</div>';
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ final class TopNotificationBarFieldMapper implements FieldMapperInterface
|
||||
'topBarShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
|
||||
'topBarShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
|
||||
'topBarShowOnPages' => ['group' => 'visibility', 'attribute' => 'show_on_pages'],
|
||||
'topBarIsCritical' => ['group' => 'visibility', 'attribute' => 'is_critical'],
|
||||
|
||||
// Content
|
||||
'topBarIconClass' => ['group' => 'content', 'attribute' => 'icon_class'],
|
||||
|
||||
@@ -107,7 +107,7 @@ final class TopNotificationBarFormBuilder
|
||||
|
||||
// Select: Show on Pages
|
||||
$showOnPages = $this->renderer->getFieldValue($componentId, 'visibility', 'show_on_pages', 'all');
|
||||
$html .= ' <div class="mb-0 mt-3">';
|
||||
$html .= ' <div class="mb-2 mt-3">';
|
||||
$html .= ' <label for="topBarShowOnPages" class="form-label small mb-1 fw-semibold" style="color: #495057;">';
|
||||
$html .= ' <i class="bi bi-file-earmark-text me-1" style="color: #FF8600;"></i>';
|
||||
$html .= ' Mostrar en';
|
||||
@@ -120,6 +120,20 @@ final class TopNotificationBarFormBuilder
|
||||
$html .= ' </select>';
|
||||
$html .= ' </div>';
|
||||
|
||||
// Switch: CSS Crítico
|
||||
$isCritical = $this->renderer->getFieldValue($componentId, 'visibility', 'is_critical', true);
|
||||
$html .= ' <div class="mb-0 mt-3">';
|
||||
$html .= ' <div class="form-check form-switch">';
|
||||
$html .= ' <input class="form-check-input" type="checkbox" id="topBarIsCritical" ';
|
||||
$html .= checked($isCritical, true, false) . '>';
|
||||
$html .= ' <label class="form-check-label small" for="topBarIsCritical" style="color: #495057;">';
|
||||
$html .= ' <i class="bi bi-lightning-charge me-1" style="color: #FF8600;"></i>';
|
||||
$html .= ' <strong>CSS Crítico</strong>';
|
||||
$html .= ' <small class="text-muted d-block">Inyectar CSS en <head> para optimizar LCP</small>';
|
||||
$html .= ' </label>';
|
||||
$html .= ' </div>';
|
||||
$html .= ' </div>';
|
||||
|
||||
$html .= ' </div>';
|
||||
$html .= '</div>';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user