Skip to content

Commit

Permalink
feat: Support setting defer attribute in Asset loader
Browse files Browse the repository at this point in the history
  • Loading branch information
hellopablo committed Dec 22, 2023
1 parent 90fd9b1 commit 5606a2d
Showing 1 changed file with 26 additions and 18 deletions.
44 changes: 26 additions & 18 deletions src/Common/Service/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,7 @@ public function addLibrary(string $sKey, array $aUrls): self
* @param string|null $sAssetLocation The asset's location
* @param string|null $sForceType The asset's file type (e.g., JS or CSS)
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
*
* @return $this
* @throws AssetException
Expand All @@ -570,7 +571,8 @@ public function load(
$mAssets,
string $sAssetLocation = null,
string $sForceType = null,
bool $bAsync = false
bool $bAsync = false,
bool $bDefer = false
): self {

$aAssets = (array) $mAssets;
Expand Down Expand Up @@ -598,13 +600,13 @@ public function load(

foreach ($aAssets as $sAsset) {
if (preg_match('#^https?://#', $sAsset)) {
$this->loadUrl($sAsset, $sForceType, $bAsync);
$this->loadUrl($sAsset, $sForceType, $bAsync, $bDefer);

} elseif (substr($sAsset, 0, 0) === '/') {
$this->loadAbsolute(substr($sAsset, 1), $sForceType, $bAsync);
$this->loadAbsolute(substr($sAsset, 1), $sForceType, $bAsync, $bDefer);

} else {
$this->{$sAssetLocationMethod}($sAsset, $sForceType, $bAsync, $sAssetLocation);
$this->{$sAssetLocationMethod}($sAsset, $sForceType, $bAsync, $bDefer, $sAssetLocation);
}
}

Expand All @@ -621,11 +623,12 @@ public function load(
* @param string $sAsset The asset to load
* @param string|null $sForceType Force a particular type of asset (i.e. JS or CSS)
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
*
* @return $this
* @throws AssetException
*/
protected function loadUrl(string $sAsset, ?string $sForceType, bool $bAsync): self
protected function loadUrl(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer): self
{
$sType = $this->determineType($sAsset, $sForceType);

Expand All @@ -637,11 +640,11 @@ protected function loadUrl(string $sAsset, ?string $sForceType, bool $bAsync): s

case static::TYPE_JS:
case static::TYPE_JS_FOOTER:
$this->aJs['URL-' . $sAsset] = [$sAsset, $bAsync];
$this->aJs['URL-' . $sAsset] = [$sAsset, $bAsync, $bDefer];
break;

case static::TYPE_JS_HEADER:
$this->aJsHeader['URL-' . $sAsset] = [$sAsset, $bAsync];
$this->aJsHeader['URL-' . $sAsset] = [$sAsset, $bAsync, $bDefer];
break;
}

Expand All @@ -656,11 +659,12 @@ protected function loadUrl(string $sAsset, ?string $sForceType, bool $bAsync): s
* @param string $sAsset The asset to load
* @param string|null $sForceType Force a particular type of asset (i.e. JS or CSS)
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
*
* @return $this
* @throws AssetException
*/
protected function loadAbsolute(string $sAsset, ?string $sForceType, bool $bAsync): self
protected function loadAbsolute(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer): self
{
$sType = $this->determineType($sAsset, $sForceType);

Expand All @@ -672,11 +676,11 @@ protected function loadAbsolute(string $sAsset, ?string $sForceType, bool $bAsyn

case static::TYPE_JS:
case static::TYPE_JS_FOOTER:
$this->aJs['ABSOLUTE-' . $sAsset] = [$this->buildUrl($sAsset), $bAsync];
$this->aJs['ABSOLUTE-' . $sAsset] = [$this->buildUrl($sAsset), $bAsync, $bDefer];
break;

case static::TYPE_JS_HEADER:
$this->aJsHeader['ABSOLUTE-' . $sAsset] = [$this->buildUrl($sAsset), $bAsync];
$this->aJsHeader['ABSOLUTE-' . $sAsset] = [$this->buildUrl($sAsset), $bAsync, $bDefer];
break;
}

Expand Down Expand Up @@ -753,15 +757,15 @@ public function output(string $sType = self::TYPE_ALL, bool $bOutput = true): ar
// Linked JS
if (!empty($this->aJs) && ($sType === static::TYPE_JS || $sType === static::TYPE_ALL)) {
foreach ($this->aJs as $aAsset) {
[$sAsset, $bAsync] = $aAsset;
$aOut[] = '<script ' . ($bAsync ? 'async ' : '') . 'src="' . $sAsset . '"></script>';
[$sAsset, $bAsync, $bDefer] = $aAsset;
$aOut[] = '<script ' . ($bAsync ? 'async ' : '') . ($bDefer ? 'defer ' : '') . 'src="' . $sAsset . '"></script>';
}
}

if (!empty($this->aJsHeader) && ($sType === static::TYPE_JS_HEADER || $sType === static::TYPE_ALL)) {
foreach ($this->aJsHeader as $aAsset) {
[$sAsset, $bAsync] = $aAsset;
$aOut[] = '<script ' . ($bAsync ? 'async ' : '') . 'src="' . $sAsset . '"></script>';
[$sAsset, $bAsync, $bDefer] = $aAsset;
$aOut[] = '<script ' . ($bAsync ? 'async ' : '') . ($bDefer ? 'defer ' : '') . 'src="' . $sAsset . '"></script>';
}
}

Expand Down Expand Up @@ -929,12 +933,13 @@ public function inline($mScript = null, string $sForceType = null, $sJsLocation
* @param string $sAsset The asset to load
* @param string|null $sForceType Force a particular type of asset (i.e. JS or CSS)
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
* @param array|string $mModule The module to load from
*
* @return $this
* @throws AssetException
*/
protected function loadModule(string $sAsset, ?string $sForceType, bool $bAsync, $mModule): self
protected function loadModule(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer, $mModule): self
{
if (is_array($mModule)) {
$sModule = !empty($mModule[0]) ? $mModule[0] : null;
Expand All @@ -958,13 +963,15 @@ protected function loadModule(string $sAsset, ?string $sForceType, bool $bAsync,
$this->aJs[$sKey] = [
$this->addCacheBuster($this->sBaseModuleUrl . $sModule . '/assets/js/' . $sAsset),
$bAsync,
$bDefer,
];
break;

case static::TYPE_JS_HEADER:
$this->aJsHeader[$sKey] = [
$this->addCacheBuster($this->sBaseModuleUrl . $sModule . '/assets/js/' . $sAsset),
$bAsync,
$bDefer,
];
break;
}
Expand Down Expand Up @@ -1103,11 +1110,12 @@ public function getCacheBuster(): ?string
* @param string $sAsset The asset to load
* @param string|null $sForceType Force a particular type of asset (i.e. JS or CSS)
* @param bool $bAsync Whether to load the asset asynchronously
* @param bool $bDefer Whether to defer loading the asset
*
* @return $this
* @throws AssetException
*/
protected function loadApp(string $sAsset, ?string $sForceType, bool $bAsync): self
protected function loadApp(string $sAsset, ?string $sForceType, bool $bAsync, bool $bDefer): self
{
$sType = $this->determineType($sAsset, $sForceType);

Expand All @@ -1119,11 +1127,11 @@ protected function loadApp(string $sAsset, ?string $sForceType, bool $bAsync): s

case static::TYPE_JS:
case static::TYPE_JS_FOOTER:
$this->aJs['APP-' . $sAsset] = [$this->buildUrl($this->sJsDir . $sAsset), $bAsync];
$this->aJs['APP-' . $sAsset] = [$this->buildUrl($this->sJsDir . $sAsset), $bAsync, $bDefer];
break;

case static::TYPE_JS_HEADER:
$this->aJsHeader['APP-' . $sAsset] = [$this->buildUrl($this->sJsDir . $sAsset), $bAsync];
$this->aJsHeader['APP-' . $sAsset] = [$this->buildUrl($this->sJsDir . $sAsset), $bAsync, $bDefer];
break;
}

Expand Down

0 comments on commit 5606a2d

Please sign in to comment.