22: Prestatie
Een Phlo-app die de conventies in deze gids volgt, begint vanuit een sterke Lighthouse-positie, omdat de architectuur al het meeste doet wat de audits meten: server-gerenderde HTML, één kleine uitgestelde script, één stylesheet, geen framework payload en geen externe verzoeken. Dit hoofdstuk koppelt correct Phlo-gebruik aan de beste praktijken voor webprestaties en behandelt het deel dat van jou blijft: afbeeldingen, markup en metingen.

22.1: Wat het platform al doet
Elke view()-respons is volledige server-gerenderde HTML. De eerste weergave is echte inhoud, er is geen hydratatiestap en geen client-side rendering om op te wachten, dus First Contentful Paint en Largest Contentful Paint worden bepaald door je servertijd en je afbeeldingen, niet door een framework.
De assets zijn even spaarzaam. De build compileert alle frontend-code in één app.js (de phlo.js-runtime plus je gecompileerde scripts, meestal een paar tientallen kilobytes) en alle stijlen in één app.css. view() omvat het script met defer, zodat het de rendering nooit blokkeert, en geeft Link: rel=preload-headers voor de stylesheet, de scripts en de icon sprite, zodat de browser ze begint op te halen voordat het de HTML parseert. Elke asset-URL bevat een ?version cache-buster van %app->version, wat lange cachelevensduur veilig maakt: verhoog de versie bij release en elke client haalt precies één keer opnieuw op.
Daarvoor biedt FrankenPHP HTTP/2 en HTTP/3 met automatische HTTPS en comprimeert het antwoorden (zstd, brotli, gzip) wanneer je vhost dit inschakelt. Dit vereist geen configuratie in de app.
22.2: Server tijd: worker modus
Time to First Byte is de enige Lighthouse-metric die volledig op je server leeft. In productie, voer de release build uit in worker mode (thread in de entry): de app blijft gecompileerd en resident in het geheugen, zodat een verzoek je route uitvoert zonder enige bootstrap. De ontwikkelingsmodus (build: true) controleert bronnen en kan tijdens een verzoek opnieuw bouwen; het is de juiste modus om in te ontwikkelen en de verkeerde modus om benchmarks uit te voeren.
Daarbuiten is servertijd gewone backend discipline: houd queries geïndexeerd en beperkt (hoofdstuk 8 behandelt ORM caching), en duw langzame taken uit het verzoek. Voor echt trage reacties streamt chunk() output regel voor regel, zodat de browser geleidelijk weergeeft in plaats van naar een lege pagina te staren. Voor terugkerend werk verplaatst %app->tasks het volledig uit verzoeken.
22.3: Afbeeldingen
Afbeeldingen bepalen de meeste LCP-scores in de echte wereld, en ze blijven jouw verantwoordelijkheid. De gebundelde img resource past de grootte aan, snijdt bij en converteert met GD, dus serveer geschaalde bestanden (een miniatuur waar een miniatuur wordt weergegeven) en geef de voorkeur aan WebP-uitvoer. Geef in de markup elke <img> een width en height (of CSS aspect-ratio) zodat de lay-out niet verschuift wanneer deze laadt, gebruik loading=lazy voor afbeeldingen onder de vouw, en laad de LCP-afbeelding zelf nooit lui.
Statische bestanden moeten langlevende cacheheaders van de webserver verzenden (Cache-Control: public, immutable met een lange max-age); de ?version buster op gegenereerde assets maakt dat veilig, en afbeeldings-URL's die veranderen wanneer de inhoud verandert, doen hetzelfde voor uploads.
22.4: Navigatie: de SPA zonder de framework rekening
Met de DOM/link resource (of app.get() vanuit je eigen script) is een navigatie binnen de app één XHR die apply() commando's retourneert: de server stuurt alleen de DOM-wijzigingen, de client past deze toe en path: werkt de URL bij. Er is geen volledige herlaadbeurt, geen her-download van CSS en JS, en Terug en Vooruit herstellen snapshots onmiddellijk uit de geschiedenis. View-overgangen animeren de wissel zonder dat dit een round trip kost.
Hier komt de zero-dependency houding van Phlo direct ten goede in de Performance en Best Practices audits: er is geen framework bundle om te downloaden, parseren en uitvoeren, en geen derde partij om verbinding mee te maken. De blocking-time metrics (Total Blocking Time, interactie-latentie) blijven laag omdat de totale JavaScript op de pagina de runtime plus wat je hebt geschreven is, niets meer.
22.5: De andere drie audits
Toegankelijkheid is grotendeels markup, en Phlo geeft je de markup zonder toevoegingen: geen gegenereerde wrappers, geen synthetische knoppen. Gebruik het semantische element (<button>, <nav>, <main>), geef afbeeldingen betekenisvolle alt-tekst, label formulier velden, en zorg voor voldoende contrast in je thema. De lang-attribuut wordt automatisch ingesteld vanuit %app->lang.
Beste Praktijken vereist HTTPS, een nette console en geen verouderde API's. FrankenPHP's automatische HTTPS dekt transport; de CSP-modi van de security resource (hoofdstuk 12) dekken beleid; en de discipline van de engine zonder veroudering houdt de console schoon. Controleer de console op de release build eenmaal per release: een verdwaalde 404 op een asset kost punten en is altijd een echte bug.
SEO is hoofdstuk 17: de seo resource levert de sitemap, robots, canonieke link en meta-instellingen vanuit props die je al hebt gedefinieerd. Een Phlo-app met actieve seo en correct ingesteld indexable scoort deze audit zonder verdere inspanning.
22.6: Eerlijk meten
Meet de release build op de productiehost, in een privévenster, tegen de openbare URL. De ontwikkelingsmodus vertekent elk cijfer: build: true kan tijdens het verzoek opnieuw bouwen, debug voegt een debugpayload toe aan de reacties, en een dev vhost kan de compressie- en cacheheaders van de productieversie missen. Lighthouse bevindt zich in Chrome DevTools; PageSpeed Insights voert dezelfde audits uit vanuit de infrastructuur van Google en voegt veldgegevens toe wanneer je site verkeer heeft.
Wanneer een score daalt, lees de trace voordat je code wijzigt: de audit noemt de resource en de milliseconden. In een correct geconfigureerde Phlo-app zijn de gebruikelijke verdachten, in volgorde: een niet-schaalbare of niet-lazy afbeelding, een trage query in de route, en een ontbrekende cacheheader op een statisch bestand. Alle drie zijn zichtbaar in de waterval, en geen van hen is het framework.