Moderní JS frameworky a tradiční PHP hosting?
Chtěli byste zkusit moderní JavaScriptový framework jako Angular, React nebo Vue, ale máte k dispozici jen PHP hosting? Jednou z možností je poohlédnout se po službách jako Netlify nebo Vercel, obě poskytují tzv. JAM stack hosting zdarma. Pokud se ovšem nechcete vzdát svého PHP hostingu, chcete zkusit JavaScriptovým framework a zároveň myslíte na SEO, je tu ještě další možnost. Není ovšem rozhodně určená pro velké projekty nebo weby, které stojí na co nejlepší SEO optimalizaci, byť ta je v tomto případě menší problém.
Řekněme, že máme hotový front-end, zbuildění jako SPA (single page application) a nahraný na testovacím FTP. Dál vytvoříme soubor ssr-index.php
. Do něj následně vložíme veškeré funkce pro zobrazení dat z API robotům a crawlerům. Ne, nemusíte se bát, nebudete muset kopírovat všechen HTML kód z vašeho front-endu.
PHP server side rendering
PHP nabízí funkci file_get_contents
, tu můžeme snadno využít ke komunikaci s naší API. Získanou odpověď pak převést do PHP objektu či pole a s daty dále pracovat. Předpokladem úspěchu je také fakt, že v rámci URL se nachází alespoň jeden identifikátor příspěvku či stránky, jejichž data chceme načíst. V mém příkladě to bude slug. První část souboru ssr-index.php
tedy bude vypadat následovně:
1<?php 2 3$SITE_ROOT = "http://example.com"; 4 5if ($_GET['slug']) { 6 $response = file_get_contents($SITE_ROOT.'?slug='.$_GET['slug']); 7 $jsonData = json_decode($response); 8 9 if ($jsonData) { 10 renderPage($jsonData, $_GET['slug']); 11 } 12} else { 13 $jsonData = json_decode('{ 14 "title": "Název stránky", 15 "content": "Obsah stránky" 16 }'); 17 renderPage($jsonData, ''); 18}
Pro lepší přehlednost si na začátku souboru nadefinujeme tzv. root URL. Následně, pokud se v rámci adresy nachází GET hodnota slug zavoláme skrze file_get_contents
API a odpověď převedeme pomocí json_decode
do PHP objektu. Odpověď z naší API je JSON, pokud pracujete s jinými daty, bude potřeba jiná transformační funkce. Pokud se transformace do PHP objektu zdařila a proměnná nese nějakou hodnotu, vykreslíme HTML stránku. V případě, že GET parametr nebyl přítomen v rámci URL adresy, můžeme vykreslit prázdnou tzv. fallback stránku, neboť se robot nachází pravděpodobně na úvodní stránce. Příkladu chybí situace, kdy API vrátí odpověď s chybovým kódem, to by chtělo také ošetřit.
V obou případech funkce renderPage
zajistí vykreslení základní HTML stránky. V našem příkladu si vystačím jen s obyčejným HTML a několika meta tagy, nicméně meze se nekladou a můžete si pohrát i s podobou této stránky. Nicméně je vcelku zbytečné ji jakkoliv designovat. Zaměřil bych se tedy spíše na sémantiku.
1function renderPage($data, $slug) { 2 ?> 3 <!DOCTYPE html> 4 <html lang="cs"> 5 <head> 6 <meta charset="UTF-8" /> 7 <title>Název stránky</title> 8 <meta property="og:title" content="<?php echo $data->title; ?>" /> 9 <meta property="og:description" content="<?php echo preg_replace('/<\/?[^>]+(>|$)/m', '',$data->excerpt); ?>" /> 10 <meta property="og:site_name" content="Název stránky" /> 11 <meta property="og:image" content="<?php echo $data->image; ?>" /> 12 <meta property="og:type" content="article" /> 13 <meta property="og:url" content="https://example.com/<?php echo $slug; ?>" /> 14 <meta name="twitter:card" content="summary_large_image" /> 15 </head> 16 <body> 17 <main> 18 <h1><?php echo $data->title; ?></h1> 19 <?php echo $data->content; ?> 20 </main> 21 </body> 22 <script type="application/ld+json"> 23 { 24 "@context":"http://schema.org", 25 "@type":"Article", 26 "name": "<?php echo $data->title; ?>", 27 "headline": "<?php echo $data->title; ?>", 28 "datePublished": "<?php echo $data->date; ?>", 29 "articleBody": "<?php echo preg_replace('/<\/?[^>]+(>|$)/m', '',$data->content); ?>", 30 "abstract": "<?php echo preg_replace('/<\/?[^>]+(>|$)/m', '',$data->excerpt); ?>", 31 "url": "https://example.com/<?php echo $slug; ?>", 32 "publisher": { 33 "@type": "Organization", 34 "name": "Název stránky" 35 } 36 </script> 37 </html> 38 <?php 39}
Jak je z ústřižku patrné, vykreslená stránka bude obsahovat základní meta tady, dále také OpenGraph hlavičky pro zobrazení na sociálních sítích a JSON+LD schéma pro rich results. V samotném těle jsem si vystačil pouze s pro nadpis H1 a HTML obsahem příspěvku. Zde je ovšem prostor přidat tagů a informací více.
Jak o tom říct robotům?
Zbývá tedy přesměrovat roboty na ssr-index.php
. Za tímto účelem je potřeba upravit soubor .htaccess
. Předpokládejme, že máte standardní hosting s RewriteEngine On
v opačném případě je nutné jej zapnout.
1 <IfModule mod_rewrite.c> 2 RewriteEngine On 3 4 # allow social media crawlers to work by redirecting them to a server-rendered static version on the page 5 RewriteCond %{HTTP_USER_AGENT} (facebookexternalhit/[0-9]|Twitterbot|Pinterest|Facebot|Google|Ads|SeznamBot|Bing|Telegram|Discord|Whatsapp|FreshBot) 6 RewriteRule ^(.*)$ ssr-index.php?slug=$1 [QSA,L] 7 8 RewriteCond %{REQUEST_FILENAME} !-f 9 RewriteCond %{REQUEST_URI} !api 10 RewriteRule ^(.*)$ index.html [QSA,L] 11</IfModule>
Jak je možno vidět z ústřižku, pokud USER-AGENT návštěvníka odpovídá některému z definovaných v seznamu, dojde k přesměrování na soubor ssr-index.php
, v opačném případě pokračuje návštěvník na soubor index.html
, tedy klasický web.
Závěrem
Jak si lze všimnout z ústřižků, celé řešení má řadu úskalí, počínaje nutností definovat seznam robotů a konče tvorbou speciální stránky, určené pro komunikaci s API. Nejedná se proto o řešení, které bych doporučoval na velké weby či weby jimž záleží na 100% spolehlivosti v SEO. Je to spíše řešení pro menší weby, které si nezakládají na 100% SEO. Je to řešení, které ovšem může poskytnout dobrý odrazový můstek pro přechod z tradičního hostingu k novým službám.