From 7798352cfc71643a88d4658f9704e65c4e24e8da Mon Sep 17 00:00:00 2001 From: Andreas Reinhold / reini Date: Sun, 13 Sep 2026 11:16:52 +0200 Subject: [PATCH] Compile unprefixed components to the same view on every machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without a prefix, Blade named the components' view namespace after the folder's absolute path, while compiled views are named relative to the application. A view compiled on a laptop and served from a container sharing storage/framework/views (or from another release directory) printed 'eb5f…::input' as text. The components now register under the prefix livewire-material when none is configured, which unprefixed tags still resolve through, and the path's namespace stays registered for views compiled before. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy --- src/LivewireMaterialServiceProvider.php | 15 +++++++++++++-- tests/Feature/ServiceProviderTest.php | 18 ++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/LivewireMaterialServiceProvider.php b/src/LivewireMaterialServiceProvider.php index 414d877a..49e6604c 100644 --- a/src/LivewireMaterialServiceProvider.php +++ b/src/LivewireMaterialServiceProvider.php @@ -5,6 +5,7 @@ namespace NoNameWeb\LivewireMaterial; use Illuminate\Contracts\View\Factory; use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Route; +use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; class LivewireMaterialServiceProvider extends ServiceProvider @@ -113,7 +114,15 @@ class LivewireMaterialServiceProvider extends ServiceProvider } /** - * Register the components as anonymous Blade components under the configured prefix. + * Register the components as anonymous Blade components under the configured prefix, or + * under `livewire-material` without one. + * + * A compiled `` names the view namespace Blade derives from the prefix, or from the + * component folder's absolute path when there is none. That path differs between a laptop and + * a container sharing `storage/framework/views`, or between release directories, while the + * compiled file's name does not — so a view compiled on one showed `a1b2…::button` as text on + * the other. A prefix does not stop an unprefixed tag resolving. The path's namespace stays + * registered, so views compiled before this release still render until they are recompiled. * * The package's own views never go through this registration: they write * ``, which resolves through the view namespace whatever the @@ -123,8 +132,10 @@ class LivewireMaterialServiceProvider extends ServiceProvider { Blade::anonymousComponentPath( static::componentPath(), - filled(config('livewire-material.prefix')) ? config('livewire-material.prefix') : null, + filled(config('livewire-material.prefix')) ? config('livewire-material.prefix') : 'livewire-material', ); + + View::addNamespace(hash('xxh128', static::componentPath()), static::componentPath()); } /** diff --git a/tests/Feature/ServiceProviderTest.php b/tests/Feature/ServiceProviderTest.php index 25da3420..20ffaf97 100644 --- a/tests/Feature/ServiceProviderTest.php +++ b/tests/Feature/ServiceProviderTest.php @@ -20,9 +20,23 @@ function packageComponentPaths(): Collection ->values(); } -it('registers the components without a prefix', function () { +it('registers the components under its own name when no prefix is configured', function () { expect(packageComponentPaths())->toHaveCount(1) - ->and(packageComponentPaths()->first()['prefix'])->toBeNull(); + ->and(packageComponentPaths()->first()['prefix'])->toBe('livewire-material') + ->and(Blade::render(''))->toContain('New'); +}); + +it('compiles an unprefixed component to the same view on every machine', function () { + $compiled = Blade::compileString(''); + + expect($compiled)->toContain("'view' => '".hash('xxh128', 'livewire-material')."::input'") + ->not->toContain(hash('xxh128', LivewireMaterialServiceProvider::componentPath())); +}); + +it('still renders a view compiled when the namespace came from the component path', function () { + $legacy = hash('xxh128', LivewireMaterialServiceProvider::componentPath()); + + expect(view()->exists($legacy.'::input'))->toBeTrue(); }); it('registers the components under a configured prefix', function () {