Refactorisation de Vite

This commit is contained in:
Sylvain Philip 2024-09-09 15:39:55 +02:00
parent bebcf91515
commit e6ac7c6c85
4 changed files with 56 additions and 88 deletions

View File

@ -2,106 +2,78 @@
namespace app\lib; namespace app\lib;
use Piko; use Piko;
use Piko\View;
use RuntimeException;
class Vite class Vite
{ {
// For a real-world example check here: private View $view;
// https://github.com/wp-bond/bond/blob/master/src/Tooling/Vite.php private array $manifest = [];
// https://github.com/wp-bond/boilerplate/tree/master/app/themes/boilerplate private string $viteHost = '';
private bool $dev = false;
// you might check @vitejs/plugin-legacy if you need to support older browsers public function __construct(View $view)
// https://github.com/vitejs/vite/tree/main/packages/plugin-legacy
/**
* Prints all the html entries needed for Vite
*/
public static function vite(string $entry): string
{ {
return implode("\n", [ $this->view = $view;
static::jsTag($entry),
static::jsPreloadImports($entry),
static::cssTag($entry)
]);
}
// Helpers to print tags $manifestFile = Piko::getAlias('@webroot/.vite/manifest.json');
private static function jsTag(string $entry): string
{ if (!file_exists($manifestFile) && !$this->dev) {
if (strpos($entry, '.js') === false) { throw new RuntimeException("Manifest file not found ($manifestFile)");
return '';
} }
$url = getenv('VITE_ENV') === 'dev' if (file_exists($manifestFile) && !$this->dev) {
? getenv('VITE_HOST') . Piko::getAlias('@vite_web/' . $entry) $manifest = file_get_contents($manifestFile);
: static::assetUrl($entry); $this->manifest = json_decode($manifest, true);
if (!$url) {
return '';
} }
return '<script type="module" crossorigin src="' . $url . '"></script>'; $this->dev = getenv('VITE_ENV') === 'dev';
$this->viteHost = getenv('VITE_HOST') ?: '';
} }
private static function jsPreloadImports(string $entry): string public function loadEntry(string $entry): void
{ {
if (getenv('VITE_ENV') === 'dev') { if ($this->dev) {
return ''; $this->loadJsFile($entry);
return;
} }
$res = ''; if (!isset($this->manifest[$entry])) {
throw new RuntimeException("Entry {$entry} not found in Vite manifest");
foreach (static::importsUrls($entry) as $url) {
$res .= '<link rel="modulepreload" href="'. $url. '">';
} }
return $res; if (isset($this->manifest[$entry]['file'])) {
} $this->loadJsFile($this->manifest[$entry]['file']);
private static function cssTag(string $entry): string
{
// Not needed on dev, it's inject by Vite
if (getenv('VITE_ENV') === 'dev' || strpos($entry, '.css') === false) {
return '';
} }
$url = static::assetUrl($entry); // Load JS imports
foreach ((array)$this->manifest[$entry]['imports'] as $import) {
if (!$url) { if (isset($this->manifest[$import]['file'])) {
return ''; $this->loadJsFile($this->manifest[$import]['file'], true);
}
return '<link rel="stylesheet" type="text/css" href="' . $url . '">';
}
// Helpers to locate files
private static function getManifest(): array
{
$content = file_get_contents(Piko::getAlias('@webroot/manifest.json'));
return json_decode($content, true);
}
private static function assetUrl(string $entry): string
{
$manifest = static::getManifest();
return isset($manifest[$entry])
? Piko::getAlias('@web/' . $manifest[$entry]['file'])
: '';
}
private static function importsUrls(string $entry): array
{
$urls = [];
$manifest = static::getManifest();
if (!empty($manifest[$entry]['imports'])) {
foreach ($manifest[$entry]['imports'] as $imports) {
$urls[] = Piko::getAlias('@web/' . $manifest[$imports]['file']);
} }
} }
return $urls; // Load Stylesheets
foreach ((array)$this->manifest[$entry]['css'] as $file) {
$this->view->registerCSSFile(Piko::getAlias('@web/' . $file));
}
}
private function loadJsFile($file, $import = false): void
{
if ($import && $this->dev) return;
if (strpos($file, '.js') === false) return;
$url = $this->dev ? rtrim($this->viteHost,'/') . '/' . $file : Piko::getAlias('@web/' . $file);
if ($import) {
$this->view->head[] = '<link rel="modulepreload" href="'. $url. '">';
return;
}
$this->view->endBody[] = '<script type="module" crossorigin src="' . $url . '"></script>';
} }
} }

View File

@ -1,16 +1,14 @@
<?php <?php
namespace app\modules\site; namespace app\modules\site;
use Piko;
use Piko\Module\Event\CreateControllerEvent; use Piko\Module\Event\CreateControllerEvent;
use Piko\Controller\Event\BeforeActionEvent; use Piko\Controller\Event\BeforeActionEvent;
use app\lib\Vite;
class Module extends \Piko\Module class Module extends \Piko\Module
{ {
public function bootstrap() public function bootstrap()
{ {
Piko::setAlias('@vite_web', '/dev');
// Instanciate once i18n to setup the language config // Instanciate once i18n to setup the language config
$this->application->getComponent('Piko\I18n'); $this->application->getComponent('Piko\I18n');
@ -21,7 +19,9 @@ class Module extends \Piko\Module
$view = $this->application->getComponent('Piko\View'); $view = $this->application->getComponent('Piko\View');
$view->params['user'] = $user; $view->params['user'] = $user;
$view->params['language'] = $this->application->language; $view->params['language'] = $this->application->language;
$view->attachBehavior('vite', 'app\lib\Vite::vite'); // $view->attachBehavior('vite', 'app\lib\Vite::vite');
$vite = new Vite($view);
$vite->loadEntry('main.js');
$userModule = $this->application->getModule('user'); $userModule = $this->application->getModule('user');
assert ($userModule instanceof \app\modules\user\Module); assert ($userModule instanceof \app\modules\user\Module);

View File

@ -14,7 +14,6 @@ if (!$this->title) $this->title = 'Openai';
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= $this->escape($this->title) ?></title> <title><?= $this->escape($this->title) ?></title>
<?= $this->head() ?> <?= $this->head() ?>
<?= $this->vite('main.css') ?>
</head> </head>
<body> <body>
<nav class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasNavbar" aria-labelledby="offcanvasNavbarLabel"> <nav class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasNavbar" aria-labelledby="offcanvasNavbarLabel">
@ -73,6 +72,5 @@ if (!$this->title) $this->title = 'Openai';
<?= $content ?> <?= $content ?>
<?= $this->endBody() ?> <?= $this->endBody() ?>
<?= $this->vite('main.js') ?>
</body> </body>
</html> </html>

View File

@ -11,13 +11,11 @@ if (!$this->title) $this->title = 'Openai';
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= $this->escape($this->title) ?></title> <title><?= $this->escape($this->title) ?></title>
<?= $this->head() ?> <?= $this->head() ?>
<?= $this->vite('main.css') ?>
</head> </head>
<body class="d-flex align-items-center py-4"> <body class="d-flex align-items-center py-4">
<?= $content ?> <?= $content ?>
<?= $this->endBody() ?> <?= $this->endBody() ?>
<?= $this->vite('main.js') ?>
</body> </body>
</html> </html>