In den vergangenen Wochen erlebe ich in meiner Bubble einen Hype um das Thema NativePHP. Nun habe ich mich gefragt, was dahinter steckt – und vor allem: Ist PHP nun wirklich nativ?
Bevor wir einsteigen, möchte ich einen passenden Rahmen setzen. Dazu gehe ich kurz auf folgende Themen ein:
- Was wir Devs unter „nativ“ verstehen,
- Wie das Thema in Programmiersprachen wie C++, Rust und Go gelöst wird,
- Wo das Problem bei PHP liegt,
- Welche Möglichkeiten wir in PHP haben,
- Und wie NativePHP Dinge umsetzt.
Was verstehen wir Devs unter „nativ“?
Das Wort „nativ“ beschreibt grundsätzlich etwas Natürliches oder Heimisches. In der Softwareentwicklung bedeutet es, dass sich eine Applikation in einem System so verhält, als wäre sie ein integraler Bestandteil des Systems.
Am Ende des Tages sprechen wir von einer Applikation, die auf vielen Endgeräten ausgerollt werden kann.
An dieser Stelle sollten wir kurz klären: Was ist eigentlich eine Applikation?
Naja – it depends.
Wenn wir Backend-Entwickler von Applikationen sprechen, meinen wir oft ein Stück Code, das durch eine API, ein Terminal oder andere Mechanismen angestoßen wird – ganz ohne Browser oder visuelle Oberfläche.
Wenn Frontend-Entwickler von Applikationen sprechen, ist damit oft ein Stück Code gemeint, das im Browser ausgeführt wird. Also etwas, das sichtbar ist und über eine GUI gesteuert wird. Die meisten Frontends benötigen an irgendeiner Stelle ein Backend, um Dinge zu erledigen.
Merken wir uns also:
- Ein Backend kann grundsätzlich ohne ein Frontend existieren.
- Ein Frontend kann nur selten ohne ein Backend auskommen.
- Ein Frontend macht Dinge für Menschen einfacher (so zumindest die Theorie).
Wie wird eine Applikation ausgeführt?
Am Ende des Tages wollen wir Dinge erledigen. Dazu braucht es eine Instanz, die unsere Programm-Befehle versteht und in systemeigene Befehle übersetzt. Dieser Prozess lässt sich in zwei große Bereiche unterteilen:
- Compiling
- Laufzeit
Je nach Programmiersprache unterscheidet sich dieser Prozess erheblich.
Manche Programmiersprachen erlauben es, Code zu kompilieren, sodass er einfach ausgeführt werden kann. In diesem Fall erhalten wir eine ausführbare Datei, die ohne weitere Abhängigkeiten läuft – unabhängig davon, ob die Programmiersprache auf dem Zielsystem installiert ist.
Andere Programmiersprachen kompilieren den Code zur Laufzeit. Das bedeutet, dass bei der Ausführung ein Dienst existieren muss, der den Code interpretiert und ausführt. Solche Programme sind darauf angewiesen, dass eine passende Laufzeitumgebung auf dem Zielsystem vorhanden ist.
Merken wir uns also:
- Frontend und Backend werden jeweils unterschiedlich ausgeführt.
- Frontend-Code wird häufig im Browser interpretiert.
- Backend-Code läuft auf einem Gerät – im weitesten Sinne auf allem, das ein Betriebssystem oder Mikrocontroller hat.
Ich gehe nun auf drei Möglichkeiten ein:
- C++
- Rust & Go
- JavaScript
Wie funktioniert Cross-Plattform in C++?
C++ wird kompiliert – aber ganz so einfach ist es nicht. C++ kann sowohl statisch als auch dynamisch kompiliert werden:
- Statisch bedeutet, dass alle Abhängigkeiten in das Build integriert sind.
- Dynamisch bedeutet, dass Abhängigkeiten zur Laufzeit aufgelöst werden.
Am Ende des Tages spielt es keine Rolle, was wir auf unseren Entwicklungsmaschinen nutzen, solange unser Deployment-Prozess einheitlich funktioniert. Dabei helfen Tools wie CMake.
Merken wir uns:
- Es ist entscheidend, ob Abhängigkeiten statisch oder dynamisch eingebunden sind.
- Es gibt Tools (wie CMake), die plattformübergreifende Builds erleichtern – viele davon sind Open Source.
Wie funktioniert Cross-Plattform in Rust und Go?
Rust und Go sind „opinionated“ Sprachen – sie entstanden aus Schwächen anderer Sprachen heraus. Ihre Entwickler wollten Dinge besser machen.
Eine Frage die man sich stellen kann ist: Warum sollte der Programmcode auf dem Zielsystem interpretiert werden? Wenn wir ehrlich sind, gibt es darauf wenig sinnvolle Antworten.
Deshalb erzeugen beide Sprachen standardmäßig statische Builds, die direkt auf dem Zielsystem lauffähig sind.
Wie funktioniert Cross-Plattform in JavaScript?
JavaScript ist ein Sonderfall. Lange Zeit wurde es nur im Browser verwendet. Dann kam Node.js, das JavaScript auf den Server brachte.
Kaum eine Community beschäftigt sich so intensiv mit ihrer eigenen Sprache wie die JavaScript-Community. Daraus entstanden Konzepte wie:
- TypeScript – kein JavaScript schreiben, aber trotzdem JavaScript schreiben.
- Funfact – seit neuestem wird Go genutzt um TypeScript zu JavaScript zu kompilieren (source).
- CoffeeScript – eine weitere Alternative kein JavaScript zu schreiben, aber trotzdem JavaScript zu schreiben.
- Deno – eine Node.js-Alternative.
JavaScript braucht aber immer eine Laufzeitumgebung.
Im Kontext von Node.js und Cross-Plattform stellt das eine Herausforderung dar. In der JavaScript-Welt lösen wir Herausforderungen mit mehr Libraries und Tooling – logisch, oder?
Deshalb entstanden Setups wie:
- Electron, Ionic – für UI-basierte Cross-Plattform-Apps.
- Cordova – zur Übersetzung von JavaScript in Android- und iOS-kompatiblen Code.
Neuere Entwicklungen wie Capacitor (von Ionic) und Tauri gehen in Richtung „eine Sprache für alles“.
Merken wir uns:
- JavaScript wird sowohl für Frontend als auch Backend genutzt.
- Es wird immer zur Laufzeit interpretiert.
- Es gibt umfangreiches Tooling für Cross-Plattform-Entwicklung.
Wo liegt das Problem mit PHP und Cross-Plattform?
Kurz gesagt: Die Laufzeit.
PHP benötigt eine Laufzeitumgebung. Seit PHP 7.0 ist die Installation einfacher geworden, doch je nach Applikation müssen zusätzliche Abhängigkeiten installiert werden. Je nach Umgebung ist das Aufsetzen der Abhängigkeiten eine Hürde.
Das erschwert die Bereitstellung von PHP-Anwendungen.
Wie geht Cross-Plattform mit PHP dennoch?
Dann kam Jerry mit dem Paket static-php-cli. Dieses Tool nimmt uns viele Hürden ab.
Mit Static PHP CLI können wir PHP-Runtimes für verschiedene Zielsysteme erstellen. Mehr noch: Wir können damit komplette Applikationen samt Laufzeitumgebung paketieren.
Das bedeutet, dass ein PHP-Programm samt PHP-Laufzeit auf Windows, Ubuntu und anderen Systemen lauffähig ist. Ähnlich wie „Go Binary Distribution“ oder „PyInstaller“ für Python.
Meiner Einschätzung nach hat dieses Package das Potenzial, die Lawine auszulösen, die wir alle mit PHP 7.0 erwartet haben.
Was macht NativePHP nun?
NativePHP stellt statische PHP-Runtimes bereit und abstrahiert Electron, das über HTTP-Requests mit den PHP-Runtimes kommuniziert.
That’s it.
Es kommt mit den bekannten Einschränkungen von Static PHP CLI und Electron und funktioniert aktuell ausschließlich mit Electron. Aber es vereinfacht vieles. Electron bringt jedoch einen Overhead durch die eingebettete Chromium-Engine mit. Und sollte mit bedacht eingesetzt werden.
Noch zwei unkommentierte Links zum Kontext, wo der ausgeschriebene Tauri Support ist:
^Auch wenn es anders wirkt. Von mir Wertfrei an der Stelle. Wir Open-Source Nutzer vergessen manchmal wie viel (unbezahlter) Arbeit hinter so Projekten steckt.
Ist PHP nun nativ?
Nope. Ist PHP nun Cross-Plattform-fähig? Ja – und der Dank gebührt Static PHP CLI!

Schreibe einen Kommentar