From 3bddb235e7b7fe06e255f0ccfb6af3e485cc8659 Mon Sep 17 00:00:00 2001 From: Jeremiasz Major Date: Fri, 11 Oct 2024 11:20:49 +0200 Subject: [PATCH 1/5] dev ssr --- src/Ssr/HttpGateway.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Ssr/HttpGateway.php b/src/Ssr/HttpGateway.php index 62b92717..89560e66 100644 --- a/src/Ssr/HttpGateway.php +++ b/src/Ssr/HttpGateway.php @@ -3,20 +3,29 @@ namespace Inertia\Ssr; use Exception; +use Illuminate\Foundation\Vite; use Illuminate\Support\Facades\Http; class HttpGateway implements Gateway { + public function __construct( + private Vite $vite, + ) { + } + /** * Dispatch the Inertia page to the Server Side Rendering engine. */ public function dispatch(array $page): ?Response { - if (! config('inertia.ssr.enabled', true) || ! (new BundleDetector)->detect()) { + if ($this->vite->isRunningHot()) { + $url = file_get_contents($this->vite->hotFile()).'/render'; + } elseif (config('inertia.ssr.enabled', true) || (new BundleDetector)->detect()) { + $url = str_replace('/render', '', config('inertia.ssr.url', 'http://127.0.0.1:13714')).'/render'; + } else { return null; } - $url = str_replace('/render', '', config('inertia.ssr.url', 'http://127.0.0.1:13714')).'/render'; try { $response = Http::post($url, $page)->throw()->json(); From 707fed2c606ebf0d137b268df32c4eda41841ceb Mon Sep 17 00:00:00 2001 From: Jeremiasz Major Date: Mon, 14 Oct 2024 12:17:07 +0200 Subject: [PATCH 2/5] fix condition --- src/Ssr/HttpGateway.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Ssr/HttpGateway.php b/src/Ssr/HttpGateway.php index 89560e66..b144eb69 100644 --- a/src/Ssr/HttpGateway.php +++ b/src/Ssr/HttpGateway.php @@ -19,8 +19,10 @@ public function __construct( public function dispatch(array $page): ?Response { if ($this->vite->isRunningHot()) { + // todo: maybe ask laravel to make Vite::hotAsset() public + // $url = $this->vite->hotAsset('render'); $url = file_get_contents($this->vite->hotFile()).'/render'; - } elseif (config('inertia.ssr.enabled', true) || (new BundleDetector)->detect()) { + } elseif (config('inertia.ssr.enabled', true) && (new BundleDetector)->detect()) { $url = str_replace('/render', '', config('inertia.ssr.url', 'http://127.0.0.1:13714')).'/render'; } else { return null; From 311edbc5c23d803c498b15cd87d421e4617a1f71 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 6 Jun 2025 13:00:18 +0200 Subject: [PATCH 3/5] Refactor + added tests --- tests/DirectiveTest.php | 2 - tests/HttpGatewayTest.php | 126 ++++++++++++++++++++++++++++++++++++++ tests/Stubs/bundle.js | 1 + tests/TestCase.php | 2 + 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 tests/HttpGatewayTest.php create mode 100644 tests/Stubs/bundle.js diff --git a/tests/DirectiveTest.php b/tests/DirectiveTest.php index f1afdd07..40e8bf73 100644 --- a/tests/DirectiveTest.php +++ b/tests/DirectiveTest.php @@ -30,8 +30,6 @@ class DirectiveTest extends TestCase /** * Example Page Objects. */ - protected const EXAMPLE_PAGE_OBJECT = ['component' => 'Foo/Bar', 'props' => ['foo' => 'bar'], 'url' => '/test', 'version' => '', 'encryptHistory' => false, 'clearHistory' => false]; - protected function setUp(): void { parent::setUp(); diff --git a/tests/HttpGatewayTest.php b/tests/HttpGatewayTest.php new file mode 100644 index 00000000..78bbc60b --- /dev/null +++ b/tests/HttpGatewayTest.php @@ -0,0 +1,126 @@ +gateway = new HttpGateway; + + Http::preventStrayRequests(); + } + + public function test_it_returns_null_when_ssr_is_disabled() + { + config([ + 'inertia.ssr.enabled' => false, + 'inertia.ssr.bundle' => __DIR__.'/Stubs/bundle.js', + ]); + + Vite::shouldReceive('isRunningHot')->never(); + + $this->assertNull($this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT])); + } + + public function test_it_returns_null_when_no_bundle_file_is_detected_and_vite_is_not_running() + { + config([ + 'inertia.ssr.enabled' => true, + 'inertia.ssr.bundle' => null, + ]); + + Vite::shouldReceive('isRunningHot')->andReturn(false); + + $this->assertNull($this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT])); + } + + public function test_it_uses_the_configured_http_url_when_the_bundle_file_is_detected() + { + config([ + 'inertia.ssr.enabled' => true, + 'inertia.ssr.bundle' => __DIR__.'/Stubs/bundle.js', + ]); + + Vite::shouldReceive('isRunningHot')->andReturn(false); + + Http::fake([ + $this->gateway->getHttpUrl() => json_encode([ + 'head' => ['SSR Test', ''], + 'body' => '
SSR Response
', + ]), + ]); + + $this->assertNotNull( + $response = $this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT]) + ); + + $this->assertEquals("SSR Test\n", $response->head); + $this->assertEquals('
SSR Response
', $response->body); + } + + public function test_it_uses_the_vite_asset_when_it_is_running_hot_even_if_a_bundle_file_is_present() + { + config([ + 'inertia.ssr.enabled' => true, + 'inertia.ssr.bundle' => __DIR__.'/Stubs/bundle.js', + ]); + + Vite::shouldReceive('isRunningHot')->andReturn(true); + Vite::shouldReceive('asset')->with('render')->andReturn($viteUrl = 'http://localhost:3000/some-url'); + + Http::fake([ + $viteUrl => json_encode([ + 'head' => ['SSR Test', ''], + 'body' => '
SSR Response
', + ]), + ]); + + $this->assertNotNull( + $response = $this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT]) + ); + + $this->assertEquals("SSR Test\n", $response->head); + $this->assertEquals('
SSR Response
', $response->body); + } + + public function test_it_returns_null_when_the_http_request_fails() + { + config([ + 'inertia.ssr.enabled' => true, + 'inertia.ssr.bundle' => __DIR__.'/Stubs/bundle.js', + ]); + + Vite::shouldReceive('isRunningHot')->andReturn(false); + + Http::fake([ + $this->gateway->getHttpUrl() => Http::response(null, 500), + ]); + + $this->assertNull($this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT])); + } + + public function test_it_returns_null_when_invalid_json_is_returned() + { + config([ + 'inertia.ssr.enabled' => true, + 'inertia.ssr.bundle' => __DIR__.'/Stubs/bundle.js', + ]); + + Vite::shouldReceive('isRunningHot')->andReturn(false); + + Http::fake([ + $this->gateway->getHttpUrl() => 'invalid json', + ]); + + $this->assertNull($this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT])); + } +} diff --git a/tests/Stubs/bundle.js b/tests/Stubs/bundle.js new file mode 100644 index 00000000..940a3ff0 --- /dev/null +++ b/tests/Stubs/bundle.js @@ -0,0 +1 @@ +console.log("Hello world!"); diff --git a/tests/TestCase.php b/tests/TestCase.php index 9e2a8833..a47918b1 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -10,6 +10,8 @@ abstract class TestCase extends Orchestra { + protected const EXAMPLE_PAGE_OBJECT = ['component' => 'Foo/Bar', 'props' => ['foo' => 'bar'], 'url' => '/test', 'version' => '', 'encryptHistory' => false, 'clearHistory' => false]; + protected function getPackageProviders($app): array { return [ From 15905e13bfa01601a18c04076308457fe23cd990 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 6 Jun 2025 13:03:16 +0200 Subject: [PATCH 4/5] Added Guzzle as dev dependency --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6cf6f0c4..75908c80 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,7 @@ "symfony/console": "^6.2|^7.0" }, "require-dev": { + "guzzlehttp/guzzle": "^7.2", "roave/security-advisories": "dev-master", "orchestra/testbench": "^8.0|^9.2|^10.0", "mockery/mockery": "^1.3.3", @@ -52,4 +53,4 @@ }, "minimum-stability": "dev", "prefer-stable": true -} +} \ No newline at end of file From 341e206de69b59edde79f6e73f1538635375b729 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Fri, 6 Jun 2025 13:07:39 +0200 Subject: [PATCH 5/5] Fix tests on Laravel 10 --- tests/HttpGatewayTest.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/HttpGatewayTest.php b/tests/HttpGatewayTest.php index 78bbc60b..1fb16c8e 100644 --- a/tests/HttpGatewayTest.php +++ b/tests/HttpGatewayTest.php @@ -53,10 +53,10 @@ public function test_it_uses_the_configured_http_url_when_the_bundle_file_is_det Vite::shouldReceive('isRunningHot')->andReturn(false); Http::fake([ - $this->gateway->getHttpUrl() => json_encode([ + $this->gateway->getHttpUrl() => Http::response(json_encode([ 'head' => ['SSR Test', ''], 'body' => '
SSR Response
', - ]), + ])), ]); $this->assertNotNull( @@ -78,10 +78,10 @@ public function test_it_uses_the_vite_asset_when_it_is_running_hot_even_if_a_bun Vite::shouldReceive('asset')->with('render')->andReturn($viteUrl = 'http://localhost:3000/some-url'); Http::fake([ - $viteUrl => json_encode([ + $viteUrl => Http::response(json_encode([ 'head' => ['SSR Test', ''], 'body' => '
SSR Response
', - ]), + ])), ]); $this->assertNotNull( @@ -118,7 +118,7 @@ public function test_it_returns_null_when_invalid_json_is_returned() Vite::shouldReceive('isRunningHot')->andReturn(false); Http::fake([ - $this->gateway->getHttpUrl() => 'invalid json', + $this->gateway->getHttpUrl() => Http::response('invalid json'), ]); $this->assertNull($this->gateway->dispatch(['page' => self::EXAMPLE_PAGE_OBJECT]));