Skip to content

Commit

Permalink
[9.x] Vite: ability to prevent preload tag generation from attribute …
Browse files Browse the repository at this point in the history
…resolver callback (#45283)

* Vite: ability to prevent preload tag generation from attribute resolver callback

* Update Vite.php

Co-authored-by: Sergey Danilchenko <s.danilchenko@ttbooking.ru>
Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
3 people committed Dec 15, 2022
1 parent 60808a7 commit ab5cddb
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 11 deletions.
28 changes: 18 additions & 10 deletions src/Illuminate/Foundation/Vite.php
Expand Up @@ -233,7 +233,7 @@ public function useStyleTagAttributes($attributes)
/**
* Use the given callback to resolve attributes for preload tags.
*
* @param (callable(string, string, ?array, ?array): array)|array $attributes
* @param (callable(string, string, ?array, ?array): array|false)|array|false $attributes
* @return $this
*/
public function usePreloadTagAttributes($attributes)
Expand Down Expand Up @@ -351,8 +351,8 @@ public function __invoke($entrypoints, $buildDirectory = null)
*
* @param string $src
* @param string $url
* @param ?array $chunk
* @param ?array $manifest
* @param array|null $chunk
* @param array|null $manifest
* @return string
*/
protected function makeTagForChunk($src, $url, $chunk, $manifest)
Expand Down Expand Up @@ -386,12 +386,16 @@ protected function makeTagForChunk($src, $url, $chunk, $manifest)
* @param string $url
* @param array $chunk
* @param array $manifest
* @return string|null
* @return string
*/
protected function makePreloadTagForChunk($src, $url, $chunk, $manifest)
{
$attributes = $this->resolvePreloadTagAttributes($src, $url, $chunk, $manifest);

if ($attributes === false) {
return '';
}

$this->preloadedAssets[$url] = $this->parseAttributes(
Collection::make($attributes)->forget('href')->all()
);
Expand All @@ -404,8 +408,8 @@ protected function makePreloadTagForChunk($src, $url, $chunk, $manifest)
*
* @param string $src
* @param string $url
* @param ?array $chunk
* @param ?array $manifest
* @param array|null $chunk
* @param array|null $manifest
* @return array
*/
protected function resolveScriptTagAttributes($src, $url, $chunk, $manifest)
Expand All @@ -426,8 +430,8 @@ protected function resolveScriptTagAttributes($src, $url, $chunk, $manifest)
*
* @param string $src
* @param string $url
* @param ?array $chunk
* @param ?array $manifest
* @param array|null $chunk
* @param array|null $manifest
* @return array
*/
protected function resolveStylesheetTagAttributes($src, $url, $chunk, $manifest)
Expand All @@ -450,7 +454,7 @@ protected function resolveStylesheetTagAttributes($src, $url, $chunk, $manifest)
* @param string $url
* @param array $chunk
* @param array $manifest
* @return array
* @return array|false
*/
protected function resolvePreloadTagAttributes($src, $url, $chunk, $manifest)
{
Expand All @@ -472,7 +476,11 @@ protected function resolvePreloadTagAttributes($src, $url, $chunk, $manifest)
: $attributes;

foreach ($this->preloadTagAttributesResolvers as $resolver) {
$attributes = array_merge($attributes, $resolver($src, $url, $chunk, $manifest));
if (false === ($resolvedAttributes = $resolver($src, $url, $chunk, $manifest))) {
return false;
}

$attributes = array_merge($attributes, $resolvedAttributes);
}

return $attributes;
Expand Down
2 changes: 1 addition & 1 deletion src/Illuminate/Support/Facades/Vite.php
Expand Up @@ -14,7 +14,7 @@
* @method static \Illuminate\Foundation\Vite useBuildDirectory(string $path)
* @method static \Illuminate\Foundation\Vite useScriptTagAttributes((callable(string, string, ?array, ?array): array)|array $attributes)
* @method static \Illuminate\Foundation\Vite useStyleTagAttributes((callable(string, string, ?array, ?array): array)|array $attributes)
* @method static \Illuminate\Foundation\Vite usePreloadTagAttributes((callable(string, string, ?array, ?array): array)|array $attributes)
* @method static \Illuminate\Foundation\Vite usePreloadTagAttributes((callable(string, string, ?array, ?array): array|false)|array|false $attributes)
* @method static \Illuminate\Support\HtmlString|void reactRefresh()
* @method static string asset(string $asset, string|null $buildDirectory = null)
* @method static string|null manifestHash(string|null $buildDirectory = null)
Expand Down
151 changes: 151 additions & 0 deletions tests/Foundation/FoundationViteTest.php
Expand Up @@ -865,6 +865,157 @@ public function testItCanSpecifyAttributesForPreloadedAssets()
$this->cleanViteManifest($buildDir);
}

public function testItCanSuppressPreloadTagGeneration()
{
$buildDir = Str::random();
$this->makeViteManifest([
'resources/js/app.js' => [
'src' => 'resources/js/app.js',
'file' => 'assets/app.versioned.js',
'imports' => [
'import.js',
'import-nopreload.js',
],
'css' => [
'assets/app.versioned.css',
'assets/app-nopreload.versioned.css',
],
],
'resources/js/app-nopreload.js' => [
'src' => 'resources/js/app-nopreload.js',
'file' => 'assets/app-nopreload.versioned.js',
],
'import.js' => [
'file' => 'assets/import.versioned.js',
],
'import-nopreload.js' => [
'file' => 'assets/import-nopreload.versioned.js',
],
'resources/css/app.css' => [
'src' => 'resources/css/app.css',
'file' => 'assets/app.versioned.css',
],
'resources/css/app-nopreload.css' => [
'src' => 'resources/css/app-nopreload.css',
'file' => 'assets/app-nopreload.versioned.css',
],
], $buildDir);
ViteFacade::usePreloadTagAttributes(function ($src, $url, $chunk, $manifest) use ($buildDir) {
$this->assertSame([
'resources/js/app.js' => [
'src' => 'resources/js/app.js',
'file' => 'assets/app.versioned.js',
'imports' => [
'import.js',
'import-nopreload.js',
],
'css' => [
'assets/app.versioned.css',
'assets/app-nopreload.versioned.css',
],
],
'resources/js/app-nopreload.js' => [
'src' => 'resources/js/app-nopreload.js',
'file' => 'assets/app-nopreload.versioned.js',
],
'import.js' => [
'file' => 'assets/import.versioned.js',
],
'import-nopreload.js' => [
'file' => 'assets/import-nopreload.versioned.js',
],
'resources/css/app.css' => [
'src' => 'resources/css/app.css',
'file' => 'assets/app.versioned.css',
],
'resources/css/app-nopreload.css' => [
'src' => 'resources/css/app-nopreload.css',
'file' => 'assets/app-nopreload.versioned.css',
],
], $manifest);

(match ($src) {
'resources/js/app.js' => function () use ($url, $chunk, $buildDir) {
$this->assertSame("https://example.com/{$buildDir}/assets/app.versioned.js", $url);
$this->assertSame([
'src' => 'resources/js/app.js',
'file' => 'assets/app.versioned.js',
'imports' => [
'import.js',
'import-nopreload.js',
],
'css' => [
'assets/app.versioned.css',
'assets/app-nopreload.versioned.css',
],
], $chunk);
},
'resources/js/app-nopreload.js' => function () use ($url, $chunk, $buildDir) {
$this->assertSame("https://example.com/{$buildDir}/assets/app-nopreload.versioned.js", $url);
$this->assertSame([
'src' => 'resources/js/app-nopreload.js',
'file' => 'assets/app-nopreload.versioned.js',
], $chunk);
},
'import.js' => function () use ($url, $chunk, $buildDir) {
$this->assertSame("https://example.com/{$buildDir}/assets/import.versioned.js", $url);
$this->assertSame([
'file' => 'assets/import.versioned.js',
], $chunk);
},
'import-nopreload.js' => function () use ($url, $chunk, $buildDir) {
$this->assertSame("https://example.com/{$buildDir}/assets/import-nopreload.versioned.js", $url);
$this->assertSame([
'file' => 'assets/import-nopreload.versioned.js',
], $chunk);
},
'resources/css/app.css' => function () use ($url, $chunk, $buildDir) {
$this->assertSame("https://example.com/{$buildDir}/assets/app.versioned.css", $url);
$this->assertSame([
'src' => 'resources/css/app.css',
'file' => 'assets/app.versioned.css',
], $chunk);
},
'resources/css/app-nopreload.css' => function () use ($url, $chunk, $buildDir) {
$this->assertSame("https://example.com/{$buildDir}/assets/app-nopreload.versioned.css", $url);
$this->assertSame([
'src' => 'resources/css/app-nopreload.css',
'file' => 'assets/app-nopreload.versioned.css',
], $chunk);
},
})();

return Str::contains($src, '-nopreload') ? false : [];
});

$result = app(Vite::class)(['resources/js/app.js', 'resources/js/app-nopreload.js'], $buildDir);

$this->assertSame(
'<link rel="preload" as="style" href="https://example.com/'.$buildDir.'/assets/app.versioned.css" />'
.'<link rel="modulepreload" href="https://example.com/'.$buildDir.'/assets/app.versioned.js" />'
.'<link rel="modulepreload" href="https://example.com/'.$buildDir.'/assets/import.versioned.js" />'
.'<link rel="stylesheet" href="https://example.com/'.$buildDir.'/assets/app.versioned.css" />'
.'<link rel="stylesheet" href="https://example.com/'.$buildDir.'/assets/app-nopreload.versioned.css" />'
.'<script type="module" src="https://example.com/'.$buildDir.'/assets/app.versioned.js"></script>'
.'<script type="module" src="https://example.com/'.$buildDir.'/assets/app-nopreload.versioned.js"></script>',
$result->toHtml());

$this->assertSame([
"https://example.com/$buildDir/assets/app.versioned.css" => [
'rel="preload"',
'as="style"',
],
"https://example.com/$buildDir/assets/app.versioned.js" => [
'rel="modulepreload"',
],
"https://example.com/$buildDir/assets/import.versioned.js" => [
'rel="modulepreload"',
],
], ViteFacade::preloadedAssets());

$this->cleanViteManifest($buildDir);
}

public function testPreloadAssetsGetAssetNonce()
{
$buildDir = Str::random();
Expand Down

0 comments on commit ab5cddb

Please sign in to comment.