diff --git a/packages/framework/src/Facades/Vite.php b/packages/framework/src/Facades/Vite.php index b778f928789..d93f60f742d 100644 --- a/packages/framework/src/Facades/Vite.php +++ b/packages/framework/src/Facades/Vite.php @@ -18,19 +18,8 @@ public static function running(): bool return true; } - // Check if Vite dev server is running by attempting to connect to it - // Todo: Improve performance on Windows (takes less than 1ms on macOS, but around 100ms on Windows) - set_error_handler(fn () => false); // Todo: This warning surpressor does not work on Windows - $server = fsockopen('localhost', 5173, $errno, $errstr, 0.1); - restore_error_handler(); - - if ($server) { - fclose($server); - - return true; - } - - return false; + // Check for Vite hot file + return Filesystem::exists('app/storage/framework/cache/vite.hot'); } public static function assets(array $paths): HtmlString diff --git a/packages/framework/tests/Unit/Facades/ViteFacadeTest.php b/packages/framework/tests/Unit/Facades/ViteFacadeTest.php index d056f0e3dc0..2219d319ceb 100644 --- a/packages/framework/tests/Unit/Facades/ViteFacadeTest.php +++ b/packages/framework/tests/Unit/Facades/ViteFacadeTest.php @@ -4,12 +4,22 @@ use Hyde\Testing\UnitTestCase; use Hyde\Facades\Vite; +use Hyde\Testing\CreatesTemporaryFiles; /** * @covers \Hyde\Facades\Vite */ class ViteFacadeTest extends UnitTestCase { + use CreatesTemporaryFiles; + + protected static bool $needsKernel = true; + + protected function tearDown(): void + { + $this->cleanUpFilesystem(); + } + public function testRunningReturnsTrueWhenEnvironmentVariableIsSet() { putenv('HYDE_SERVER_VITE=enabled'); @@ -19,17 +29,14 @@ public function testRunningReturnsTrueWhenEnvironmentVariableIsSet() putenv('HYDE_SERVER_VITE'); } - public function testRunningReturnsTrueWhenViteServerIsAccessible() + public function testRunningReturnsTrueWhenViteHotFileExists() { - // Create a mock server to simulate Vite - $server = stream_socket_server('tcp://localhost:5173'); + $this->file('app/storage/framework/cache/vite.hot'); $this->assertTrue(Vite::running()); - - stream_socket_shutdown($server, STREAM_SHUT_RDWR); } - public function testRunningReturnsFalseWhenViteServerIsNotAccessible() + public function testRunningReturnsFalseWhenViteHotFileDoesNotExist() { $this->assertFalse(Vite::running()); } diff --git a/vite.config.js b/vite.config.js index f9b614b0816..7e70d1dcae5 100644 --- a/vite.config.js +++ b/vite.config.js @@ -9,6 +9,34 @@ import autoprefixer from 'autoprefixer'; import fs from 'fs'; import path from 'path'; +const hydeVitePlugin = () => ({ + name: 'hyde-vite', + configureServer(server) { + // Create hot file when Vite server starts + fs.writeFileSync(path.resolve(process.cwd(), 'app/storage/framework/cache/vite.hot'), ''); + + // Remove hot file when Vite server closes + ['SIGINT', 'SIGTERM'].forEach(signal => { + process.on(signal, () => { + fs.rmSync(path.resolve(process.cwd(), 'app/storage/framework/cache/vite.hot')); + process.exit(); + }); + }); + + // Render the Vite index page when the root URL is requested + server.middlewares.use((req, res, next) => { + if (req.url === '/') { + res.end(fs.readFileSync( + path.resolve(__dirname, 'vendor/hyde/realtime-compiler/resources/vite-index-page.html'), + 'utf-8' + )); + } else { + next(); + } + }); + } +}); + export default defineConfig({ server: { port: 5173, @@ -18,23 +46,7 @@ export default defineConfig({ }, middlewareMode: false, }, - plugins: [ - { - name: 'hyde-vite-server', - configureServer(server) { - server.middlewares.use((req, res, next) => { - if (req.url === '/') { - res.end(fs.readFileSync( - path.resolve(__dirname, 'vendor/hyde/realtime-compiler/resources/vite-index-page.html'), - 'utf-8' - )); - } else { - next(); - } - }); - }, - }, - ], + plugins: [hydeVitePlugin()], css: { postcss: { plugins: [