Files
SFusion/doc/tutorial-development-live-reload.md
2026-05-09 13:28:22 +03:00

5.4 KiB
Raw Permalink Blame History

Tutorial — Local development and live reload

This guide explains how to work on SFusion day to day, and what kind of live reload / hot reload you can expect (and what you cannot).


1. What actually reloads?

Part of the stack Live / hot reload Notes
React + Vite (frontend/) Yes — HMR Vite pushes updated modules to the browser; state is preserved where React Fast Refresh allows it.
Vapor backend (backend/) No true hot reload Swift compiles to a native binary. Any change to server code requires rebuild + process restart. You can automate restarts with file watchers (below).
PostgreSQL schema No Fluent runs migrations when the app starts (AUTO_MIGRATE / dev). Schema changes are deliberate migration steps, not hot-patched.

So: frontend feels like live reload out of the box; backend is save → rebuild → rerun, optionally scripted.


Run three processes on the host (not inside the backend container), and only use Docker for Postgres if you want:

  1. PostgreSQLdocker compose up postgres or a local Postgres listening on 5432.
  2. Backendswift run Run from backend/, with DATABASE_* / AUTO_MIGRATE set.
  3. Frontendnpm run dev from frontend/, with Vite proxying /api to the backend.

That way you get instant HMR on the UI and incremental Swift builds between short restarts.


3. Database

Option A — Postgres in Docker

docker compose up postgres

Use the same credentials as in docker-compose.yml (defaults: user/database/password sfusion) and point the backend at localhost:5432.

Option B — Postgres installed locally

Create database and users to match your DATABASE_* environment variables.


4. Backend (Vapor / Swift)

From backend/:

export DATABASE_HOST=localhost
export DATABASE_PORT=5432
export DATABASE_USERNAME=sfusion
export DATABASE_PASSWORD=sfusion
export DATABASE_NAME=sfusion
export AUTO_MIGRATE=true

swift run Run

The server listens on 0.0.0.0:8080 by default (configure.swift).

“Live reload” for Swift means auto-restart on save

There is no Swift equivalent of Vites HMR at the HTTP layer. Practical approach: watch Sources/**/*.swift and Package.swift, then build and run again.

entr (e.g. brew install entr):

With DATABASE_* and AUTO_MIGRATE exported in your shell beforehand:

cd backend

(find Sources -name '*.swift'; echo Package.swift) | entr -r swift run Run

swift run performs an incremental build when needed and then launches Run; entr -r restarts that whole step after each tracked file change.

Note: SPM may place binaries under .build/*/debug/ depending on triple; swift run always runs the right product.

watchexec is a good cross-platform variant:

cd backend
watchexec -e swift -w Sources -w Package.swift --restart -- swift run Run

(Export the same DATABASE_* and AUTO_MIGRATE in your shell.)

IDE

Opening backend/Package.swift in Xcode (or similar) gives incremental builds plus one-click Run; restarting the debugger is still the “reload.”


5. Frontend — real hot module replacement

From frontend/:

npm install
export VITE_API_PROXY_TARGET=http://127.0.0.1:8080
npm run dev

Open http://localhost:5173. Edits under frontend/src update in the browser via Vite HMR.

vite.config.ts proxies /api to VITE_API_PROXY_TARGET; keep that URL pointed at whichever host runs Vapor (127.0.0.1:8080 when the backend runs on your machine).


6. All-in-docker vs hybrid

Full docker compose up

When the frontend service bind-mounts ./frontend, npm run dev in the container still supports Vite HMR: the browser talks to the mapped port (5173), and edits on disk sync through the volume.

Changing Swift in backend/ requires rebuilding the backend image (e.g. docker compose build backend or up --build). There is no hot reload inside the Swift container unless you add your own watcher and dev image.

Service Where to run
Postgres Docker Compose or native
Backend cd backend && swift run Run (optionally entr/watchexec)
Frontend cd frontend && npm run dev with proxy → http://127.0.0.1:8080

7. Environment quick reference

Variable Typical local value
DATABASE_HOST localhost
DATABASE_PORT 5432
DATABASE_USERNAME / DATABASE_PASSWORD / DATABASE_NAME sfusion (match docker-compose.yml)
AUTO_MIGRATE true in development
VITE_API_PROXY_TARGET http://127.0.0.1:8080
PORT 8080 (backend)

Inside Dockers backend service, DATABASE_HOST is postgres; on the Mac host it must be localhost.


8. Summary

  • Treat frontend development as Vite HMR.
  • Treat backend development as recompile + rerun, optionally wrapped with entr or watchexec.
  • For the fastest iteration across layers, prefer Docker or local Postgres + local Swift + local Vite over rebuilding the Swift image on every tweak.