dev: fix the Vite proxy and add a one-command dev runner
Running `pnpm dev` alone gave ECONNREFUSED on every request, because nothing was listening on :7788. Two separate causes: - the backend simply was not running, and - Vite bound [::1]:5173 while the proxy target was "localhost", which Node resolves to ::1 first. The Go server binds IPv4, so even with the backend up the proxy could fail before falling back. - vite.config.ts: proxy target is now 127.0.0.1 explicitly and overridable via VELLUM_API; server.host is true so both stacks are served. - scripts/dev.sh + `make dev`: builds the backend, waits for /healthz, starts Vite, and stops the backend on exit. Ctrl-C tears down both. - README documents that running Vite alone needs the backend already up.
This commit is contained in:
parent
1d7831ac10
commit
7754b0f504
4 changed files with 85 additions and 4 deletions
6
Makefile
6
Makefile
|
|
@ -7,7 +7,11 @@ BINARY := vellum
|
|||
VERSION ?= 0.4.0-dev
|
||||
LDFLAGS := -s -w -X main.version=$(VERSION)
|
||||
|
||||
.PHONY: build web run test fmt vet tidy check docker clean
|
||||
.PHONY: build web build-go dev run test fmt vet tidy check docker clean
|
||||
|
||||
# Backend + Vite dev server together, with hot reload. Ctrl-C stops both.
|
||||
dev:
|
||||
./scripts/dev.sh
|
||||
|
||||
# Build the frontend first: the Go build embeds web/dist.
|
||||
build: web
|
||||
|
|
|
|||
11
README.md
11
README.md
|
|
@ -141,9 +141,18 @@ The application never writes to `/media`.
|
|||
## Development
|
||||
|
||||
```bash
|
||||
make dev # backend + Vite dev server together, with hot reload
|
||||
make build # builds the frontend, then the Go binary with it embedded
|
||||
make build-go # Go only, when the frontend is unchanged
|
||||
make check # gofmt + vet + test
|
||||
make run # run the server on :7788
|
||||
cd web && pnpm dev # frontend dev server, proxies /api to :7788
|
||||
cd web && pnpm dev # frontend only; needs the backend running on :7788
|
||||
```
|
||||
|
||||
`make dev` is the one to reach for while developing: it builds and starts the
|
||||
backend, waits for it to answer, then starts Vite. Vite proxies `/api` to the
|
||||
backend so the browser sees a single origin and sessions behave exactly as in
|
||||
production. Ctrl-C stops both.
|
||||
|
||||
If you run Vite on its own, the backend must already be running, or every
|
||||
request fails with `ECONNREFUSED` on `:7788`.
|
||||
|
|
|
|||
61
scripts/dev.sh
Executable file
61
scripts/dev.sh
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/env bash
|
||||
# Run the backend and the Vite dev server together.
|
||||
#
|
||||
# ./scripts/dev.sh
|
||||
#
|
||||
# The Go server runs in the background; the Vite dev server runs in the
|
||||
# foreground. Ctrl-C stops both. Vite proxies /api to the Go server, so the
|
||||
# browser sees one origin and sessions behave exactly as in production.
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
# A local preview instance, so this works on a fresh clone without touching
|
||||
# your real media or your real database.
|
||||
export VELLUM_DATA_DIR="${VELLUM_DATA_DIR:-$PWD/demo/data}"
|
||||
export VELLUM_CONFIG_DIR="${VELLUM_CONFIG_DIR:-$PWD/demo/config}"
|
||||
export VELLUM_LISTEN="${VELLUM_LISTEN:-127.0.0.1:7788}"
|
||||
export VELLUM_ADMIN_USER="${VELLUM_ADMIN_USER:-admin}"
|
||||
export VELLUM_ADMIN_PASSWORD="${VELLUM_ADMIN_PASSWORD:-vellumdemo}"
|
||||
export VELLUM_LOG_LEVEL="${VELLUM_LOG_LEVEL:-info}"
|
||||
|
||||
if ! command -v go >/dev/null 2>&1; then
|
||||
export PATH="$PATH:/usr/lib/golang/bin"
|
||||
fi
|
||||
|
||||
echo "building backend..."
|
||||
CGO_ENABLED=0 go build -trimpath -o vellum ./cmd/vellum
|
||||
|
||||
echo "starting backend on ${VELLUM_LISTEN}"
|
||||
./vellum &
|
||||
BACKEND=$!
|
||||
|
||||
cleanup() {
|
||||
echo
|
||||
echo "stopping backend..."
|
||||
kill "$BACKEND" 2>/dev/null || true
|
||||
wait "$BACKEND" 2>/dev/null || true
|
||||
}
|
||||
trap cleanup EXIT INT TERM
|
||||
|
||||
# Wait for the API to answer before handing over to Vite, so the first page
|
||||
# load does not race the backend's startup.
|
||||
for _ in $(seq 1 50); do
|
||||
if curl -fsS -m 1 "http://${VELLUM_LISTEN#*:}/healthz" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
if ! kill -0 "$BACKEND" 2>/dev/null; then
|
||||
echo "backend exited during startup" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
echo
|
||||
echo "backend: http://${VELLUM_LISTEN} (${VELLUM_ADMIN_USER} / ${VELLUM_ADMIN_PASSWORD})"
|
||||
echo "frontend: http://localhost:5173"
|
||||
echo
|
||||
|
||||
cd web
|
||||
pnpm install --silent
|
||||
pnpm dev
|
||||
|
|
@ -1,6 +1,11 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import { svelte } from '@sveltejs/vite-plugin-svelte'
|
||||
|
||||
// The backend the dev server proxies to. 127.0.0.1 rather than localhost on
|
||||
// purpose: Node resolves "localhost" to ::1 first, and the Go server binds
|
||||
// IPv4, so the proxy would fail before falling back.
|
||||
const apiTarget = process.env.VELLUM_API ?? 'http://127.0.0.1:7788'
|
||||
|
||||
// The bundle is embedded into the Go binary and served from /, so all asset
|
||||
// paths must be relative (base: './').
|
||||
export default defineConfig({
|
||||
|
|
@ -13,9 +18,11 @@ export default defineConfig({
|
|||
},
|
||||
server: {
|
||||
port: 5173,
|
||||
// Listen on both stacks so a browser using either localhost works.
|
||||
host: true,
|
||||
proxy: {
|
||||
'/api': 'http://localhost:7788',
|
||||
'/healthz': 'http://localhost:7788',
|
||||
'/api': apiTarget,
|
||||
'/healthz': apiTarget,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue