Files
Michael St.ClaireandAlexander Medvednikov 640dda22aa veb, tools: live reload over server-sent events, keeping page state (#30208)
* tools: make `v watch` build veb apps before restarting them

- Watch `templates/` and its subdirectories in veb projects. Templates are
  compiled in, but the compiler does not report them, so a change to
  `templates/layout/header.html` never triggered a rebuild.
- For veb apps, build the new executable while the old server keeps
  serving, and swap them only when the build succeeds, so the app is down
  only for the restart. A failed build leaves the old server running. A
  change during a build cancels it and starts a new one, after a 150 ms
  debounce. `--no-build-first` restores the previous behaviour.
- Write the build status (`building`, `failed` with the compiler output, or
  `ok`) to a file named by VEB_LIVERELOAD_STATUS in the app's environment,
  for veb's live reload. Print how long each build took.
- Stop the build and the program on SIGTERM and SIGHUP, as on Ctrl-C. They
  run in their own process groups, so they kept running (and kept their
  port) after `v watch` was terminated.

* veb: live reload over server-sent events, keeping page state

With `-d veb_livereload`:
- Replace the 250 ms polling with one Server-Sent Events stream per page,
  held in a shared hub (no thread per tab), capped by
  `-d veb_livereload_max_streams` (default 32). A keepalive ping every 15 s
  drops closed tabs.
- After a restart, fetch the page again and morph the DOM in place, keeping
  scroll position, focus, typed form values and page JS state. Pages from a
  POST, failed fetches and non-HTML answers reload instead.
- Follow the files of a StaticHandler: a changed stylesheet is swapped in
  place, other files update the page, with no rebuild.
- Relay the build status written by `v watch` (VEB_LIVERELOAD_STATUS): a
  toast for rebuilding/updated, and a panel with the compiler output when a
  build fails. `-d veb_livereload_no_toast` hides them.
- Reconnect every 250 ms; `-d veb_livereload_retry_max_ms` lets it back off.
- Keep the polling script behind `-d veb_livereload_polling`, for HTTPS apps
  and for proxies that block long-lived connections, with its interval set
  by `-d veb_livereload_poll_ms`. Deprecate the unused
  `Context.livereload_poll_interval_ms`, which could never be set.

* examples, docs: update the veb live reload instructions

- examples/vwatch/web_server: put `-d veb_livereload` after `watch` (the
  order before `watch` is currently dropped, see #30199), describe the new
  live reload, and drop `--only-watch=*.v,*.html,*.css,*.js`, which is the
  default for veb projects.
- v-veb skill: live reload is enabled by `-d veb_livereload` and applies to
  any HTML response ending with `</html>`, not only to `$veb.html()` in
  debug builds.
- veb blog tutorial: suggest `v watch -d veb_livereload run blog.v`, so the
  open page updates too.

* veb: reload changed scripts and page resources

* veb: preserve typed values on their original form controls

---------

Co-authored-by: Alexander Medvednikov <alexander@medvednikov.com>
2026-10-12 00:14:46 +03:00
..