refrakt_cli/dev
refrakt dev — run the app in development with rebuilds and live reload.
Sets APP_ENV=dev, builds the app and starts it with gleam run.
Then it watches src/ and priv/:
- A change under
src/rebuilds. When the build succeeds the server restarts; when it fails the compiler error is printed and the old server keeps running until the next successful build. - After a restart, or a change under
priv/(served as is), open pages reload:refrakt devruns a small Server-Sent Events server onREFRAKT_LIVE_RELOAD_PORT(35729 by default) and sends it areloadevent. The root layout’srefrakt/live_reload.script()listens to it and renders only underrefrakt devwithAPP_ENV=dev.
Files are watched with fswatch when it is installed, else with
inotifywait on Linux, else by polling every 500ms. Bursts of events
(an editor saving several files) are debounced into one rebuild.
The process work (ports, sockets, polling) lives in
refrakt_cli_dev_ffi.erl; the decisions it makes are the functions
below, so they can be unit-tested.
Types
What a batch of file changes calls for.
pub type Change {
Rebuild
ReloadOnly
NoChange
}
Constructors
-
RebuildSomething under
src/changed: rebuild and restart. -
ReloadOnlyOnly files under
priv/changed: they are served as they are, so reloading the browser is enough. -
NoChangeOnly editor scratch files changed.
How refrakt dev notices file changes.
pub type Watcher {
Fswatch(executable: String)
Inotifywait(executable: String)
Polling(interval_ms: Int)
}
Constructors
-
Fswatch(executable: String)fswatch(macOS, BSD, Linux), given its path. -
Inotifywait(executable: String)inotifywaitfrom inotify-tools (Linux), given its path. -
Polling(interval_ms: Int)Compare file sizes, times and contents every
interval_ms.
Values
pub fn changed_paths(
before: dict.Dict(String, stamp),
after: dict.Dict(String, stamp),
) -> List(String)
The paths that were added, removed or changed between two polling snapshots, sorted.
pub fn choose_watcher(
os os: String,
fswatch fswatch: Result(String, Nil),
inotifywait inotifywait: Result(String, Nil),
) -> Watcher
Prefer fswatch, then inotifywait on Linux, then polling.
pub fn classify(changes: List(#(String, String))) -> Change
Decide what a debounced batch of #(watched_dir, path) changes calls
for. Editor scratch files (swap files, backups, dotfiles) are ignored.
pub const debounce_ms: Int
How long to wait for more file events before acting on a burst.
pub const default_live_reload_port: Int
The default port of the live reload event stream.
pub fn describe_watcher(watcher: Watcher) -> String
pub fn is_relevant(path: String) -> Bool
False for files editors write while saving: dotfiles (.post.swp,
.#post.gleam), backups (post.gleam~), and vim’s 4913 probe.
pub fn live_reload_port(value: Result(String, Nil)) -> Int
The port from REFRAKT_LIVE_RELOAD_PORT, or the default when it is
unset or not a port number.
pub const poll_interval_ms: Int
How often the polling watcher compares snapshots.