On a high level, WordPress Playground works in web browsers as follows:
The index.html file on playground.wordpress.net loads the remote.html file via an <iframe src="https://developer.wordpress.org/remote.html">.
remote.html starts a Worker Thread and a ServiceWorker and sends back the download progress information.
The Worker Thread starts PHP and populates the filesystem with a WordPress patched to run on SQLite.
The ServiceWorker starts intercepting all HTTP requests and forwarding them to the Worker Thread.
remote.html creates an <iframe src="https://developer.wordpress.org/index.php">, and the Service Worker forwards the index.php request to the Worker Thread where the WordPress homepage is rendered.
Visually, it looks like this:
High-level ideas
The @php-wasm/web is built on top of the following ideas:
Browser tab orchestrates everything – The browser tab is the main program. Closing or reloading it means destroying the entire execution environment.
Iframe-based rendering – Every response produced by the PHP server must be rendered in an iframe to avoid reloading the browser tab when the user clicks on a link.
PHP Worker Thread – The PHP server is slow and must run in a web worker, otherwise handling requests freezes the website UI.
Service Worker routing – All HTTP requests originating in that iframe must be intercepted by a Service worker and passed on to the PHP worker thread for rendering.