diff --git a/src/Illuminate/Foundation/Vite.php b/src/Illuminate/Foundation/Vite.php index 0eddc517b2b5..a860e94f2b92 100644 --- a/src/Illuminate/Foundation/Vite.php +++ b/src/Illuminate/Foundation/Vite.php @@ -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) @@ -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) @@ -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() ); @@ -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) @@ -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) @@ -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) { @@ -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; diff --git a/src/Illuminate/Support/Facades/Vite.php b/src/Illuminate/Support/Facades/Vite.php index ad5576463699..3a289074a7d9 100644 --- a/src/Illuminate/Support/Facades/Vite.php +++ b/src/Illuminate/Support/Facades/Vite.php @@ -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) diff --git a/tests/Foundation/FoundationViteTest.php b/tests/Foundation/FoundationViteTest.php index 68814a7535b1..8d8a69a6328b 100644 --- a/tests/Foundation/FoundationViteTest.php +++ b/tests/Foundation/FoundationViteTest.php @@ -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( + '' + .'' + .'' + .'' + .'' + .'' + .'', + $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();