laravel-workersv0.4.10
documentation

docs / Architecture

Architecture

PHP runs at build time only, in phase workers that each boot the app at most once. Everything the edge executes is generated JavaScript and a schema.

The pipeline

Seven stages, and exactly one boundary: S0 is the only stage that runs your PHP application, and everything from S1 on is generated or plain JavaScript. The stage names are the repository's own.

stagewhatwhere
S0dump — PHP boots the app and dumps what only Laravel knows: routes, compiled Blade, the schema from the migrations, config, schedule, events. The first of the build phase workers.tools/*.php
S1transpile — Blade to JS, routes to a router, migrations to schema.json, controllers to handlers. Outside the supported subset is a compile error (LW001 to LW004).tools/*.mjs, compiler/
S2bundler — The Workers-native kernel and the generated modules are bundled into one Worker ESM.dist/src/worker.mjs
S3golden tests — The real Laravel render and the compiled render are compared; the shadow harness diffs a whole request: status, headers, body.shadow/, compiler/tests/
S4gate — --strict fails the build on a route with no handler, snapshot or port. The READINESS block is the verdict.tools/readiness.mjs
S5prerender — Clean GET routes render to static snapshots, served as assets with zero invocations. Its own phase worker, still at build time.tools/prerender.php
S6deploy — wrangler deploys the Worker, the static assets and D1; the state file records what was deployed.tools/deploy.mjs

One boot per phase

A full build runs every PHP-live step as a phase-scoped worker. Each phase boots Laravel at most once — not at all when its job list is empty — and processes every closure inside that same boot.

phaseworkerLaravel boots
schematools/schema-compile.php1
snapshotstools/prerender.php0–1 (when prerender URIs exist)
route and error viewstools/compile-view.php --batch1
metadatatools/metadata-phase.php0–1 (models, FormRequests)
controller viewstools/compile-view.php --batch0–1 (controllers)

Measured, not estimated: instrumenting every PHP process a --no-cache build spawns on the 43-route fixture recorded exactly 5 Laravel boots, plus onephp -r version probe. Route export, config, schedule, events, class metadata and controller extraction never call PHP.

The build cache

Before any live work, the build hashes its inputs by content, not mtime: app sources, Composer identity files and the autoloader, build-tool sources, Vite/Tailwind/PostCSS configs and manifests, .env, the PHP version, the CLI flags and curated LW_* keys. On the fixture app that is 199 files, about 3.0 MB.

  • A hit needs the same key and the files every build emits still in dist/; a deleted or half-written dist is a miss, never a stale worker.
  • Measured: about 1.3 s on a hit against about 35 s full, with zero Laravel boots.
  • --no-cache skips only the hit check; a forced build still refreshes the stamp.
  • What the key does not hash does not invalidate — that is what the escape hatch is for. CI should use --no-cache regardless, because a hit prints no READINESS block.

What the artifact is made of

repositoryshell
compiler/          Blade to PHP to JS at build time (+ the transpiled runtime)
kernel/            request-time runtime: http, router, db, session, csrf, auth,
                   validator, cache, storage, mail, paginator, php-json, php-serialize
tools/             build-time PHP + JS: schema, views, metadata, deploy, doctor, cache
shadow/            the proof harness (real PHP app vs the compiled worker)
build.mjs          the phase-scoped pipeline, which writes dist/
bin/               the laravel-workers CLI

The published package is the same tree plus docs/, MAP.md,COMPILED.md and CHANGELOG.md; the tests are excluded from the tarball.

How it is proven

Three layers of evidence, all runnable:

  • Parity — the corpus (55/55) byte-compares the compiled render against the PHP 8.3 expectation, and the shadow harness diffs whole requests against the real app.
  • Integration — the kernel suite runs against a real in-memory SQLite, a real request pipeline and a real guard port, not mocks.
  • Platform — npm run gate:cpu deploys a probe worker on a real account, reads cpuTime and outcome back through wrangler tail, and asserts both the budget and that a burn is caught.

This site's audit is a fourth layer: an independent extraction of the repository's own claims, with the commit and the file attached to every figure.

Source: README.md Architecture, Build phases, Build cache, What's inside; MAP.md sections 4 to 6 — repository ba1e9a5