diff --git a/Test/Unit/ViewModel/SpeculationRulesTest.php b/Test/Unit/ViewModel/SpeculationRulesTest.php index 39c70ef..e6d66b8 100644 --- a/Test/Unit/ViewModel/SpeculationRulesTest.php +++ b/Test/Unit/ViewModel/SpeculationRulesTest.php @@ -5,6 +5,7 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\UrlInterface; +use Magento\Framework\View\DesignInterface; use Magento\Framework\View\Element\Block\ArgumentInterface; use Magento\Store\Model\ScopeInterface; use MageOS\ThemeOptimization\ViewModel\SpeculationRules; @@ -27,6 +28,11 @@ class SpeculationRulesTest extends TestCase */ private $serializerMock; + /** + * @var DesignInterface + */ + private $viewDesignMock; + /** * @var SpeculationRules */ @@ -37,11 +43,13 @@ protected function setUp(): void $this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class); $this->urlBuilderMock = $this->createMock(UrlInterface::class); $this->serializerMock = $this->createMock(SerializerInterface::class); + $this->viewDesignMock = $this->createMock(DesignInterface::class); $this->speculationRules = new SpeculationRules( $this->scopeConfigMock, $this->urlBuilderMock, - $this->serializerMock + $this->serializerMock, + $this->viewDesignMock ); } diff --git a/ViewModel/SpeculationRules.php b/ViewModel/SpeculationRules.php index cd98f2d..29567da 100644 --- a/ViewModel/SpeculationRules.php +++ b/ViewModel/SpeculationRules.php @@ -6,18 +6,22 @@ use Magento\Framework\Serialize\SerializerInterface; use Magento\Framework\UrlInterface; use Magento\Framework\View\Element\Block\ArgumentInterface; +use Magento\Framework\View\DesignInterface; use Magento\Store\Model\ScopeInterface; class SpeculationRules implements ArgumentInterface { protected const CONFIG_PATH = 'system/speculation_rules/'; - protected const FETCH_MODES = ['prefetch', 'prerender']; + protected const MODE_PREFETCH = 'prefetch'; + protected const MODE_PRERENDER = 'prerender'; + protected const FETCH_MODES = [self::MODE_PREFETCH, self::MODE_PRERENDER]; protected const EAGERNESS_MODES = ['conservative', 'moderate', 'eager']; public function __construct( protected ScopeConfigInterface $scopeConfig, protected UrlInterface $urlBuilder, protected SerializerInterface $serializer, + protected DesignInterface $viewDesign ) { } @@ -35,7 +39,7 @@ public function getMode(): string return $mode; } - return 'prefetch'; + return self::MODE_PREFETCH; } public function getEagerness(): string @@ -49,6 +53,47 @@ public function getEagerness(): string return 'moderate'; } + /** + * Check if the current mode is prerender + * + * @return bool + */ + public function isPrerenderMode(): bool + { + return $this->getMode() === self::MODE_PRERENDER; + } + + /** + * Get prerendering change script for customer data reinitialization + * Returns script only when prerender mode is enabled + * Uses different approaches for Hyva vs Luma themes + * + * @return string + */ + public function getPrerenderingScript(): string + { + if (!$this->isPrerenderMode()) { + return ''; + } + + // Hyva theme uses a custom event, Luma uses RequireJS + $reloadAction = $this->isHyva() + ? "window.dispatchEvent(new CustomEvent('reload-customer-section-data'));" + : "require(['Magento_Customer/js/customer-data'], customerData => { + customerData.init(); + });"; + + return << { + if (document.prerendering) { + document.addEventListener("prerenderingchange", () => { + $reloadAction + }, { once: true }); + } + })(); + JS; + } + public function getSpeculationRules(): array { // Possible future development: add support for multiple modes and rulesets at once. @@ -148,4 +193,21 @@ public function getExcludedSelectors(): array return $rules; } + + /** + * Check if current theme is Hyva or extends from Hyva + * + * @return bool + */ + private function isHyva(): bool + { + $theme = $this->viewDesign->getDesignTheme(); + while ($theme) { + if (strpos($theme->getCode(), 'Hyva/') === 0) { + return true; + } + $theme = $theme->getParentTheme(); + } + return false; + } } diff --git a/view/frontend/templates/speculation-rules.phtml b/view/frontend/templates/speculation-rules.phtml index 1c8f32d..067d61c 100644 --- a/view/frontend/templates/speculation-rules.phtml +++ b/view/frontend/templates/speculation-rules.phtml @@ -12,9 +12,17 @@ use MageOS\ThemeOptimization\ViewModel\SpeculationRules; /** @var SpeculationRules $viewModel */ $viewModel = $block->getViewModel(); ?> -renderTag( +renderTag( 'script', ['type' => 'speculationrules'], $viewModel->getSpeculationRulesJson(), false ) ?> +getPrerenderingScript()): ?> + renderTag( + 'script', + ['type' => 'text/javascript'], + $prerenderingScript, + false + ) ?> +