The build pipeline lives in a Dockerfile
. In broad strokes, it:
- Installs all the necessary linux packages (like
build-essential
) - Downloads PHP and the required libraries, e.g.
sqlite3
. - Applies a few patches.
- Compiles everything using Emscripten, a drop-in replacement for the C compiler.
- Compiles
php_wasm.c
โ a convenient API for JavaScript. - Outputs a
php.wasm
file and one or more JavaScript loaders, depending on the configuration. - Transforms the Emscripten’s default
php.js
output into an ESM module with additional features.
To find out more about each step, refer directly to the Dockerfile.
Building
To build all PHP versions, run npm run recompile:php:web
(or php-wasm-node
) in the repository root. You’ll find the output files in packages/php-wasm/php-web/public
. To build a specific version, run npm run recompile:php:web:kitchen-sink:8.0
or npm run recompile:php:web:light:8.0
โ depending on the build pack.
The build produces two files: php.wasm
and php.js
.
PHP.wasm WebAssembly module
PHP extensions
PHP is built with several extensions listed in the Dockerfile
.
Some extensions, like zip
, can be turned on or off during the build. Others, like sqlite3
, are hardcoded.
If you need to turn off one of the hardcoded extensions, feel free to open an issue in this repo. Better yet, this project needs contributors. You are more than welcome to open a PR and author the change you need.
C API exposed to JavaScript
The C API exposed to JavaScript lives in the php_wasm.c
file.
Refer to the source code and the inline documentation in php_wasm.c
to learn more.
Build configuration
The build is configurable via the Docker --build-arg
feature. You can set them up through the build.js
script, just run this command to get the usage message:
npm run recompile:php:web
PHP.js JavaScript module
The php.js
file generated by the WebAssembly PHP build pipeline is not a vanilla Emscripten module. Instead, it’s an ESM module that wraps the regular Emscripten output and adds some extra functionality.
Here’s the API it exposes:
// php.wasm size in bytes:
export const dependenciesTotalSize = 5644199;
// php.wasm filename:
export const dependencyFilename = 'php.wasm';
// Run Emscripten's generated module:
export default function (jsEnv, emscriptenModuleArgs) {}
The generated JavaScript module is not meant for direct use. Instead, it can be consumed through a NodePHP
class in Node.js and a WebPHP
class in the browser:
// In Node.js:
const php = NodePHP.load('7.4');
// On the web:
const php = await WebPHP.load('8.0');
Both of these classes extend the BasePHP
class exposed by the @php-wasm/universal
package and implement the UniversalPHP
interface that standardizes the API across all PHP environments.
Loading the PHP runtime
The load() method handles the entire PHP initialization pipeline. In particular, it:
- Instantiates the Emscripten PHP module
- Wires it together with the data dependencies and loads them
- Ensures is all happens in a correct order
- Waits until the entire loading sequence is finished