From 0f89e7d57267a2563fa113c786ed318f6391c930 Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Sat, 6 Jan 2024 17:52:21 -0300 Subject: [PATCH 01/11] Preload by default --- src/Importmap.php | 4 ++-- tests/ImportmapTest.php | 6 ++++-- tests/fixtures/npm/single-quote-importmap.php | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Importmap.php b/src/Importmap.php index d62b8e7..48c71c4 100755 --- a/src/Importmap.php +++ b/src/Importmap.php @@ -20,12 +20,12 @@ public function __construct(public ?string $rootPath = null) $this->directories = collect(); } - public function pin(string $name, string $to = null, bool $preload = false) + public function pin(string $name, string $to = null, bool $preload = true) { $this->packages->add(new MappedFile($name, path: $to ?: "js/{$name}.js", preload: $preload)); } - public function pinAllFrom(string $dir, string $under = null, string $to = null, bool $preload = false) + public function pinAllFrom(string $dir, string $under = null, string $to = null, bool $preload = true) { $this->directories->add(new MappedDirectory($dir, $under, $to, $preload)); } diff --git a/tests/ImportmapTest.php b/tests/ImportmapTest.php index f794ef5..b61c1b5 100644 --- a/tests/ImportmapTest.php +++ b/tests/ImportmapTest.php @@ -15,8 +15,9 @@ protected function setUp(): void $this->map = new Importmap(rootPath: __DIR__.DIRECTORY_SEPARATOR.'stubs'.DIRECTORY_SEPARATOR); - $this->map->pin('app'); - $this->map->pin('editor', to: 'js/rich_text.js'); + $this->map->pin('app', preload: false); + $this->map->pin('editor', to: 'js/rich_text.js', preload: false); + $this->map->pin('not_there', to: 'js/nowhere.js', preload: false); $this->map->pin('md5', to: 'https://cdn.skypack.dev/md5', preload: true); $this->map->pinAllFrom('resources/js/controllers', under: 'controllers', to: 'js/controllers', preload: true); @@ -90,6 +91,7 @@ public function preload_modules_are_included_in_preload_tags() $this->assertStringContainsString('md5', $preloadingModulePaths); $this->assertStringContainsString('hello_controller', $preloadingModulePaths); + $this->assertStringNotContainsString('not_there', $preloadingModulePaths); $this->assertStringNotContainsString('app', $preloadingModulePaths); } } diff --git a/tests/fixtures/npm/single-quote-importmap.php b/tests/fixtures/npm/single-quote-importmap.php index 53e0b2b..eeda064 100644 --- a/tests/fixtures/npm/single-quote-importmap.php +++ b/tests/fixtures/npm/single-quote-importmap.php @@ -3,4 +3,4 @@ use Tonysm\ImportmapLaravel\Facades\Importmap; Importmap::pin('md5', to: 'https://cdn.skypack.dev/md5', preload: true); -Importmap::pin('not_there', to: 'nowhere.js'); +Importmap::pin('not_there', to: 'nowhere.js', preload: false); From 88b98e2d769a48acf89aedcca85252f95d6eab33 Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Sat, 6 Jan 2024 17:55:34 -0300 Subject: [PATCH 02/11] docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ba7edc..95dcbbd 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ The version is added as a comment to your pin so you know which version was impo ### Preloading Modules -To avoid the waterfall effect where the browser has to load one file after another before it can get to the deepest nested import, we support [modulepreload links](https://developers.google.com/web/updates/2017/12/modulepreload). Pinned modules can be preloaded by appending `preload: true` to the pin, like so: +To avoid the waterfall effect where the browser has to load one file after another before it can get to the deepest nested import, we use [modulepreload links](https://developers.google.com/web/updates/2017/12/modulepreload) by default. If you don't want to preload a dependency, because you want to load it on demand for efficiency, pinned modules can prevent preloading by appending `preload: false` to the pin: ```php Importmap::pinAllFrom("resources/js/", to: "js/", preload: true); From 359ebbd99227b3d336142d0ff4bbb92a800ba567 Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Sat, 6 Jan 2024 17:59:55 -0300 Subject: [PATCH 03/11] docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 95dcbbd..24ea3ac 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ The version is added as a comment to your pin so you know which version was impo ### Preloading Modules -To avoid the waterfall effect where the browser has to load one file after another before it can get to the deepest nested import, we use [modulepreload links](https://developers.google.com/web/updates/2017/12/modulepreload) by default. If you don't want to preload a dependency, because you want to load it on demand for efficiency, pinned modules can prevent preloading by appending `preload: false` to the pin: +To avoid the waterfall effect where the browser has to load one file after another before it can get to the deepest nested import, we use [modulepreload links](https://developers.google.com/web/updates/2017/12/modulepreload) by default. If you don't want to preload a dependency, because you want to load it on-demand for efficiency, append `preload: false` to the pin. ```php Importmap::pinAllFrom("resources/js/", to: "js/", preload: true); From c7a29e012073e46f502152f3522adc18902290de Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Sat, 6 Jan 2024 18:24:54 -0300 Subject: [PATCH 04/11] Adds middleware to set the link header for preloaded modules --- src/Commands/InstallCommand.php | 2 +- .../AddLinkHeadersForPreloadedPins.php | 26 +++++++++++ src/Importmap.php | 4 +- tests/PreloadingWithLinkHeadersTest.php | 46 +++++++++++++++++++ 4 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/Http/Middleware/AddLinkHeadersForPreloadedPins.php create mode 100644 tests/PreloadingWithLinkHeadersTest.php diff --git a/src/Commands/InstallCommand.php b/src/Commands/InstallCommand.php index 33a95c7..453eae5 100644 --- a/src/Commands/InstallCommand.php +++ b/src/Commands/InstallCommand.php @@ -63,7 +63,7 @@ private function deleteNpmRelatedFiles(): void private function publishImportmapFile(): void { $this->displayTask('publishing the `routes/importmap.php` file', function () { - File::copy(dirname(__DIR__, 2).join(DIRECTORY_SEPARATOR, ['', 'stubs', 'routes', 'importmap.php']), base_path(join(DIRECTORY_SEPARATOR, ['routes', 'importmap.php']))); + File::copy(dirname(__DIR__, 2).implode(DIRECTORY_SEPARATOR, ['', 'stubs', 'routes', 'importmap.php']), base_path(implode(DIRECTORY_SEPARATOR, ['routes', 'importmap.php']))); return self::SUCCESS; }); diff --git a/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php b/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php new file mode 100644 index 0000000..c4082f2 --- /dev/null +++ b/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php @@ -0,0 +1,26 @@ + asset($file))) { + $response->header('Link', collect($preloaded) + ->map(fn ($url) => "<{$url}>; rel=\"modulepreload\"") + ->join(', ')); + } + }); + } +} diff --git a/src/Importmap.php b/src/Importmap.php index 48c71c4..5c227dc 100755 --- a/src/Importmap.php +++ b/src/Importmap.php @@ -20,12 +20,12 @@ public function __construct(public ?string $rootPath = null) $this->directories = collect(); } - public function pin(string $name, string $to = null, bool $preload = true) + public function pin(string $name, ?string $to = null, bool $preload = true) { $this->packages->add(new MappedFile($name, path: $to ?: "js/{$name}.js", preload: $preload)); } - public function pinAllFrom(string $dir, string $under = null, string $to = null, bool $preload = true) + public function pinAllFrom(string $dir, ?string $under = null, ?string $to = null, bool $preload = true) { $this->directories->add(new MappedDirectory($dir, $under, $to, $preload)); } diff --git a/tests/PreloadingWithLinkHeadersTest.php b/tests/PreloadingWithLinkHeadersTest.php new file mode 100644 index 0000000..0ef048f --- /dev/null +++ b/tests/PreloadingWithLinkHeadersTest.php @@ -0,0 +1,46 @@ +swap(Importmap::class, $map = new Importmap(rootPath: __DIR__.DIRECTORY_SEPARATOR.'stubs'.DIRECTORY_SEPARATOR)); + + $map->pin('app', preload: false); + $map->pin('editor', to: 'js/rich_text.js', preload: false); + $map->pinAllFrom('resources/js/', under: 'controllers', to: 'js/', preload: false); + + $response = (new AddLinkHeadersForPreloadedPins)->handle(new Request(), function () { + return new Response('Hello World'); + }); + + $this->assertNull($response->headers->get('Link')); + } + + /** @test */ + public function sets_link_header_when_pins_are_preloaded(): void + { + $this->swap(Importmap::class, $map = new Importmap(rootPath: __DIR__.DIRECTORY_SEPARATOR.'stubs'.DIRECTORY_SEPARATOR)); + + $map->pin('app', preload: true); + $map->pin('editor', to: 'js/rich_text.js', preload: false); + $map->pinAllFrom('resources/js/', under: 'controllers', to: 'js/', preload: true); + + $response = (new AddLinkHeadersForPreloadedPins)->handle(new Request(), function () { + return new Response('Hello World'); + }); + + $this->assertEquals( + '; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload"', + $response->headers->get('Link'), + ); + } +} From ae1e2f55e66745fd6848f3bd6a0cafef5cbda3e9 Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Sat, 6 Jan 2024 19:01:14 -0300 Subject: [PATCH 05/11] Use inline anonymous component instead of class component --- README.md | 9 ++++-- .../views/{ => components}/tags.blade.php | 9 ++++++ src/Commands/InstallCommand.php | 6 ++-- src/ImportmapLaravelServiceProvider.php | 11 +++++++- src/View/Components/Tags.php | 28 ------------------- tests/TagsComponentTest.php | 6 ++-- 6 files changed, 31 insertions(+), 38 deletions(-) rename resources/views/{ => components}/tags.blade.php (52%) delete mode 100644 src/View/Components/Tags.php diff --git a/README.md b/README.md index 24ea3ac..0e50894 100644 --- a/README.md +++ b/README.md @@ -45,15 +45,15 @@ php artisan importmap:install Next, we need to add the following component to our view or layout file: ```blade - + ``` Add that between your `` tags. The `entrypoint` should be the "main" file, commonly the `resources/js/app.js` file, which will be mapped to the `app` module (use the module name, not the file). -By default the `x-importmap-tags` component assumes your entrypoint module is `app`, which matches the existing `resources/js/app.js` file from Laravel's default scaffolding. You may want to customize the entrypoint, which you can do with the `entrypoint` prop: +By default the `x-importmap::tags` component assumes your entrypoint module is `app`, which matches the existing `resources/js/app.js` file from Laravel's default scaffolding. You may want to customize the entrypoint, which you can do with the `entrypoint` prop: ```blade - + ``` The package will automatically map the `resources/js` folder to your `public/js` folder using Laravel's symlink feature. All you have to do after installing the package is run: @@ -186,6 +186,9 @@ Which will add the correct `links` tags to your head tag in the HTML document, l ``` +You may add the `AddLinkHeadersForPreloadedPins` middleware to the `web` routes group so these preloaded links are sent as a `Link` header. +Add the `Tonysm\ImportmapLaravel\Http\Middleware\AddLinkHeadersForPreloadedPins` to the `web` route group so the preloaded modules are sent as the Link headers, which are used in [HTTP/2 Server Push](https://datatracker.ietf.org/doc/html/rfc7540#section-8.2) and [Resource Hints](https://html.spec.whatwg.org/#linkTypes) to push resources to the client as early as possible. Some web servers can pick up this `Link` header and convert them to [Early Hints](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/103) responses. + ## Dependency Maintenance Commands Maintaining a healthy dependency list can be tricky. Here are a couple of commands to help you with this task. diff --git a/resources/views/tags.blade.php b/resources/views/components/tags.blade.php similarity index 52% rename from resources/views/tags.blade.php rename to resources/views/components/tags.blade.php index c61d39d..b632e40 100644 --- a/resources/views/tags.blade.php +++ b/resources/views/components/tags.blade.php @@ -1,3 +1,12 @@ +@props(['entrypoint' => 'app', 'nonce' => null, 'importmap' => null]) + +@php + $resolver = new \Tonysm\ImportmapLaravel\AssetResolver(); + + $importmaps = $importmap?->asArray($resolver) ?? \Tonysm\ImportmapLaravel\Facades\Importmap::asArray($resolver); + $preloadedModules = $importmap?->preloadedModulePaths($resolver) ?? \Tonysm\ImportmapLaravel\Facades\Importmap::preloadedModulePaths($resolver); +@endphp + diff --git a/src/Commands/InstallCommand.php b/src/Commands/InstallCommand.php index 453eae5..dcc9031 100644 --- a/src/Commands/InstallCommand.php +++ b/src/Commands/InstallCommand.php @@ -140,7 +140,7 @@ private function updateAppLayoutsUsingMix() $file, str_replace( "", - '', + '', File::get($file), ), )); @@ -157,7 +157,7 @@ private function updateAppLayoutsUsingVite() $file, preg_replace( '/\@vite.*/', - '', + '', File::get($file), ), )) @@ -182,7 +182,7 @@ private function appendImportmapTagsToLayoutsHead(): void $file, preg_replace( '/(\s*)(<\/head>)/', - "\\1 \n\\1\\2", + "\\1 \n\\1\\2", File::get($file), ), )); diff --git a/src/ImportmapLaravelServiceProvider.php b/src/ImportmapLaravelServiceProvider.php index 69593d0..9de44ee 100644 --- a/src/ImportmapLaravelServiceProvider.php +++ b/src/ImportmapLaravelServiceProvider.php @@ -2,6 +2,7 @@ namespace Tonysm\ImportmapLaravel; +use Illuminate\View\Compilers\BladeCompiler; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; use Tonysm\ImportmapLaravel\View\Components; @@ -19,7 +20,6 @@ public function configurePackage(Package $package): void ->name('importmap') ->hasConfigFile() ->hasViews() - ->hasViewComponent('importmap', Components\Tags::class) ->hasCommand(Commands\InstallCommand::class) ->hasCommand(Commands\OptimizeCommand::class) ->hasCommand(Commands\ClearCacheCommand::class) @@ -51,5 +51,14 @@ public function packageBooted() public_path('js') => resource_path('js'), ]); } + + $this->configureComponents(); + } + + private function configureComponents() + { + $this->callAfterResolving('blade.compiler', function (BladeCompiler $blade) { + $blade->anonymousComponentPath(__DIR__.'/../resources/views/components', 'importmap'); + }); } } diff --git a/src/View/Components/Tags.php b/src/View/Components/Tags.php deleted file mode 100644 index 9222f2e..0000000 --- a/src/View/Components/Tags.php +++ /dev/null @@ -1,28 +0,0 @@ - $this->importmap?->asArray($resolver) ?? ImportmapFacade::asArray($resolver), - 'preloadedModules' => $this->importmap?->preloadedModulePaths($resolver) ?? ImportmapFacade::preloadedModulePaths($resolver), - ]); - } -} diff --git a/tests/TagsComponentTest.php b/tests/TagsComponentTest.php index 073a135..f2b623b 100644 --- a/tests/TagsComponentTest.php +++ b/tests/TagsComponentTest.php @@ -33,14 +33,14 @@ protected function setUp(): void /** @test */ public function generates_tags_without_nonce() { - $this->blade('') + $this->blade('') ->assertSee('', escape: false); } /** @test */ public function uses_given_csp_nonce() { - $this->blade('') + $this->blade('') ->assertSee('', escape: false); } @@ -51,7 +51,7 @@ public function uses_custom_map() $importmap->pin('foo', preload: true); $importmap->pin('bar', preload: true); - $this->blade('', ['importmap' => $importmap]) + $this->blade('', ['importmap' => $importmap]) ->assertSee('', escape: false) ->assertSee('', escape: false) ->assertDontSee('', escape: false); From e1ae1f05f6847911fde1f1eeda51fb3667b3f67b Mon Sep 17 00:00:00 2001 From: tonysm Date: Sat, 6 Jan 2024 22:01:42 +0000 Subject: [PATCH 06/11] Fix styling --- src/ImportmapLaravelServiceProvider.php | 1 - tests/PreloadingWithLinkHeadersTest.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ImportmapLaravelServiceProvider.php b/src/ImportmapLaravelServiceProvider.php index 9de44ee..4ccb11d 100644 --- a/src/ImportmapLaravelServiceProvider.php +++ b/src/ImportmapLaravelServiceProvider.php @@ -5,7 +5,6 @@ use Illuminate\View\Compilers\BladeCompiler; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; -use Tonysm\ImportmapLaravel\View\Components; class ImportmapLaravelServiceProvider extends PackageServiceProvider { diff --git a/tests/PreloadingWithLinkHeadersTest.php b/tests/PreloadingWithLinkHeadersTest.php index 0ef048f..c13444d 100644 --- a/tests/PreloadingWithLinkHeadersTest.php +++ b/tests/PreloadingWithLinkHeadersTest.php @@ -18,7 +18,7 @@ public function doesnt_set_link_header_when_no_pins_are_preloaded(): void $map->pin('editor', to: 'js/rich_text.js', preload: false); $map->pinAllFrom('resources/js/', under: 'controllers', to: 'js/', preload: false); - $response = (new AddLinkHeadersForPreloadedPins)->handle(new Request(), function () { + $response = (new AddLinkHeadersForPreloadedPins())->handle(new Request(), function () { return new Response('Hello World'); }); @@ -34,7 +34,7 @@ public function sets_link_header_when_pins_are_preloaded(): void $map->pin('editor', to: 'js/rich_text.js', preload: false); $map->pinAllFrom('resources/js/', under: 'controllers', to: 'js/', preload: true); - $response = (new AddLinkHeadersForPreloadedPins)->handle(new Request(), function () { + $response = (new AddLinkHeadersForPreloadedPins())->handle(new Request(), function () { return new Response('Hello World'); }); From 8cf7981b2e0a30c5826f59aae430d03a5b51259f Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Sat, 6 Jan 2024 19:09:24 -0300 Subject: [PATCH 07/11] Use asset resolver instead manually resolving --- src/Http/Middleware/AddLinkHeadersForPreloadedPins.php | 5 ++++- tests/PreloadingWithLinkHeadersTest.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php b/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php index c4082f2..d1bd86b 100644 --- a/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php +++ b/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php @@ -2,6 +2,7 @@ namespace Tonysm\ImportmapLaravel\Http\Middleware; +use Tonysm\ImportmapLaravel\AssetResolver; use Tonysm\ImportmapLaravel\Facades\Importmap; class AddLinkHeadersForPreloadedPins @@ -16,7 +17,9 @@ class AddLinkHeadersForPreloadedPins public function handle($request, $next) { return tap($next($request), function ($response) { - if ($preloaded = Importmap::preloadedModulePaths(fn ($file) => asset($file))) { + $resolver = new AssetResolver(); + + if ($preloaded = Importmap::preloadedModulePaths($resolver)) { $response->header('Link', collect($preloaded) ->map(fn ($url) => "<{$url}>; rel=\"modulepreload\"") ->join(', ')); diff --git a/tests/PreloadingWithLinkHeadersTest.php b/tests/PreloadingWithLinkHeadersTest.php index c13444d..29ee34d 100644 --- a/tests/PreloadingWithLinkHeadersTest.php +++ b/tests/PreloadingWithLinkHeadersTest.php @@ -39,7 +39,7 @@ public function sets_link_header_when_pins_are_preloaded(): void }); $this->assertEquals( - '; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload"', + '; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload"', $response->headers->get('Link'), ); } From 218a1eb79956369c47567d23a722fe5a08088402 Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Sat, 6 Jan 2024 19:14:29 -0300 Subject: [PATCH 08/11] Try setting the app.url config --- tests/TestCase.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/TestCase.php b/tests/TestCase.php index 15d69bf..c681f3d 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -35,6 +35,7 @@ protected function getPackageProviders($app) public function getEnvironmentSetUp($app) { config()->set('database.default', 'testing'); + config()->set('app.url', 'http://localhost'); /* $migration = include __DIR__.'/../database/migrations/create_importmap-laravel_table.php.stub'; From eee0cdfc61dd3b4ffc638e123842d8d60348a12c Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Sat, 6 Jan 2024 19:25:55 -0300 Subject: [PATCH 09/11] Fix tests --- .../Middleware/AddLinkHeadersForPreloadedPins.php | 6 +++++- tests/PreloadingWithLinkHeadersTest.php | 13 +++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php b/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php index d1bd86b..839fe1d 100644 --- a/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php +++ b/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php @@ -7,6 +7,10 @@ class AddLinkHeadersForPreloadedPins { + public function __construct(private ?AssetResolver $assetsResolver = null) + { + } + /** * Sets the Link header for preloaded pins. * @@ -17,7 +21,7 @@ class AddLinkHeadersForPreloadedPins public function handle($request, $next) { return tap($next($request), function ($response) { - $resolver = new AssetResolver(); + $resolver = $this->assetsResolver ?? new AssetResolver(); if ($preloaded = Importmap::preloadedModulePaths($resolver)) { $response->header('Link', collect($preloaded) diff --git a/tests/PreloadingWithLinkHeadersTest.php b/tests/PreloadingWithLinkHeadersTest.php index 29ee34d..430fbad 100644 --- a/tests/PreloadingWithLinkHeadersTest.php +++ b/tests/PreloadingWithLinkHeadersTest.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; use Illuminate\Http\Response; +use Tonysm\ImportmapLaravel\AssetResolver; use Tonysm\ImportmapLaravel\Http\Middleware\AddLinkHeadersForPreloadedPins; use Tonysm\ImportmapLaravel\Importmap; @@ -34,12 +35,20 @@ public function sets_link_header_when_pins_are_preloaded(): void $map->pin('editor', to: 'js/rich_text.js', preload: false); $map->pinAllFrom('resources/js/', under: 'controllers', to: 'js/', preload: true); - $response = (new AddLinkHeadersForPreloadedPins())->handle(new Request(), function () { + $resolver = new class extends AssetResolver + { + public function __invoke($module) + { + return 'http://localhost/'.str_replace(['.js'], ['-123123.js'], $module); + } + }; + + $response = (new AddLinkHeadersForPreloadedPins($resolver))->handle(new Request(), function () { return new Response('Hello World'); }); $this->assertEquals( - '; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload"', + '; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload", ; rel="modulepreload"', $response->headers->get('Link'), ); } From e5c0741bc037baca357e3462c577fdc78316ebbf Mon Sep 17 00:00:00 2001 From: tonysm Date: Sat, 6 Jan 2024 22:26:17 +0000 Subject: [PATCH 10/11] Fix styling --- tests/PreloadingWithLinkHeadersTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/PreloadingWithLinkHeadersTest.php b/tests/PreloadingWithLinkHeadersTest.php index 430fbad..1e37f40 100644 --- a/tests/PreloadingWithLinkHeadersTest.php +++ b/tests/PreloadingWithLinkHeadersTest.php @@ -35,8 +35,7 @@ public function sets_link_header_when_pins_are_preloaded(): void $map->pin('editor', to: 'js/rich_text.js', preload: false); $map->pinAllFrom('resources/js/', under: 'controllers', to: 'js/', preload: true); - $resolver = new class extends AssetResolver - { + $resolver = new class () extends AssetResolver { public function __invoke($module) { return 'http://localhost/'.str_replace(['.js'], ['-123123.js'], $module); From a47604c4fa7c5028d542c922c88e0993cdf30301 Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Sat, 6 Jan 2024 19:28:31 -0300 Subject: [PATCH 11/11] Inject the resolver --- src/Http/Middleware/AddLinkHeadersForPreloadedPins.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php b/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php index 839fe1d..43b0b79 100644 --- a/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php +++ b/src/Http/Middleware/AddLinkHeadersForPreloadedPins.php @@ -7,7 +7,7 @@ class AddLinkHeadersForPreloadedPins { - public function __construct(private ?AssetResolver $assetsResolver = null) + public function __construct(private AssetResolver $assetsResolver = new AssetResolver()) { } @@ -21,9 +21,7 @@ public function __construct(private ?AssetResolver $assetsResolver = null) public function handle($request, $next) { return tap($next($request), function ($response) { - $resolver = $this->assetsResolver ?? new AssetResolver(); - - if ($preloaded = Importmap::preloadedModulePaths($resolver)) { + if ($preloaded = Importmap::preloadedModulePaths($this->assetsResolver)) { $response->header('Link', collect($preloaded) ->map(fn ($url) => "<{$url}>; rel=\"modulepreload\"") ->join(', '));