Skip to content

Commit

Permalink
add RenderAssetTagEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
lhapaipai committed Oct 22, 2023
1 parent 6f10979 commit 9b989f6
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 24 deletions.
2 changes: 1 addition & 1 deletion install/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"license": "UNLICENSED",
"devDependencies": {
"vite": "^4.0",
"vite-plugin-symfony": "^4.0"
"vite-plugin-symfony": "^5.0"
}
}
18 changes: 10 additions & 8 deletions src/Asset/EntrypointRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public function renderScripts(string $entryName, array $options = [], $buildName

$content = [];
$viteServer = $this->entrypointsLookup->getViteServer($buildName);
$isBuild = $this->entrypointsLookup->isBuild($buildName);

if (false !== $viteServer) {
// vite server is active
Expand Down Expand Up @@ -90,7 +91,7 @@ public function renderScripts(string $entryName, array $options = [], $buildName
'src' => $this->completeURL($fileWithHash['path'], $useAbsoluteUrl),
'integrity' => $fileWithHash['hash'],
], $options['attr'] ?? []);
$content[] = $this->tagRenderer->renderScriptFile($attributes, '', $buildName);
$content[] = $this->tagRenderer->renderScriptFile($attributes, '', $buildName, $isBuild);
}

/* legacy js scripts */
Expand All @@ -103,7 +104,7 @@ public function renderScripts(string $entryName, array $options = [], $buildName
'id' => $id,
'crossorigin' => true,
'class' => 'vite-legacy-entry',
], $this->tagRenderer->getSystemJSInlineCode($id), $buildName);
], $this->tagRenderer->getSystemJSInlineCode($id), $buildName, $isBuild);
}

return implode(PHP_EOL, $content);
Expand Down Expand Up @@ -132,32 +133,33 @@ public function renderLinks(string $entryName, array $options = [], $buildName =
}

$useAbsoluteUrl = $this->shouldUseAbsoluteURL($options, $buildName);
$isBuild = $this->entrypointsLookup->isBuild($buildName);

$content = [];

foreach ($this->entrypointsLookup->getCSSFiles($entryName, $buildName) as $fileWithHash) {
$content[] = $this->tagRenderer->renderLinkStylesheet($this->completeURL($fileWithHash['path'], $useAbsoluteUrl), array_merge([
'integrity' => $fileWithHash['hash'],
], $options['attr'] ?? []), $buildName);
], $options['attr'] ?? []), $buildName, $isBuild);
}

if ($this->entrypointsLookup->isProd($buildName)) {
if ($this->entrypointsLookup->isBuild($buildName)) {
foreach ($this->entrypointsLookup->getJavascriptDependencies($entryName, $buildName) as $fileWithHash) {
if (false === \in_array($fileWithHash['path'], $this->returnedPreloadedScripts, true)) {
$content[] = $this->tagRenderer->renderLinkPreload($this->completeURL($fileWithHash['path'], $useAbsoluteUrl), [
'integrity' => $fileWithHash['hash'],
], $buildName);
], $buildName, $isBuild);
$this->returnedPreloadedScripts[] = $fileWithHash['path'];
}
}
}

if ($this->entrypointsLookup->isProd($buildName) && isset($options['preloadDynamicImports']) && true === $options['preloadDynamicImports']) {
if ($this->entrypointsLookup->isBuild($buildName) && isset($options['preloadDynamicImports']) && true === $options['preloadDynamicImports']) {
foreach ($this->entrypointsLookup->getJavascriptDynamicDependencies($entryName, $buildName) as $fileWithHash) {
if (false === \in_array($fileWithHash['path'], $this->returnedPreloadedScripts, true)) {
$content[] = $this->tagRenderer->renderLinkPreload($this->completeURL($fileWithHash['path'], $useAbsoluteUrl), [
'integrity' => $fileWithHash['hash'],
], $buildName);
], $buildName, $isBuild);
$this->returnedPreloadedScripts[] = $fileWithHash['path'];
}
}
Expand All @@ -172,7 +174,7 @@ public function getMode(string $buildName = null): ?string
return null;
}

