P
imvdmolen.nl
Blog

Expose.dev voor lokale ontwikkeling: Hoe ik mijn development workflow verbeter

Laatste week zat ik met een vervelend probleem. Een klant wilde een nieuwe feature zien die ik net had gebouwd in Laravel, maar hij was onderweg en had alleen zijn iPad bij zich. Mijn ontwikkelomgeving draaide lokaal op Herd, dus ik moest een manier vinden om mijn localhost toegankelijk te maken vanaf internet. Poorten openzetten op mijn router is iets wat ik principieel vermijd, en ngrok had ik in het verleden gebruikt maar dat werd altijd traag bij grotere uploads. Expose.dev kwam als redder in nood.

Expose werkt eigenlijk vrij simpel: het creëert een beveiligde tunnel tussen jouw lokale machine en een publiekelijk toegankelijke URL. Installeer de CLI, voer een commando uit, en binnen seconden heb je een werkende verbinding. Geen servers configureren, geen DNS-records wijzigen, geen gedoe met firewall-regels. Voor mijn Laravel Herd project dat op poort 8000 draaide, was het letterlijk één regel:

expose share http://localhost:8000

Direct krijg je een tijdelijke URL terug die je kunt delen met wie je maar wilt. Bezoekt iemand die URL, dan routeert het verkeer via de Expose-servers naar jouw lokale machine. Zolang de tunnel actief blijft, werkt alles precies zoals je het gewend bent: cookies, sessies, WebSocket-verbindingen, het hele circus. Ik was binnen twee minuten klaar en kon mijn klant een werkende link sturen.

HTTPS en SSL-configuratie

Zodra cookies of authenticatie onderdeel zijn van je applicatie, wil je eigenlijk altijd met HTTPS werken. Expose ondersteunt dit van nature, maar je hebt wel je eigen SSL-certificaten nodig. Voor lokale ontwikkeling gebruik ik meestal zelfondertekende certificaten die ik met OpenSSL genereer:

expose dev --https --key=/path/to/ssl/key --cert=/path/to/ssl/cert

Deze aanpak levert een volledig versleutelde tunnel op waarbij alle communicatie via TLS loopt. Wat ik bijzonder handig vind, is dat ik in PHPStorm de externe URL kan koppelen als remote server voor debugging. Daarmee kan ik breakpoints zetten terwijl een externe gebruiker de applicatie gebruikt. Vooral nuttig bij bugs die alleen optreden op specifieke apparaten of in bepaalde netwerkomgevingen waar ik zelf geen toegang tot heb.

De SSL-setup kost wat extra tijd in het begin, maar eenmaal geconfigureerd scheelt het een hoop hoofdpijn. Browser-waarschuwingen over onveilige verbindingen zijn irritant voor klanten, en sommige moderne webfeatures werken simpelweg niet zonder HTTPS. Progressive Web App features, geolocation APIs, camera-toegang: het vereist allemaal een beveiligde verbinding.

Beveiliging en toegangscontrole

Een publieke tunnel betekent ook een potentieel veiligheidsrisico. Iedereen die de URL in handen krijgt, heeft toegang tot jouw lokale omgeving. Gelukkig biedt Expose wachtwoordbeveiliging per tunnel, zodat alleen mensen met de juiste credentials kunnen doorkomen. Voor demo-sessies met bekende klanten schakel ik dit meestal in. Het voegt een extra laag beveiliging toe zonder veel overhead.

Langduriger tunnels, waarbij ik de verbinding een aantal uur open laat staan, combineer ik vaak met firewall-regels die de tunnel beperken tot specifieke IP-adressen. Dit doe ik vooral als ik weet dat de klant vanaf een vast kantoornetwerk werkt. Extra beveiliging kan geen kwaad, zeker als je project gevoelige testdata bevat.

Belangrijk om te beseffen is dat zonder versleuteling al het verkeer in plaintext zichtbaar is voor de Expose-servers. Voor productiedata zou ik dat nooit accepteren, maar voor een lokale dev-omgeving zonder gevoelige informatie is het tijdelijk wel werkbaar. Gratis accounts hebben sowieso beperkte sessietijden, dus de tunnels worden automatisch na een tijdje afgesloten.

