```
✨ feat(ViteAssetExtension): Ajoute la gestion des favicons et améliore la gestion des scripts. ⚙️ chore(pwa): Met à jour le nom et l'URL de démarrage du PWA. ```
This commit is contained in:
@@ -30,9 +30,9 @@ pwa:
|
||||
max_age: 3600
|
||||
manifest:
|
||||
enabled: true
|
||||
name: "Intranet Lukikevent"
|
||||
short_name: "Intranet"
|
||||
start_url: "app_home"
|
||||
name: "Réservation Lukikevent"
|
||||
short_name: "Réservation Lukikevent"
|
||||
start_url: "reservation"
|
||||
display: "standalone"
|
||||
background_color: "#ffffff"
|
||||
theme_color: "#f4c842"
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Twig;
|
||||
|
||||
use Detection\MobileDetect;
|
||||
use Jaybizzle\CrawlerDetect\CrawlerDetect;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
use Nelmio\SecurityBundle\EventListener\ContentSecurityPolicyListener;
|
||||
|
||||
class ViteAssetExtension extends AbstractExtension
|
||||
{
|
||||
private const CACHE_KEY = 'vite_manifest';
|
||||
const CACHE_KEY = 'vite_manifest';
|
||||
private ?array $manifestData = null;
|
||||
private readonly bool $isDev;
|
||||
|
||||
@@ -22,9 +18,8 @@ class ViteAssetExtension extends AbstractExtension
|
||||
private readonly string $manifest,
|
||||
private readonly CacheItemPoolInterface $cache,
|
||||
private readonly ContentSecurityPolicyListener $cspListener,
|
||||
private readonly RequestStack $requestStack,
|
||||
) {
|
||||
$this->isDev = ($_ENV['VITE_LOAD'] ?? "1") === "0";
|
||||
$this->isDev = $_ENV['VITE_LOAD'] === "0";
|
||||
}
|
||||
|
||||
public function getFunctions(): array
|
||||
@@ -32,29 +27,25 @@ class ViteAssetExtension extends AbstractExtension
|
||||
return [
|
||||
new TwigFunction('vite_asset', $this->asset(...), ['is_safe' => ['html']]),
|
||||
new TwigFunction('isMobile', $this->isMobile(...), ['is_safe' => ['html']]),
|
||||
new TwigFunction('vite_favicons', $this->favicons(...), ['is_safe' => ['html']])
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le nonce pour les scripts via le Listener de Nelmio
|
||||
*/
|
||||
private function getNonce(): string
|
||||
{
|
||||
// Dans la v3.8, on utilise getNonce('script') sur le listener
|
||||
return $this->cspListener->getNonce('script');
|
||||
}
|
||||
|
||||
public function isMobile(): bool
|
||||
{
|
||||
$detect = new MobileDetect();
|
||||
return $detect->isMobile() || $detect->isTablet();
|
||||
}
|
||||
|
||||
private function isBot(): bool
|
||||
{
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
if (!$request) return false;
|
||||
|
||||
$crawlerDetect = new CrawlerDetect($request->headers->all());
|
||||
return $crawlerDetect->isCrawler();
|
||||
}
|
||||
|
||||
private function getNonce(): string
|
||||
{
|
||||
return $this->cspListener->getNonce('script');
|
||||
}
|
||||
|
||||
private function loadManifest(): void
|
||||
{
|
||||
if ($this->manifestData === null) {
|
||||
@@ -91,47 +82,35 @@ HTML;
|
||||
{
|
||||
$this->loadManifest();
|
||||
$nonce = $this->getNonce();
|
||||
$isBot = $this->isBot();
|
||||
|
||||
$entryData = $this->manifestData[$entry] ?? null;
|
||||
if (!$entryData) return '';
|
||||
$file = $this->manifestData[$entry]['file'] ?? '';
|
||||
$css = $this->manifestData[$entry]['css'] ?? [];
|
||||
|
||||
$file = $entryData['file'];
|
||||
$css = $entryData['css'] ?? [];
|
||||
$imports = $entryData['imports'] ?? []; // Les fichiers JS secondaires (chunks)
|
||||
|
||||
$html = '';
|
||||
|
||||
// 1. On charge le fichier JS principal (ex: reserve.js)
|
||||
$html .= <<<HTML
|
||||
$html = <<<HTML
|
||||
<script type="module" src="/build/{$file}" crossorigin="anonymous" nonce="{$nonce}" defer></script>
|
||||
HTML;
|
||||
|
||||
// 2. On traite les imports (chunks comme Sentry BrowserTracing)
|
||||
foreach ($imports as $importKey) {
|
||||
$importData = $this->manifestData[$importKey] ?? null;
|
||||
if (!$importData) continue;
|
||||
|
||||
$importFile = $importData['file'];
|
||||
|
||||
// LOGIQUE DE FILTRAGE :
|
||||
// Si c'est un bot ET que le fichier contient "browserTracing" dans son nom d'origine
|
||||
if ($isBot && str_contains($importKey, 'browserTracingIntegration')) {
|
||||
$html .= "";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sinon on l'ajoute normalement
|
||||
$html .= <<<HTML
|
||||
<link rel="modulepreload" href="/build/{$importFile}" nonce="{$nonce}">
|
||||
HTML;
|
||||
}
|
||||
|
||||
// 3. On ajoute le CSS
|
||||
foreach ($css as $cssFile) {
|
||||
$html .= '<link rel="stylesheet" href="/build/'.$cssFile.'" crossorigin="anonymous"/>';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function favicons(): string
|
||||
{
|
||||
return $this->isDev ? '<link rel="icon" href="/favicon.ico">' : $this->faviconsProd();
|
||||
}
|
||||
|
||||
private function faviconsProd(): string
|
||||
{
|
||||
$this->loadManifest();
|
||||
$faviconHtml = "";
|
||||
foreach ($this->manifestData as $key => $favicon) {
|
||||
if(!str_contains($key, ".js") && isset($favicon['file'])) {
|
||||
$faviconHtml .= '<link rel="icon" href="/build/'.$favicon['file'].'" type="image/x-icon">';
|
||||
}
|
||||
}
|
||||
return $faviconHtml;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user