return $this->entrypointsLookup->isProd() ? 'prod' : 'dev';
return $this->entrypointsLookup->isBuild() ? 'build' : 'dev';
}

public function reset()
Expand Down
8 changes: 4 additions & 4 deletions src/Asset/EntrypointsLookup.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ private function getInfos($buildName = null): array
}
$entrypointsFilePath = $this->buildsInfos[$buildName]['entryPointsPath'];
$fileInfos = json_decode(file_get_contents($entrypointsFilePath), true);
if (!isset($fileInfos['isProd'], $fileInfos['entryPoints'], $fileInfos['viteServer'])) {
throw new \Exception($entrypointsFilePath.' : isProd, entryPoints or viteServer not exists');
if (!isset($fileInfos['isBuild'], $fileInfos['entryPoints'], $fileInfos['viteServer'])) {
throw new \Exception($entrypointsFilePath.' : isBuild, entryPoints or viteServer not exists');
}

$this->buildsInfos[$buildName]['infos'] = $fileInfos;
Expand All @@ -63,9 +63,9 @@ public function isLegacyPluginEnabled($buildName = null): bool
return array_key_exists('legacy', $buildInfos) && true === $buildInfos['legacy'];
}

public function isProd($buildName = null): bool
public function isBuild($buildName = null): bool
{
return $this->getInfos($buildName)['isProd'];
return $this->getInfos($buildName)['isBuild'];
}

public function getViteServer($buildName = null)
Expand Down
49 changes: 38 additions & 11 deletions src/Asset/TagRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

namespace Pentatrion\ViteBundle\Asset;

use Pentatrion\ViteBundle\Event\RenderAssetTagEvent;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

class TagRenderer
{
private $defaultBuild;
private $builds;
private string $defaultBuild;
private array $builds;
private EventDispatcherInterface $eventDispatcher;

// https://gist.github.com/samthor/64b114e4a4f539915a95b91ffd340acc
public const SAFARI10_NO_MODULE_FIX = '<!-- SAFARI10_NO_MODULE_FIX --><script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>';
Expand Down Expand Up @@ -36,10 +40,12 @@ class TagRenderer

public function __construct(
$defaultBuild = 'default',
$builds = []
$builds = [],
EventDispatcherInterface $eventDispatcher = null
) {
$this->defaultBuild = $defaultBuild;
$this->builds = $builds;
$this->eventDispatcher = $eventDispatcher;
}

public function getSystemJSInlineCode($id): string
Expand All @@ -58,18 +64,25 @@ public function renderReactRefreshInline($devServerUrl): string
</script>'.PHP_EOL;
}

public function renderScriptFile($extraAttributes = [], $content = '', $buildName = null): string
public function renderScriptFile($extraAttributes = [], $content = '', $buildName = null, $isBuild): string

Check failure on line 67 in src/Asset/TagRenderer.php

View workflow job for this annotation

GitHub Actions / CI (8.1)

Deprecated in PHP 8.0: Required parameter $isBuild follows optional parameter $buildName.
{
if (is_null($buildName)) {
$buildName = $this->defaultBuild;
}

$attributes = array_merge($this->builds[$buildName]['script_attributes'], $extraAttributes);
$event = new RenderAssetTagEvent(
RenderAssetTagEvent::TYPE_SCRIPT,
array_merge($this->builds[$buildName]['script_attributes'], $extraAttributes),
$isBuild
);
if (null !== $this->eventDispatcher) {
$event = $this->eventDispatcher->dispatch($event);
}

return $this->renderTag('script', $attributes, $content);
return $this->renderTag('script', $event->getAttributes(), $content);
}

public function renderLinkStylesheet($fileName, $extraAttributes = [], $buildName = null): string
public function renderLinkStylesheet($fileName, $extraAttributes = [], $buildName = null, $isBuild): string

