static::$request_id, 'method' => 'minify', 'files' => [ [ 'type' => $type, 'content' => $content, 'filename' => $filename ] ] ]) . "\n"; fwrite($socket, $request); $response = fgets($socket); fclose($socket); if (!$response) { throw new RuntimeException("No response from minify RPC server"); } $result = json_decode($response, true); if (!isset($result['results'][$filename])) { throw new RuntimeException("Invalid response from minify RPC server"); } $file_result = $result['results'][$filename]; if ($file_result['status'] === 'error') { $error = $file_result['error']; throw new RuntimeException( "Minification failed for {$filename}: {$error['message']}" ); } return $file_result['result']; } /** * Force restart the RPC server * * Call this before production builds to ensure code changes take effect. */ public static function force_restart(): void { static::stop_rpc_server(force: true); static::$server_started = false; static::start_rpc_server(); } /** * Start RPC server for minification */ public static function start_rpc_server(): void { $socket_path = base_path(self::RPC_SOCKET); $server_script = base_path(self::RPC_SERVER_SCRIPT); if (!file_exists($server_script)) { throw new RuntimeException("Minify RPC server script not found at {$server_script}"); } // If socket exists, check if it's stale if (file_exists($socket_path)) { if (static::ping_rpc_server()) { static::$server_started = true; return; } static::stop_rpc_server(force: true); } // Ensure socket directory exists $socket_dir = dirname($socket_path); if (!is_dir($socket_dir)) { mkdir($socket_dir, 0755, true); } // Start RPC server $process = new Process([ 'node', $server_script, '--socket=' . $socket_path ]); $process->setWorkingDirectory(base_path()); $process->setTimeout(null); $process->start(); static::$rpc_server_process = $process; // Wait for server to be ready $max_wait_ms = 10000; $wait_interval_ms = 50; $iterations = $max_wait_ms / $wait_interval_ms; for ($i = 0; $i < $iterations; $i++) { usleep($wait_interval_ms * 1000); if (static::ping_rpc_server()) { static::$server_started = true; register_shutdown_function([self::class, 'stop_rpc_server']); return; } } throw new RuntimeException( "Minify RPC server failed to start within {$max_wait_ms}ms.\n" . "Check that Node.js, Terser, and cssnano are installed." ); } /** * Ping the RPC server */ public static function ping_rpc_server(): bool { $socket_path = base_path(self::RPC_SOCKET); if (!file_exists($socket_path)) { return false; } try { $socket = @stream_socket_client('unix://' . $socket_path, $errno, $errstr, 1); if (!$socket) { return false; } stream_set_blocking($socket, true); static::$request_id++; $request = json_encode([ 'id' => static::$request_id, 'method' => 'ping' ]) . "\n"; fwrite($socket, $request); $response = fgets($socket); fclose($socket); if (!$response) { return false; } $result = json_decode($response, true); return isset($result['result']) && $result['result'] === 'pong'; } catch (\Exception $e) { return false; } } /** * Stop the RPC server */ public static function stop_rpc_server(bool $force = false): void { $socket_path = base_path(self::RPC_SOCKET); if ($force) { if (file_exists($socket_path)) { try { $socket = @stream_socket_client('unix://' . $socket_path, $errno, $errstr, 1); if ($socket) { stream_set_blocking($socket, true); static::$request_id++; $request = json_encode([ 'id' => static::$request_id, 'method' => 'shutdown' ]) . "\n"; fwrite($socket, $request); fclose($socket); } } catch (\Exception $e) { // Ignore errors during force shutdown } usleep(100000); // 100ms if (file_exists($socket_path)) { @unlink($socket_path); } } if (static::$rpc_server_process) { if (static::$rpc_server_process->isRunning()) { static::$rpc_server_process->stop(1, SIGTERM); } static::$rpc_server_process = null; } static::$server_started = false; return; } // Graceful shutdown if (file_exists($socket_path)) { try { $socket = @stream_socket_client('unix://' . $socket_path, $errno, $errstr, 1); if ($socket) { stream_set_blocking($socket, true); static::$request_id++; $request = json_encode([ 'id' => static::$request_id, 'method' => 'shutdown' ]) . "\n"; fwrite($socket, $request); fclose($socket); } } catch (\Exception $e) { // Ignore errors } } static::$server_started = false; } }