Skip to content

Fix Vite asset loading on Android emulator with Herd HTTPS#129

Open
simonhamp wants to merge 2 commits into
mainfrom
fix-android-vite-https
Open

Fix Vite asset loading on Android emulator with Herd HTTPS#129
simonhamp wants to merge 2 commits into
mainfrom
fix-android-vite-https

Conversation

@simonhamp
Copy link
Copy Markdown
Member

Summary

Closes #109.

When Laravel Herd is installed, it automatically promotes the Vite dev server to HTTPS using a self-signed certificate. The Android emulator can't validate that cert, so every CSS/JS request to the dev server is rejected and the app renders unstyled.

nativephpMobile() already returned a server config pinned to the LAN IP, but laravel-vite-plugin runs with enforce: 'post' and its Herd/Valet TLS auto-detection only steps aside when userConfig.server.host / .https / .hmr are already set. Returning a partial config from our hook isn't enough — laravel-vite-plugin still overwrites our values with Herd's hostname + cert.

Changes

resources/js/vite-plugin.js:

  • Add https: false and hmr: { host: localIP, protocol: 'ws' } to the server block on both the iOS and Android branches.
  • Change the plugin's config() hook to take userConfig and Object.assign our server config onto userConfig.server before returning. Because nativephpMobile is enforce: 'pre', this lands before laravel-vite-plugin's config hook reads userConfig.server, so its fallback checks see our values and skip the Herd substitution.

Result: public/android-hot (and public/ios-hot) are written as http://<LAN-IP>:5173 and the emulator can load assets without certificate trust gymnastics. Production builds are unaffected (assets are bundled into the APK/AAB).

Considered shipping a debug network_security_config.xml with <certificates src="user"/> instead, but that still requires every developer to manually export Herd's CA, set a lock-screen PIN on the emulator, push and install the cert via Settings, and repeat for every fresh AVD — strictly worse UX than disabling HTTPS for the dev server.

Test plan

  • On a machine with Laravel Herd installed, run php artisan native:run -W android against a fresh emulator.
  • Confirm cat public/android-hot shows http://<LAN-IP>:5173 (not https://*.test:5173).
  • Confirm the app loads with CSS/JS applied and HMR works on save.
  • Run php artisan native:run -W ios and confirm iOS still loads assets and HMR.
  • Run a production build (php artisan native:build) and confirm assets are bundled correctly and the hot files are cleaned up.

🤖 Generated with Claude Code

simonhamp and others added 2 commits May 12, 2026 12:16
Laravel Herd auto-enables HTTPS on the Vite dev server using a self-signed
cert that the Android emulator can't validate, causing all CSS/JS assets
to fail to load. The laravel-vite-plugin runs with enforce: 'post' and
only honours its own Herd/Valet TLS auto-detection when userConfig.server
doesn't already declare host/https/hmr, so simply returning a partial
config from our config() hook wasn't enough — laravel-vite-plugin still
won.

Force plain HTTP + the local LAN IP for HMR by:

- Setting https: false and hmr.host/hmr.protocol in our server config for
  both the iOS and Android branches.
- Mutating userConfig.server inside the config() hook (we already run with
  enforce: 'pre') so laravel-vite-plugin's fallback checks see our values
  and skip the Herd substitution entirely.

Closes #109
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CSS fails to load on Android emulator when using Laravel Herd + solution

1 participant