Check failure on line 85 in src/Asset/TagRenderer.php

View workflow job for this annotation

GitHub Actions / CI (8.1)

Deprecated in PHP 8.0: Required parameter $isBuild follows optional parameter $buildName.
{
if (is_null($buildName)) {
$buildName = $this->defaultBuild;
Expand All @@ -80,12 +93,19 @@ public function renderLinkStylesheet($fileName, $extraAttributes = [], $buildNam
'href' => $fileName,
];

$attributes = array_merge($attributes, $this->builds[$buildName]['link_attributes'], $extraAttributes);
$event = new RenderAssetTagEvent(
RenderAssetTagEvent::TYPE_LINK,
array_merge($attributes, $this->builds[$buildName]['link_attributes'], $extraAttributes),
$isBuild
);
if (null !== $this->eventDispatcher) {
$event = $this->eventDispatcher->dispatch($event);
}

return $this->renderTag('link', $attributes);
return $this->renderTag('link', $event->getAttributes());
}

public function renderLinkPreload($fileName, $extraAttributes = [], $buildName = null): string
public function renderLinkPreload($fileName, $extraAttributes = [], $buildName = null, $isBuild): string

Check failure on line 108 in src/Asset/TagRenderer.php

View workflow job for this annotation

GitHub Actions / CI (8.1)

Deprecated in PHP 8.0: Required parameter $isBuild follows optional parameter $buildName.
{
if (is_null($buildName)) {
$buildName = $this->defaultBuild;
Expand All @@ -96,7 +116,14 @@ public function renderLinkPreload($fileName, $extraAttributes = [], $buildName =
'href' => $fileName,
];

$attributes = array_merge($attributes, $this->builds[$buildName]['link_attributes'], $extraAttributes);
$event = new RenderAssetTagEvent(
RenderAssetTagEvent::TYPE_PRELOAD,
array_merge($attributes, $this->builds[$buildName]['link_attributes'], $extraAttributes),
$isBuild
);
if (null !== $this->eventDispatcher) {
$event = $this->eventDispatcher->dispatch($event);
}

return $this->renderTag('link', $attributes);
}
Expand Down
67 changes: 67 additions & 0 deletions src/Event/RenderAssetTagEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

/*
* This file is inspired from the Symfony WebpackEncoreBundle package.
*/

namespace Pentatrion\ViteBundle\Event;

/**
* Dispatched each time a script or link tag is rendered.
*/
final class RenderAssetTagEvent
{
public const TYPE_SCRIPT = 'script';
public const TYPE_LINK = 'link';
public const TYPE_PRELOAD = 'preload';

private string $type;
private array $attributes;
private bool $isBuild;

public function __construct(string $type, array $attributes, bool $isBuild)
{
$this->type = $type;
$this->attributes = $attributes;
$this->isBuild = $isBuild;
}

public function isScriptTag(): bool
{
return self::TYPE_SCRIPT === $this->type;
}

public function isLinkTag(): bool
{
return self::TYPE_LINK === $this->type;
}

public function isPreloadTag(): bool
{
return self::TYPE_PRELOAD === $this->type;
}

public function getAttributes(): array
{
return $this->attributes;
}

public function isBuild(): bool
{
return $this->isBuild;
}

/**
* @param string $name The attribute name
* @param string|bool $value Value can be "true" to have an attribute without a value (e.g. "defer")
*/
public function setAttribute(string $name, $value): void
{
$this->attributes[$name] = $value;
}

public function removeAttribute(string $name): void
{
unset($this->attributes[$name]);
}
}
1 change: 1 addition & 0 deletions src/Resources/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ services:
arguments:
- default
- []
- "@?event_dispatcher"
public: true

Pentatrion\ViteBundle\Asset\EntrypointsLookup:
Expand Down

0 comments on commit 9b989f6

Please sign in to comment.