Cross-device testing en debugging

De meeste waarde haal ik uit Expose bij drie specifieke scenario's: cross-device testing, remote debugging en client reviews. Responsive design controleer ik normaal gesproken via de devtools in Chrome of Firefox, maar soms gedraagt een echte iPhone of Android-telefoon zich compleet anders dan de browser-emulator suggereert. Touch-events, viewport-gedrag, font-rendering: er zijn zoveel kleine verschillen die alleen op het echte apparaat naar boven komen.

Met een actieve tunnel test ik direct op het daadwerkelijke apparaat, inclusief alle browser-specifieke eigenaardigheden die Safari Mobile of Chrome Android met zich meebrengen. Scroll-behavior in iOS Safari is bijvoorbeeld een klassieker: in de desktop-simulator ziet alles er prima uit, maar op het echte apparaat blijkt opeens dat je fixed headers niet werken zoals verwacht door de dynamische viewport-hoogte.

Remote debugging wordt ook een stuk makkelijker met Expose. Klanten rapporteren vaak bugs met beschrijvingen als "het werkt niet op mijn telefoon" of "de knop doet niks op mijn laptop". Met een tunnel kan ik ze vragen om de exacte stappen uit te voeren terwijl ik meekijk via de developer tools. Veel effectiever dan eindeloos heen-en-weer mailen over screenshots en foutmeldingen.

Livewire en moderne PHP frameworks

Bij Livewire-projecten werkt Expose probleemloos. Livewire communiceert via reguliere HTTP-requests en AJAX-calls, die allemaal netjes via de tunnel worden gerouteerd. Geen speciale configuratie of aanpassingen nodig aan je componenten:

use Livewire\Component;

class ProductSearch extends Component
{
    public $search = '';
    public $results = [];

    public function updatedSearch()
    {
        $this->results = Product::where('name', 'like', '%' . $this->search . '%')
            ->take(10)
            ->get();
    }

    public function render()
    {
        return view('livewire.product-search');
    }
}

WebSocket-verbindingen voor real-time features werken ook prima door de tunnel heen. Laravel Echo met Pusher of Socket.IO: alles functioneert alsof je lokaal werkt. Ik heb zelfs Laravel Reverb (de nieuwe WebSocket-server) via Expose kunnen demonstreren aan klanten, zonder dat zij merkten dat de backend op mijn ontwikkelmachine draaide.

Voor Laravel Sanctum API-authenticatie moet je wel oppassen met de CORS-instellingen. De externe URL van Expose moet worden toegevoegd aan je cors.php configuratie, anders blokkeren browsers de requests. Een kleine aanpassing in je .env bestand en je bent weer operationeel.

Configuratie en workflow-optimalisatie

Voor projecten waar ik regelmatig een tunnel gebruik, sla ik de instellingen op in een expose.json bestand in de projectroot. Hierin definieer ik de standaardpoort, SSL-certificaatlocaties en eventuele authenticatie-opties. Scheelt tijd en voorkomt typefouten bij herhaald gebruik:

{
    "host": "localhost:8000",
    "auth": "username:password",
    "https": {
        "key": "./ssl/key.pem",
        "cert": "./ssl/cert.pem"
    }
}

Een handige workflow die ik vaak gebruik: start de tunnel op, zet de URL in een gedeelde Slack-chat of Teams-kanaal, en laat het team er doorheen klikken terwijl ik wijzigingen maak. Real-time feedback krijgen terwijl je aan het coderen bent, is onbetaalbaar voor de ontwikkelsnelheid. Vooral bij frontend-werk waar visuele details belangrijk zijn.

Expose is uiteraard niet bedoeld voor permanente omgevingen. Voor langdurige demo's of staging heb je gewoon een echte server nodig. Maar voor die momenten waar je snel iets wilt laten zien zonder een hele deployment-pipeline op te starten, is het moeilijk te verslaan. Ik gebruik het inmiddels wekelijks, en het heeft al menig client-meeting gered van technische frustraties.