Add build and deploy recipes for the server-rendered target
This commit is contained in:
parent
fc7c749856
commit
3b79271874
2 changed files with 44 additions and 7 deletions
20
README.md
20
README.md
|
|
@ -90,12 +90,20 @@ npm run dev -- --open
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
To create a production version of your app:
|
Two deployment targets share the same code base, selected by `PUBLIC_SSR`:
|
||||||
|
|
||||||
```sh
|
- **Static (default, `PUBLIC_SSR=no`)** — `npm run build` (or `just build`) writes a single-page bundle to `build/`; serve it from any web server with `index.html` as the fallback for unknown paths. Everything is fetched by the browser.
|
||||||
npm run build
|
- **Server-rendered (`PUBLIC_SSR=yes`)** — `just build-ssr` writes a Node app to `build/`. Pages arrive as crawlable HTML (threads, rooms, resources, contacts, with description/Open Graph tags, JSON-LD, a live `robots.txt` and `sitemap.xml`, and real 404s), then the browser takes over exactly as in the static build. The server reads the relay anonymously, so it only ever renders public content; members see their private rooms once the client is running.
|
||||||
```
|
|
||||||
|
|
||||||
You can preview the production build with `npm run preview`.
|
Preview a build locally with `npm run preview` (static) or `node --env-file=.env.production build` (server).
|
||||||
|
|
||||||
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
## Deploying
|
||||||
|
|
||||||
|
`just deploy <host>` rsyncs the static bundle to `~/squalk/` on the host and purges the Cloudflare cache.
|
||||||
|
|
||||||
|
`just deploy-ssr <host>` ships the Node build, `package.json`/`package-lock.json` and `.env.production` (as `~/squalk/.env`, since the server reads the `PUBLIC_*` values at runtime), runs `npm ci --omit=dev` and restarts the `squalk` systemd unit. On the host you need:
|
||||||
|
|
||||||
|
- Node 22 or newer (the relay client uses the built-in `WebSocket`).
|
||||||
|
- The unit from [`deploy/squalk.service`](deploy/squalk.service), with `ORIGIN` set to the public URL — it feeds canonical links, `robots.txt` and the sitemap.
|
||||||
|
- A reverse proxy (Caddy, nginx) in front of the port in `PORT`.
|
||||||
|
- If Cloudflare sits in front, a cache rule that caches HTML and respects origin headers: pages and snapshots are sent with `Cache-Control: public, max-age=0, s-maxage=300, stale-while-revalidate=3600`, so the edge serves them for five minutes and refreshes in the background for an hour after that. `just deploy-ssr` purges the cache after each release.
|
||||||
|
|
|
||||||
31
justfile
31
justfile
|
|
@ -1,8 +1,37 @@
|
||||||
|
set dotenv-load
|
||||||
|
|
||||||
|
# Cloudflare credentials (set these as environment variables)
|
||||||
|
CF_ZONE_ID := env_var_or_default("CF_ZONE_ID", "")
|
||||||
|
CF_API_TOKEN := env_var_or_default("CF_API_TOKEN", "")
|
||||||
|
CF_HOST := env_var_or_default("CF_HOST", "")
|
||||||
|
|
||||||
dev:
|
dev:
|
||||||
npm run dev
|
npm run dev
|
||||||
|
|
||||||
|
# Static single-page bundle (served by any web server)
|
||||||
build:
|
build:
|
||||||
npm run build
|
PUBLIC_SSR=no npm run build
|
||||||
|
|
||||||
|
# Server-rendered bundle (needs Node 22+ on the host, see deploy/squalk.service)
|
||||||
|
build-ssr:
|
||||||
|
PUBLIC_SSR=yes npm run build
|
||||||
|
|
||||||
deploy target: build
|
deploy target: build
|
||||||
rsync -av --delete --progress build/ {{target}}:~/squalk/
|
rsync -av --delete --progress build/ {{target}}:~/squalk/
|
||||||
|
@just purge-web-cache
|
||||||
|
|
||||||
|
# Ships the Node build plus its runtime deps and env, then restarts the unit
|
||||||
|
deploy-ssr target: build-ssr
|
||||||
|
rsync -av --delete --progress --exclude node_modules build/ {{target}}:~/squalk/build/
|
||||||
|
rsync -av package.json package-lock.json {{target}}:~/squalk/
|
||||||
|
rsync -av .env.production {{target}}:~/squalk/.env
|
||||||
|
ssh {{target}} 'cd ~/squalk && npm ci --omit=dev && sudo systemctl restart squalk'
|
||||||
|
@just purge-web-cache
|
||||||
|
|
||||||
|
purge-web-cache:
|
||||||
|
@echo "\nPurging Cloudflare cache... for zone {{CF_ZONE_ID}}"
|
||||||
|
@curl -s -X POST "https://api.cloudflare.com/client/v4/zones/{{CF_ZONE_ID}}/purge_cache" \
|
||||||
|
-H "Authorization: Bearer {{CF_API_TOKEN}}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data '{"purge_everything": true}' \
|
||||||
|
| jq -r 'if .success then "✅ Cache purged successfully" else "‼️ Error: " + (.errors[0].message // "Unknown error") end'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue