Skip to content

Commit

Permalink
Adds header for preloading Tailwind assets
Browse files Browse the repository at this point in the history
  • Loading branch information
tonysm committed Jan 12, 2024
1 parent 08f2f66 commit d453d19
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 4 deletions.
31 changes: 31 additions & 0 deletions src/Http/Middleware/AddLinkHeaderForPreloadedAssets.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Tonysm\TailwindCss\Http\Middleware;

use Tonysm\TailwindCss\Manifest;

class AddLinkHeaderForPreloadedAssets
{
public function __construct(private Manifest $manifest)
{
}

public function handle($request, $next)
{
return tap($next($request), function ($response) {
if (count($assets = $this->manifest->assetsForPreloading()) > 0) {
$response->header('Link', trim(implode(', ', array_filter([
$response->headers->get('Link', null),
...collect($assets)
->map(fn ($attributes, $asset) => implode('; ', [
"<$asset>",
...collect(array_merge(['rel' => 'preload', 'as' => 'style'], $attributes))
->map(fn ($value, $key) => "{$key}={$value}")
->all(),
]))
->all(),
]))));
}
});
}
}
17 changes: 15 additions & 2 deletions src/Manifest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@

class Manifest
{
protected array $preloading = [];

public function assetsForPreloading(): array
{
return $this->preloading;
}

public static function filename(): string
{
return basename(self::path());
Expand All @@ -18,7 +25,7 @@ public static function path(): string
return config('tailwindcss.build.manifest_file_path');
}

public function __invoke(string $path)
public function __invoke(string $path, $preload = true)
{
static $manifests = [];

Expand Down Expand Up @@ -50,6 +57,12 @@ public function __invoke(string $path)
}
}

return new HtmlString(asset($manifest[$path]));
$asset = asset($manifest[$path]);

if ($preload) {
$this->preloading[$asset] = is_array($preload) ? $preload : [];
}

return new HtmlString($asset);
}
}
5 changes: 5 additions & 0 deletions src/TailwindCssServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,9 @@ public function configurePackage(Package $package): void
Commands\WatchCommand::class,
]);
}

public function packageRegistered()
{
$this->app->scoped(Manifest::class);
}
}
5 changes: 3 additions & 2 deletions src/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
* Get the path to a versioned TailwindCSS file.
*
* @param string $path
* @param bool|array $preload
* @return \Illuminate\Support\HtmlString|string
*/
function tailwindcss(string $path): HtmlString|string
function tailwindcss(string $path, $preload = true): HtmlString|string
{
return app(Manifest::class)($path);
return app(Manifest::class)($path, $preload);
}
}
79 changes: 79 additions & 0 deletions tests/PreloadingHeaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

namespace Tonysm\TailwindCss\Tests;

use Illuminate\Http\Request;
use Tonysm\TailwindCss\Http\Middleware\AddLinkHeaderForPreloadedAssets;

class PreloadingHeaderTest extends TestCase
{
/** @test */
public function no_link_header_when_not_preloading()
{
config()->set('tailwindcss.build.manifest_file_path', __DIR__.'/stubs/test-manifest.json');

$tailwindcss = tailwindcss('css/app.css', preload: false);

$response = resolve(AddLinkHeaderForPreloadedAssets::class)->handle(
Request::create('/'),
fn () => response('hello world'),
);

$this->assertEquals('http://localhost/css/app-123.css', (string) $tailwindcss);
$this->assertEquals('hello world', $response->content());
$this->assertNull($response->headers->get('Link', null));
}

/** @test */
public function adds_link_header_when_preloading()
{
config()->set('tailwindcss.build.manifest_file_path', __DIR__.'/stubs/test-manifest.json');

$tailwindcss = tailwindcss('css/app.css', preload: true);

$response = resolve(AddLinkHeaderForPreloadedAssets::class)->handle(
Request::create('/'),
fn () => response('hello world'),
);

$this->assertEquals($asset = 'http://localhost/css/app-123.css', (string) $tailwindcss);
$this->assertEquals('hello world', $response->content());
$this->assertEquals("<{$asset}>; rel=preload; as=style", $response->headers->get('Link', null));
}

/** @test */
public function keeps_existing_preloading_link_header()
{
config()->set('tailwindcss.build.manifest_file_path', __DIR__.'/stubs/test-manifest.json');

$tailwindcss = tailwindcss('css/app.css', preload: true);

$response = resolve(AddLinkHeaderForPreloadedAssets::class)->handle(
Request::create('/'),
fn () => response('hello world')->withHeaders([
'Link' => '</js/app.js>; rel=modulepreload'
]),
);

$this->assertEquals($asset = 'http://localhost/css/app-123.css', (string) $tailwindcss);
$this->assertEquals('hello world', $response->content());
$this->assertEquals("</js/app.js>; rel=modulepreload, <{$asset}>; rel=preload; as=style", $response->headers->get('Link', null));
}

/** @test */
public function adds_link_header_when_preloading_custom_attributes()
{
config()->set('tailwindcss.build.manifest_file_path', __DIR__.'/stubs/test-manifest.json');

$tailwindcss = tailwindcss('css/app.css', ['crossorigin' => 'anonymous']);

$response = resolve(AddLinkHeaderForPreloadedAssets::class)->handle(
Request::create('/'),
fn () => response('hello world'),
);

$this->assertEquals($asset = 'http://localhost/css/app-123.css', (string) $tailwindcss);
$this->assertEquals('hello world', $response->content());
$this->assertEquals("<{$asset}>; rel=preload; as=style; crossorigin=anonymous", $response->headers->get('Link', null));
}
}
2 changes: 2 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,7 @@ protected function getPackageProviders($app)
public function getEnvironmentSetUp($app)
{
config()->set('database.default', 'testing');
config()->set('app.url', 'http://localhost');
config()->set('app.asset_url', 'http://localhost');
}
}
3 changes: 3 additions & 0 deletions tests/stubs/test-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"/css/app.css": "/css/app-123.css"
}

0 comments on commit d453d19

Please sign in to comment.